generated from VLADIMIR/template
up
This commit is contained in:
@@ -13,12 +13,13 @@ func playlistErrorStatus(err error, fallback string) error {
|
||||
case errors.Is(err, playlist_service.ErrInvalidName),
|
||||
errors.Is(err, playlist_service.ErrInvalidTrack):
|
||||
return status.Error(codes.InvalidArgument, err.Error())
|
||||
case errors.Is(err, playlist_service.ErrPlaylistNotFound),
|
||||
case errors.Is(err, playlist_service.ErrGroupNotFound),
|
||||
errors.Is(err, playlist_service.ErrPlaylistNotFound),
|
||||
errors.Is(err, playlist_service.ErrTrackNotFound),
|
||||
errors.Is(err, playlist_service.ErrGameNotFound),
|
||||
errors.Is(err, playlist_service.ErrScenarioNotFound):
|
||||
return status.Error(codes.NotFound, err.Error())
|
||||
case errors.Is(err, playlist_service.ErrTrackOrderChanged):
|
||||
case errors.Is(err, playlist_service.ErrTrackOrderChanged), errors.Is(err, playlist_service.ErrGroupOrderChanged):
|
||||
return status.Error(codes.Aborted, err.Error())
|
||||
case errors.Is(err, playlist_service.ErrPlaylistInUse):
|
||||
return status.Error(codes.FailedPrecondition, err.Error())
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
proto "evening_detective_server/proto"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func (s *server) SavePlaylistGroup(ctx context.Context, req *proto.SavePlaylistGroupReq) (*proto.SavePlaylistGroupRsp, error) {
|
||||
if !canManagePlaylists(ctx) {
|
||||
return nil, status.Error(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
var mode string
|
||||
switch req.GetEndMode() {
|
||||
case proto.PlaylistGroupEndMode_PLAYLIST_GROUP_END_MODE_REPEAT:
|
||||
mode = "repeat"
|
||||
case proto.PlaylistGroupEndMode_PLAYLIST_GROUP_END_MODE_STOP:
|
||||
mode = "stop"
|
||||
case proto.PlaylistGroupEndMode_PLAYLIST_GROUP_END_MODE_NEXT:
|
||||
mode = "next"
|
||||
default:
|
||||
return nil, status.Error(codes.InvalidArgument, "некорректный режим завершения группы")
|
||||
}
|
||||
item, err := s.playlistService.SaveGroup(ctx, int(req.GetPlaylistID()), int(req.GetGroupID()), req.GetName(), mode)
|
||||
if err != nil {
|
||||
return nil, playlistErrorStatus(err, "не удалось сохранить группу")
|
||||
}
|
||||
return &proto.SavePlaylistGroupRsp{Playlist: mapPlaylist(item)}, nil
|
||||
}
|
||||
|
||||
func (s *server) DeletePlaylistGroup(ctx context.Context, req *proto.DeletePlaylistGroupReq) (*proto.DeletePlaylistGroupRsp, error) {
|
||||
if !canManagePlaylists(ctx) {
|
||||
return nil, status.Error(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
item, err := s.playlistService.DeleteGroup(ctx, int(req.GetPlaylistID()), int(req.GetGroupID()))
|
||||
if err != nil {
|
||||
return nil, playlistErrorStatus(err, "не удалось удалить группу")
|
||||
}
|
||||
return &proto.DeletePlaylistGroupRsp{Playlist: mapPlaylist(item)}, nil
|
||||
}
|
||||
|
||||
func (s *server) ReorderPlaylistGroups(ctx context.Context, req *proto.ReorderPlaylistGroupsReq) (*proto.ReorderPlaylistGroupsRsp, error) {
|
||||
if !canManagePlaylists(ctx) {
|
||||
return nil, status.Error(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
ids := make([]int, len(req.GetGroupIDs()))
|
||||
for i, id := range req.GetGroupIDs() {
|
||||
ids[i] = int(id)
|
||||
}
|
||||
item, err := s.playlistService.ReorderGroups(ctx, int(req.GetPlaylistID()), ids)
|
||||
if err != nil {
|
||||
return nil, playlistErrorStatus(err, "не удалось изменить порядок групп")
|
||||
}
|
||||
return &proto.ReorderPlaylistGroupsRsp{Playlist: mapPlaylist(item)}, nil
|
||||
}
|
||||
|
||||
func (s *server) SetPlaylistTrackGroup(ctx context.Context, req *proto.SetPlaylistTrackGroupReq) (*proto.SetPlaylistTrackGroupRsp, error) {
|
||||
if !canManagePlaylists(ctx) {
|
||||
return nil, status.Error(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
item, err := s.playlistService.SetTrackGroup(ctx, int(req.GetPlaylistID()), int(req.GetTrackID()), int(req.GetGroupID()))
|
||||
if err != nil {
|
||||
return nil, playlistErrorStatus(err, "не удалось изменить группу трека")
|
||||
}
|
||||
return &proto.SetPlaylistTrackGroupRsp{Playlist: mapPlaylist(item)}, nil
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
proto "evening_detective_server/proto"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func TestPlaylistGroupsRequireManagementRights(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
call func(*server, context.Context) error
|
||||
}{
|
||||
{"save", func(s *server, ctx context.Context) error {
|
||||
_, err := s.SavePlaylistGroup(ctx, &proto.SavePlaylistGroupReq{})
|
||||
return err
|
||||
}},
|
||||
{"delete", func(s *server, ctx context.Context) error {
|
||||
_, err := s.DeletePlaylistGroup(ctx, &proto.DeletePlaylistGroupReq{})
|
||||
return err
|
||||
}},
|
||||
{"order", func(s *server, ctx context.Context) error {
|
||||
_, err := s.ReorderPlaylistGroups(ctx, &proto.ReorderPlaylistGroupsReq{})
|
||||
return err
|
||||
}},
|
||||
{"track", func(s *server, ctx context.Context) error {
|
||||
_, err := s.SetPlaylistTrackGroup(ctx, &proto.SetPlaylistTrackGroupReq{})
|
||||
return err
|
||||
}},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
for _, ctx := range []context.Context{context.Background(), ctxWithClaims("user")} {
|
||||
if err := tc.call(&server{}, ctx); status.Code(err) != codes.PermissionDenied {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSavePlaylistGroupRejectsUnknownMode(t *testing.T) {
|
||||
for _, mode := range []proto.PlaylistGroupEndMode{-1, 99} {
|
||||
t.Run(mode.String(), func(t *testing.T) {
|
||||
_, err := (&server{}).SavePlaylistGroup(ctxWithClaims("organizer"), &proto.SavePlaylistGroupReq{EndMode: mode})
|
||||
if status.Code(err) != codes.InvalidArgument {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,10 @@ func TestPlaylistOrderErrorCodes(t *testing.T) {
|
||||
}{
|
||||
{"invalid", playlist_service.ErrInvalidTrack, codes.InvalidArgument},
|
||||
{"conflict", playlist_service.ErrTrackOrderChanged, codes.Aborted},
|
||||
{"group conflict", playlist_service.ErrGroupOrderChanged, codes.Aborted},
|
||||
{"missing", playlist_service.ErrPlaylistNotFound, codes.NotFound},
|
||||
{"missing group", playlist_service.ErrGroupNotFound, codes.NotFound},
|
||||
{"active group", playlist_service.ErrPlaylistInUse, codes.FailedPrecondition},
|
||||
{"internal", errors.New("secret SQL"), codes.Internal},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -153,6 +153,7 @@ func (s *server) SetGameMusic(ctx context.Context, req *proto.SetGameMusicReq) (
|
||||
req.GetVolume(),
|
||||
req.GetLoop(),
|
||||
int32(req.GetPlayback()),
|
||||
int(req.GetGroupId()),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, playlistErrorStatus(err, "не удалось изменить музыку игры")
|
||||
|
||||
@@ -19,8 +19,12 @@ func mapPlaylist(value *playlist_service.Playlist) *proto.Playlist {
|
||||
Name: track.Name,
|
||||
Filename: track.Filename,
|
||||
Position: int32(track.Position),
|
||||
GroupId: int32(track.GroupID),
|
||||
})
|
||||
}
|
||||
for _, group := range value.Groups {
|
||||
result.Groups = append(result.Groups, &proto.PlaylistGroup{ID: int32(group.ID), Name: group.Name, Position: int32(group.Position), EndMode: mapGroupEndMode(group.EndMode)})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -31,6 +35,7 @@ func mapMusicState(value *playlist_service.MusicState) *proto.MusicState {
|
||||
return &proto.MusicState{
|
||||
Playlist: mapPlaylist(value.Playlist),
|
||||
TrackIndex: int32(value.TrackIndex),
|
||||
GroupId: int32(value.GroupID),
|
||||
PositionMs: value.PositionMs,
|
||||
Volume: value.Volume,
|
||||
Loop: value.Loop,
|
||||
@@ -38,3 +43,14 @@ func mapMusicState(value *playlist_service.MusicState) *proto.MusicState {
|
||||
StateVersion: value.Version,
|
||||
}
|
||||
}
|
||||
|
||||
func mapGroupEndMode(mode string) proto.PlaylistGroupEndMode {
|
||||
switch mode {
|
||||
case "stop":
|
||||
return proto.PlaylistGroupEndMode_PLAYLIST_GROUP_END_MODE_STOP
|
||||
case "next":
|
||||
return proto.PlaylistGroupEndMode_PLAYLIST_GROUP_END_MODE_NEXT
|
||||
default:
|
||||
return proto.PlaylistGroupEndMode_PLAYLIST_GROUP_END_MODE_REPEAT
|
||||
}
|
||||
}
|
||||
|
||||
+4
-15
@@ -64,23 +64,12 @@ func (s *server) AdvanceScreenMusic(ctx context.Context, req *proto.AdvanceScree
|
||||
if err != nil || session.GameID == nil {
|
||||
return nil, status.Error(codes.FailedPrecondition, "экран не привязан к игре")
|
||||
}
|
||||
state, err := s.playlistService.GetGame(ctx, *session.GameID)
|
||||
if err != nil || state.Playlist == nil || len(state.Playlist.Tracks) == 0 {
|
||||
return &proto.AdvanceScreenMusicRsp{State: mapMusicState(state)}, nil
|
||||
if !session.Sound {
|
||||
return nil, status.Error(codes.FailedPrecondition, "экран не назначен для звука")
|
||||
}
|
||||
next := state.TrackIndex + 1
|
||||
playback := state.Playback
|
||||
if next >= len(state.Playlist.Tracks) {
|
||||
if state.Loop {
|
||||
next = 0
|
||||
} else {
|
||||
next = len(state.Playlist.Tracks) - 1
|
||||
playback = 1
|
||||
}
|
||||
}
|
||||
updated, err := s.playlistService.SetGame(ctx, *session.GameID, state.Playlist.ID, next, 0, state.Volume, state.Loop, playback)
|
||||
updated, err := s.playlistService.Advance(ctx, *session.GameID, req.GetExpectedStateVersion())
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "не удалось переключить трек")
|
||||
return nil, playlistErrorStatus(err, "не удалось переключить трек")
|
||||
}
|
||||
return &proto.AdvanceScreenMusicRsp{State: mapMusicState(updated)}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user