This commit is contained in:
2026-09-18 03:24:01 +07:00
parent f8a4ca0f55
commit fc171dace5
9 changed files with 547 additions and 288 deletions
+15
View File
@@ -695,6 +695,17 @@ service EveningDetectiveServer {
};
}
rpc GetScenarioReviews(GetScenarioReviewsReq) returns (GetGameReviewsRsp) {
option (google.api.http) = {
get: "/api/scenarios/{scenarioId}/reviews"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
security: { security_requirement: {} }
tags: "Отзывы"
summary: "Получить отзывы сценария"
};
}
rpc GetGameReviewsForModeration(GetGameReviewsReq) returns (GetGameReviewsRsp) {
option (google.api.http) = {
get: "/api/admin/games/{gameId}/reviews"
@@ -1654,6 +1665,10 @@ message GetGameReviewsReq {
int32 gameId = 1;
}
message GetScenarioReviewsReq {
int32 scenarioId = 1;
}
message GetReviewsForModerationReq {}
message GetGameReviewsRsp {
Binary file not shown.
@@ -1915,6 +1915,43 @@
]
}
},
"/api/scenarios/{scenarioId}/reviews": {
"get": {
"summary": "Получить отзывы сценария",
"operationId": "EveningDetectiveServer_GetScenarioReviews",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverGetGameReviewsRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "scenarioId",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}
],
"tags": [
"Отзывы"
],
"security": [
{
"": []
}
]
}
},
"/api/screens": {
"post": {
"summary": "Создать сессию экрана",
+8
View File
@@ -40,6 +40,14 @@ func (s *server) GetGameReviews(ctx context.Context, req *proto.GetGameReviewsRe
return &proto.GetGameReviewsRsp{AverageRating: average, ReviewsCount: count, Reviews: mapGameReviews(reviews)}, nil
}
func (s *server) GetScenarioReviews(ctx context.Context, req *proto.GetScenarioReviewsReq) (*proto.GetGameReviewsRsp, error) {
reviews, average, count, err := s.reviewService.ListByScenario(ctx, int(req.ScenarioId))
if err != nil {
return &proto.GetGameReviewsRsp{Error: err.Error()}, nil
}
return &proto.GetGameReviewsRsp{AverageRating: average, ReviewsCount: count, Reviews: mapGameReviews(reviews)}, nil
}
func (s *server) GetGameReviewsForModeration(ctx context.Context, req *proto.GetGameReviewsReq) (*proto.GetGameReviewsRsp, error) {
claims := ctx.Value("claims").(*processor_jwt.JWTClaims)
if !roles.HasRole(claims, roles.Admin) {
+24
View File
@@ -128,6 +128,30 @@ func (r *Repo) ScenarioRating(ctx context.Context, scenarioID int) (float64, int
return average, int32(count), err
}
func (r *Repo) ListByScenario(ctx context.Context, scenarioID int) ([]*Review, float64, int32, error) {
rows, err := r.pool.Query(ctx, `SELECT r.id,r.game_id,r.team_id,t.name,g.name,r.rating,r.text,r.status,r.created_at
FROM game_reviews r JOIN teams t ON t.id=r.team_id JOIN games g ON g.id=r.game_id
WHERE g.scenario_id=$1 AND g.status='finish' AND r.status='approved'
ORDER BY r.created_at DESC`, scenarioID)
if err != nil {
return nil, 0, 0, err
}
defer rows.Close()
var reviews []*Review
for rows.Next() {
review := &Review{}
if err := rows.Scan(&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Text, &review.Status, &review.CreatedAt); err != nil {
return nil, 0, 0, err
}
reviews = append(reviews, review)
}
if err := rows.Err(); err != nil {
return nil, 0, 0, err
}
average, count, err := r.ScenarioRating(ctx, scenarioID)
return reviews, average, count, err
}
func (r *Repo) queryOne(ctx context.Context, condition string, id int) (*Review, error) {
review := &Review{}
err := r.pool.QueryRow(ctx, `SELECT r.id,r.game_id,r.team_id,t.name,g.name,r.rating,r.text,r.status,r.created_at
@@ -70,6 +70,10 @@ func (s *Service) ScenarioRating(ctx context.Context, scenarioID int) (float64,
return s.reviews.ScenarioRating(ctx, scenarioID)
}
func (s *Service) ListByScenario(ctx context.Context, scenarioID int) ([]*game_reviews_repo.Review, float64, int32, error) {
return s.reviews.ListByScenario(ctx, scenarioID)
}
func reviewReminderEmail(job *teams_repo.ReviewReminder, baseURL string) email_sender.Message {
link := strings.TrimRight(baseURL, "/") + "/team-story/" + fmt.Sprint(job.TeamID) + "?" + url.Values{"password": {job.Password}, "review": {"1"}}.Encode()
body := fmt.Sprintf("Команда «%s», поделитесь впечатлениями об игре «%s».\n\nОценка и отзыв займут пару минут: %s\n\nОтзыв можно оставить один раз от команды.", job.TeamName, job.GameName, link)
+343 -288
View File
File diff suppressed because it is too large Load Diff
+78
View File
@@ -2234,6 +2234,45 @@ func local_request_EveningDetectiveServer_GetGameReviews_0(ctx context.Context,
return msg, metadata, err
}
func request_EveningDetectiveServer_GetScenarioReviews_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetScenarioReviewsReq
metadata runtime.ServerMetadata
err error
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["scenarioId"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "scenarioId")
}
protoReq.ScenarioId, err = runtime.Int32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "scenarioId", err)
}
msg, err := client.GetScenarioReviews(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_EveningDetectiveServer_GetScenarioReviews_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetScenarioReviewsReq
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["scenarioId"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "scenarioId")
}
protoReq.ScenarioId, err = runtime.Int32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "scenarioId", err)
}
msg, err := server.GetScenarioReviews(ctx, &protoReq)
return msg, metadata, err
}
func request_EveningDetectiveServer_GetGameReviewsForModeration_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetGameReviewsReq
@@ -4306,6 +4345,26 @@ func RegisterEveningDetectiveServerHandlerServer(ctx context.Context, mux *runti
}
forward_EveningDetectiveServer_GetGameReviews_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetScenarioReviews_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetScenarioReviews", runtime.WithHTTPPathPattern("/api/scenarios/{scenarioId}/reviews"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_EveningDetectiveServer_GetScenarioReviews_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_EveningDetectiveServer_GetScenarioReviews_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetGameReviewsForModeration_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -5766,6 +5825,23 @@ func RegisterEveningDetectiveServerHandlerClient(ctx context.Context, mux *runti
}
forward_EveningDetectiveServer_GetGameReviews_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetScenarioReviews_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetScenarioReviews", runtime.WithHTTPPathPattern("/api/scenarios/{scenarioId}/reviews"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_EveningDetectiveServer_GetScenarioReviews_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_EveningDetectiveServer_GetScenarioReviews_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetGameReviewsForModeration_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -6170,6 +6246,7 @@ var (
pattern_EveningDetectiveServer_GetGameResults_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"api", "games", "gameId", "results"}, ""))
pattern_EveningDetectiveServer_CreateGameReview_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"api", "games", "gameId", "reviews"}, ""))
pattern_EveningDetectiveServer_GetGameReviews_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"api", "games", "gameId", "reviews"}, ""))
pattern_EveningDetectiveServer_GetScenarioReviews_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"api", "scenarios", "scenarioId", "reviews"}, ""))
pattern_EveningDetectiveServer_GetGameReviewsForModeration_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "admin", "games", "gameId", "reviews"}, ""))
pattern_EveningDetectiveServer_GetReviewsForModeration_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "admin", "game-reviews"}, ""))
pattern_EveningDetectiveServer_ModerateGameReview_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "admin", "game-reviews", "id"}, ""))
@@ -6253,6 +6330,7 @@ var (
forward_EveningDetectiveServer_GetGameResults_0 = runtime.ForwardResponseMessage
forward_EveningDetectiveServer_CreateGameReview_0 = runtime.ForwardResponseMessage
forward_EveningDetectiveServer_GetGameReviews_0 = runtime.ForwardResponseMessage
forward_EveningDetectiveServer_GetScenarioReviews_0 = runtime.ForwardResponseMessage
forward_EveningDetectiveServer_GetGameReviewsForModeration_0 = runtime.ForwardResponseMessage
forward_EveningDetectiveServer_GetReviewsForModeration_0 = runtime.ForwardResponseMessage
forward_EveningDetectiveServer_ModerateGameReview_0 = runtime.ForwardResponseMessage
+38
View File
@@ -80,6 +80,7 @@ const (
EveningDetectiveServer_GetGameResults_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetGameResults"
EveningDetectiveServer_CreateGameReview_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/CreateGameReview"
EveningDetectiveServer_GetGameReviews_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetGameReviews"
EveningDetectiveServer_GetScenarioReviews_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetScenarioReviews"
EveningDetectiveServer_GetGameReviewsForModeration_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetGameReviewsForModeration"
EveningDetectiveServer_GetReviewsForModeration_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetReviewsForModeration"
EveningDetectiveServer_ModerateGameReview_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/ModerateGameReview"
@@ -176,6 +177,7 @@ type EveningDetectiveServerClient interface {
GetGameResults(ctx context.Context, in *GetGameResultsReq, opts ...grpc.CallOption) (*GetGameResultsRsp, error)
CreateGameReview(ctx context.Context, in *CreateGameReviewReq, opts ...grpc.CallOption) (*CreateGameReviewRsp, error)
GetGameReviews(ctx context.Context, in *GetGameReviewsReq, opts ...grpc.CallOption) (*GetGameReviewsRsp, error)
GetScenarioReviews(ctx context.Context, in *GetScenarioReviewsReq, opts ...grpc.CallOption) (*GetGameReviewsRsp, error)
GetGameReviewsForModeration(ctx context.Context, in *GetGameReviewsReq, opts ...grpc.CallOption) (*GetGameReviewsRsp, error)
GetReviewsForModeration(ctx context.Context, in *GetReviewsForModerationReq, opts ...grpc.CallOption) (*GetGameReviewsRsp, error)
ModerateGameReview(ctx context.Context, in *ModerateGameReviewReq, opts ...grpc.CallOption) (*ModerateGameReviewRsp, error)
@@ -806,6 +808,16 @@ func (c *eveningDetectiveServerClient) GetGameReviews(ctx context.Context, in *G
return out, nil
}
func (c *eveningDetectiveServerClient) GetScenarioReviews(ctx context.Context, in *GetScenarioReviewsReq, opts ...grpc.CallOption) (*GetGameReviewsRsp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetGameReviewsRsp)
err := c.cc.Invoke(ctx, EveningDetectiveServer_GetScenarioReviews_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *eveningDetectiveServerClient) GetGameReviewsForModeration(ctx context.Context, in *GetGameReviewsReq, opts ...grpc.CallOption) (*GetGameReviewsRsp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetGameReviewsRsp)
@@ -1080,6 +1092,7 @@ type EveningDetectiveServerServer interface {
GetGameResults(context.Context, *GetGameResultsReq) (*GetGameResultsRsp, error)
CreateGameReview(context.Context, *CreateGameReviewReq) (*CreateGameReviewRsp, error)
GetGameReviews(context.Context, *GetGameReviewsReq) (*GetGameReviewsRsp, error)
GetScenarioReviews(context.Context, *GetScenarioReviewsReq) (*GetGameReviewsRsp, error)
GetGameReviewsForModeration(context.Context, *GetGameReviewsReq) (*GetGameReviewsRsp, error)
GetReviewsForModeration(context.Context, *GetReviewsForModerationReq) (*GetGameReviewsRsp, error)
ModerateGameReview(context.Context, *ModerateGameReviewReq) (*ModerateGameReviewRsp, error)
@@ -1290,6 +1303,9 @@ func (UnimplementedEveningDetectiveServerServer) CreateGameReview(context.Contex
func (UnimplementedEveningDetectiveServerServer) GetGameReviews(context.Context, *GetGameReviewsReq) (*GetGameReviewsRsp, error) {
return nil, status.Error(codes.Unimplemented, "method GetGameReviews not implemented")
}
func (UnimplementedEveningDetectiveServerServer) GetScenarioReviews(context.Context, *GetScenarioReviewsReq) (*GetGameReviewsRsp, error) {
return nil, status.Error(codes.Unimplemented, "method GetScenarioReviews not implemented")
}
func (UnimplementedEveningDetectiveServerServer) GetGameReviewsForModeration(context.Context, *GetGameReviewsReq) (*GetGameReviewsRsp, error) {
return nil, status.Error(codes.Unimplemented, "method GetGameReviewsForModeration not implemented")
}
@@ -2452,6 +2468,24 @@ func _EveningDetectiveServer_GetGameReviews_Handler(srv interface{}, ctx context
return interceptor(ctx, in, info, handler)
}
func _EveningDetectiveServer_GetScenarioReviews_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetScenarioReviewsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EveningDetectiveServerServer).GetScenarioReviews(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EveningDetectiveServer_GetScenarioReviews_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EveningDetectiveServerServer).GetScenarioReviews(ctx, req.(*GetScenarioReviewsReq))
}
return interceptor(ctx, in, info, handler)
}
func _EveningDetectiveServer_GetGameReviewsForModeration_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetGameReviewsReq)
if err := dec(in); err != nil {
@@ -3059,6 +3093,10 @@ var EveningDetectiveServer_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetGameReviews",
Handler: _EveningDetectiveServer_GetGameReviews_Handler,
},
{
MethodName: "GetScenarioReviews",
Handler: _EveningDetectiveServer_GetScenarioReviews_Handler,
},
{
MethodName: "GetGameReviewsForModeration",
Handler: _EveningDetectiveServer_GetGameReviewsForModeration_Handler,