This commit is contained in:
2026-09-16 02:44:44 +07:00
parent 27db2067e3
commit 0e42278b36
25 changed files with 1781 additions and 424 deletions
+4
View File
@@ -148,6 +148,8 @@ func main() {
os.Getenv("APP_BASE_URL"),
)
go gameService.RunParticipationEmails(context.Background(), emailSender, os.Getenv("PARTICIPATION_SECRET"), os.Getenv("GAME_TIMEZONE"))
// Create a listener on TCP port
lis, err := net.Listen("tcp", ":8080")
if err != nil {
@@ -160,6 +162,8 @@ func main() {
grpc.UnaryInterceptor(
processor_jwt.NewAuthorizationInterceptor(
map[string]bool{
"/crabs.evening_detective_server.EveningDetectiveServer/GetParticipation": true,
"/crabs.evening_detective_server.EveningDetectiveServer/AnswerParticipation": true,
"/crabs.evening_detective_server.EveningDetectiveServer/Ping": true,
"/crabs.evening_detective_server.EveningDetectiveServer/Echo": true,
"/crabs.evening_detective_server.EveningDetectiveServer/Signup": true,
@@ -972,6 +972,76 @@
]
}
},
"/api/participation/answer": {
"post": {
"summary": "Подтвердить или отменить участие",
"description": "Принимает окончательный ответ капитана: confirmed или cancelled. Авторизация JWT не требуется; доступ определяется персональным токеном. Первый ответ сохраняется, повтор того же ответа успешен, противоположный ответ отклоняется. Новый ответ принимается только до планового начала игры и пока игра имеет статус draft. Ошибки ссылки, значения answer, закрытого приёма или изменения решения возвращаются в поле error при HTTP 200; при уже принятом решении возвращается его текущее состояние.",
"operationId": "EveningDetectiveServer_AnswerParticipation",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverParticipationRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/evening_detective_serverAnswerParticipationReq"
}
}
],
"tags": [
"Подтверждение участия"
],
"security": []
}
},
"/api/participation/get": {
"post": {
"summary": "Получить состояние участия",
"description": "Возвращает команду, игру и текущее решение по персональному токену из письма. Авторизация JWT не требуется. Чтение не меняет статус участия. Токен передаётся в теле запроса. Недействительная ссылка и ошибки обработки возвращаются в поле error при HTTP 200.",
"operationId": "EveningDetectiveServer_GetParticipation",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverParticipationRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/evening_detective_serverGetParticipationReq"
}
}
],
"tags": [
"Подтверждение участия"
],
"security": []
}
},
"/api/privacy": {
"get": {
"summary": "Получить текст Политики конфиденциальности",
@@ -3004,6 +3074,19 @@
},
"title": "Ответ команды на вопрос дела"
},
"evening_detective_serverAnswerParticipationReq": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "Персональный токен из письма: 64 шестнадцатеричных символа. Не является JWT."
},
"answer": {
"type": "string",
"description": "Окончательное решение: confirmed — участвуем, cancelled — отменяем запись."
}
}
},
"evening_detective_serverAnswerScore": {
"type": "object",
"properties": {
@@ -3364,6 +3447,15 @@
}
}
},
"evening_detective_serverGetParticipationReq": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "Персональный токен из письма: 64 шестнадцатеричных символа. Не является JWT."
}
}
},
"evening_detective_serverGetPermissionsRsp": {
"type": "object",
"properties": {
@@ -3627,6 +3719,41 @@
}
}
},
"evening_detective_serverParticipationRsp": {
"type": "object",
"properties": {
"error": {
"type": "string",
"description": "Пустая строка при успехе; иначе сообщение об ошибке для пользователя."
},
"teamName": {
"type": "string",
"description": "Название команды. Данные доступны только по действительному токену."
},
"gameName": {
"type": "string",
"description": "Название игры."
},
"startAt": {
"type": "string",
"format": "date-time",
"description": "Плановое начало игры, UTC (RFC 3339 в JSON)."
},
"participantsCount": {
"type": "integer",
"format": "int32",
"description": "Заявленное число участников команды."
},
"status": {
"type": "string",
"description": "pending — ожидает ответа, confirmed — подтверждено, cancelled — отменено."
},
"closed": {
"type": "boolean",
"description": "Новые ответы закрыты: наступило плановое начало или игра вышла из draft.\nИзменение уже принятого решения запрещено независимо от этого поля."
}
}
},
"evening_detective_serverPauseGameRsp": {
"type": "object",
"properties": {
@@ -3996,6 +4123,22 @@
"evening_detective_serverTeam": {
"type": "object",
"properties": {
"participationStatus": {
"type": "string",
"description": "Статус участия: pending, confirmed или cancelled. Поле панели организатора."
},
"participationSource": {
"type": "string",
"description": "Источник решения: captain, automatic либо пустая строка до ответа."
},
"participationEmailError": {
"type": "string",
"description": "Последняя ошибка отправки; пустая строка, если ошибки нет."
},
"participationEmailSent": {
"type": "boolean",
"description": "Письмо принято SMTP-сервером; не означает прочтение или доставку во входящие."
},
"id": {
"type": "integer",
"format": "int32"