generated from VLADIMIR/template
add sound screen
This commit is contained in:
+49
-4
@@ -9,6 +9,7 @@ import (
|
||||
"net/netip"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"evening_detective_server/docs"
|
||||
"evening_detective_server/internal/modules/file_storage"
|
||||
@@ -93,6 +94,27 @@ func (s *server) GetScreenState(ctx context.Context, req *proto.GetScreenStateRe
|
||||
return &proto.GetScreenStateRsp{State: screenState(session)}, nil
|
||||
}
|
||||
|
||||
func (s *server) GetGameScreens(ctx context.Context, req *proto.GetGameScreensReq) (*proto.GetGameScreensRsp, error) {
|
||||
if !canManageScreens(ctx) {
|
||||
return nil, status.Error(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
if req == nil || req.GameId <= 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "некорректный идентификатор игры")
|
||||
}
|
||||
if _, err := s.gameService.GetGame(ctx, int(req.GameId)); err != nil {
|
||||
return nil, status.Error(codes.NotFound, "игра не найдена")
|
||||
}
|
||||
sessions, err := s.screenRepo.ListByGame(ctx, int(req.GameId))
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "не удалось получить экраны игры")
|
||||
}
|
||||
states := make([]*proto.ScreenState, 0, len(sessions))
|
||||
for _, session := range sessions {
|
||||
states = append(states, screenState(session))
|
||||
}
|
||||
return &proto.GetGameScreensRsp{Screens: states}, nil
|
||||
}
|
||||
|
||||
func (s *server) BindScreen(ctx context.Context, req *proto.BindScreenReq) (*proto.BindScreenRsp, error) {
|
||||
if !canManageScreens(ctx) {
|
||||
return nil, status.Error(codes.PermissionDenied, "permission denied")
|
||||
@@ -141,6 +163,26 @@ func (s *server) UnbindScreen(ctx context.Context, req *proto.UnbindScreenReq) (
|
||||
return &proto.UnbindScreenRsp{}, nil
|
||||
}
|
||||
|
||||
func (s *server) SetScreenSound(ctx context.Context, req *proto.SetScreenSoundReq) (*proto.SetScreenSoundRsp, error) {
|
||||
if !canManageScreens(ctx) {
|
||||
return nil, status.Error(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
if req == nil || req.ScreenId == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "некорректный идентификатор экрана")
|
||||
}
|
||||
id, err := strconv.Atoi(req.ScreenId)
|
||||
if err != nil || id <= 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "некорректный идентификатор экрана")
|
||||
}
|
||||
if err = s.screenRepo.SetSound(ctx, id, req.SoundEnabled); err != nil {
|
||||
if errors.Is(err, screen_sessions_repo.ErrScreenNotFound) {
|
||||
return nil, status.Error(codes.NotFound, "экран не найден")
|
||||
}
|
||||
return nil, status.Error(codes.Internal, "не удалось назначить экран со звуком")
|
||||
}
|
||||
return &proto.SetScreenSoundRsp{}, nil
|
||||
}
|
||||
|
||||
func canManageScreens(ctx context.Context) bool {
|
||||
claims, ok := ctx.Value("claims").(*processor_jwt.JWTClaims)
|
||||
if !ok || claims == nil {
|
||||
@@ -156,14 +198,17 @@ func hashScreenToken(token string) string {
|
||||
|
||||
func screenState(session *screen_sessions_repo.ScreenSession) *proto.ScreenState {
|
||||
state := &proto.ScreenState{
|
||||
Id: fmt.Sprint(session.ID),
|
||||
Status: "waiting",
|
||||
Mode: proto.ScreenMode_SCREEN_MODE_UNSPECIFIED,
|
||||
Id: fmt.Sprint(session.ID),
|
||||
Status: "disconnected",
|
||||
SoundEnabled: session.Sound,
|
||||
Mode: proto.ScreenMode_SCREEN_MODE_UNSPECIFIED,
|
||||
}
|
||||
if time.Since(session.LastSeen) <= 5*time.Second {
|
||||
state.Status = "connected"
|
||||
}
|
||||
if session.GameID != nil {
|
||||
gameID := int32(*session.GameID)
|
||||
state.GameId = &gameID
|
||||
state.Status = "bound"
|
||||
state.Mode = proto.ScreenMode_SCREEN_MODE_COVER
|
||||
}
|
||||
return state
|
||||
|
||||
@@ -3,6 +3,7 @@ package screen_sessions_repo
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
@@ -11,8 +12,10 @@ import (
|
||||
var ErrScreenNotFound = errors.New("Экран не найден")
|
||||
|
||||
type ScreenSession struct {
|
||||
ID int
|
||||
GameID *int
|
||||
ID int
|
||||
GameID *int
|
||||
Sound bool
|
||||
LastSeen time.Time
|
||||
}
|
||||
|
||||
type ScreenSessionsRepo struct {
|
||||
@@ -35,19 +38,46 @@ func (r *ScreenSessionsRepo) Create(ctx context.Context, tokenHash string) (int,
|
||||
func (r *ScreenSessionsRepo) Get(ctx context.Context, id int, tokenHash string) (*ScreenSession, error) {
|
||||
session := &ScreenSession{ID: id}
|
||||
err := r.pool.QueryRow(ctx, `
|
||||
SELECT game_id
|
||||
SELECT game_id, sound_enabled, last_seen_at
|
||||
FROM screen_sessions
|
||||
WHERE id = $1 AND access_token_hash = $2`, id, tokenHash).
|
||||
Scan(&session.GameID)
|
||||
Scan(&session.GameID, &session.Sound, &session.LastSeen)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrScreenNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.pool.Exec(ctx, `UPDATE screen_sessions SET last_seen_at = NOW() WHERE id = $1`, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
session.LastSeen = time.Now()
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (r *ScreenSessionsRepo) ListByGame(ctx context.Context, gameID int) ([]*ScreenSession, error) {
|
||||
rows, err := r.pool.Query(ctx, `
|
||||
SELECT id, game_id, sound_enabled, last_seen_at
|
||||
FROM screen_sessions
|
||||
WHERE game_id = $1
|
||||
ORDER BY id`, gameID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var sessions []*ScreenSession
|
||||
for rows.Next() {
|
||||
session := &ScreenSession{}
|
||||
if err := rows.Scan(&session.ID, &session.GameID, &session.Sound, &session.LastSeen); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sessions = append(sessions, session)
|
||||
}
|
||||
return sessions, rows.Err()
|
||||
}
|
||||
|
||||
func (r *ScreenSessionsRepo) Bind(ctx context.Context, id, gameID int, tokenHash string) error {
|
||||
result, err := r.pool.Exec(ctx, `
|
||||
UPDATE screen_sessions
|
||||
@@ -75,3 +105,21 @@ func (r *ScreenSessionsRepo) Unbind(ctx context.Context, id int) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ScreenSessionsRepo) SetSound(ctx context.Context, id int, enabled bool) error {
|
||||
query := `UPDATE screen_sessions SET sound_enabled = FALSE, updated_at = NOW() WHERE id = $1`
|
||||
args := []any{id}
|
||||
if enabled {
|
||||
query = `UPDATE screen_sessions
|
||||
SET sound_enabled = (id = $1), updated_at = NOW()
|
||||
WHERE game_id = (SELECT game_id FROM screen_sessions WHERE id = $1)`
|
||||
}
|
||||
result, err := r.pool.Exec(ctx, query, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if result.RowsAffected() == 0 {
|
||||
return ErrScreenNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user