Files
ShbDiscordBot/docs/API.md
2026-08-07 13:41:43 +03:00

368 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ShbUtils Core API
Локальный справочник по API сервиса `https://api.shlakoblock.com`.
- Источник: `https://api.shlakoblock.com/api.json`
- OpenAPI: `3.1.0`
- Версия сервиса: `2.1.3-SNAPSHOT`
- Дата снимка: `2026-07-22`
- Формат запросов и ответов, если не указано иное: `application/json`
Документ является снимком контракта. В OpenAPI не описаны rate limits, гарантии идемпотентности и формат JSON-тел для большинства ошибок.
## Авторизация
### Internal endpoints
Все пути `/internal/*` требуют заголовок:
```http
X-Internal-Secret: <shared-secret>
```
При отсутствующем или неверном секрете возвращается `401 invalid_internal_secret`.
### Player endpoints
Пути `/api/*` требуют bearer-токен, выданный `POST /internal/auth/start`:
```http
Authorization: Bearer <token>
```
Хотя схема `BearerAuth` присутствует в OpenAPI, требования `security` не проставлены у самих операций. Необходимость токена следует из ответов `401 missing/invalid token`; для этих endpoint также возможен `403 player_offline`.
## Basic
### `GET /`
Маркер сервиса. Возвращает `200` и название сервиса простым текстом.
### `GET /health`
Проверяет соединения с БД и Redis.
| Код | Значение |
| --- | --- |
| `200` | `status: ok` |
| `503` | `status: degraded` |
## Internal
### `POST /internal/join`
Регистрирует вход игрока.
```json
{
"uuid": "11111111-1111-1111-1111-111111111111",
"playerName": "Player"
}
```
`playerName` необязателен и может быть `null`. Успех: `200 ApiMessage`. Ошибки: `400 invalid_body / invalid_uuid`, `401 invalid_internal_secret`.
### `POST /internal/quit`
Регистрирует выход игрока. Тело: `UuidRequest`. Успех: `200 ApiMessage`. Ошибки: `400 invalid_body / invalid_uuid`, `401`.
### `POST /internal/auth/start`
Выдаёт bearer-токен для игрока. Игрок должен быть онлайн.
- Тело: `UuidRequest`.
- Успех: `200 TokenResponse`.
- Ошибки: `400 invalid_body / invalid_uuid`, `401`, `403 player_offline`.
### `POST /internal/verification/code`
Создаёт verification-код для Minecraft UUID. Это направление «Minecraft → внешний клиент», поэтому ShbDiscordBot не использует endpoint для своего `/auth`.
- Тело: `VerificationCodeRequest`.
- Успех: `200 VerificationCodeResponse`.
- Ошибки: `400 invalid_body / invalid_uuid`, `401`.
### `POST /internal/verification/verify`
Проверяет ранее созданный код и привязывает Telegram и/или Discord.
```json
{
"code": "123456",
"telegramId": 123456789,
"telegramTag": "example",
"discordId": "123456789012345678"
}
```
Кроме `code`, поля необязательны и nullable. Успех: `200 VerificationVerifyResponse`. Ошибки: `400 invalid_body`, `401`, `404 invalid_or_expired_code`.
### `POST /internal/auth/password`
Проверяет пароль игрока без передачи хэша наружу.
```json
{
"uuid": "11111111-1111-1111-1111-111111111111",
"password": "plain-text-password"
}
```
Успех: `200 PasswordVerifyResponse`. Ошибки: `400 invalid_body / invalid_uuid`, `401`.
### `POST /internal/auth/password/change`
Заменяет пароль игрока.
```json
{
"uuid": "11111111-1111-1111-1111-111111111111",
"newPassword": "new-plain-text-password"
}
```
Успех: `200 ApiMessage`. Ошибки: `400 invalid_body / invalid_uuid / invalid_password`, `401`, `404 player_not_found`.
### `POST /internal/players/password/reset`
Удаляет сохранённый пароль игрока. Тело: `PasswordResetRequest`. Успех: `200 ApiMessage`. Ошибки: `400 invalid_body / invalid_uuid`, `401`, `404 player_not_found`.
### `POST /internal/players/unlink`
Отвязывает Telegram и/или Discord. Оба флага по умолчанию равны `true`.
```json
{
"uuid": "11111111-1111-1111-1111-111111111111",
"telegram": true,
"discord": true
}
```
Успех: `200 ApiMessage`. Ошибки: `400 invalid_body / invalid_uuid`, `401`, `404 player_not_found`.
### `POST /internal/players/status`
Ищет игрока и возвращает состояние регистрации/привязок. В теле должно присутствовать ровно одно из полей `uuid`, `name`, `telegramId`, `discordId`.
```json
{
"discordId": "123456789012345678"
}
```
Успех: `200 PlayerStatusResponse`; если совпадение отсутствует, возвращается объект с `exists: false`, а не `404`. Ошибки: `400 invalid_body / invalid_uuid / exactly_one_identifier_required`, `401`.
### `GET /internal/players/{uuid}`
Возвращает полный `PlayerProfile` по UUID. Ошибки: `400 invalid_uuid`, `401`, `404 player_not_found`.
### `GET /internal/players/by-name/{name}`
Ищет полный `PlayerProfile` по Minecraft-нику без учёта регистра. Ошибки: `401`, `404 player_not_found`.
### `GET /internal/players/by-telegram/{telegramId}`
Ищет полный `PlayerProfile` по Telegram ID. Ошибки: `400 invalid_telegram_id`, `401`, `404 player_not_found`.
### `POST /internal/players/{uuid}/telegram`
Устанавливает либо очищает Telegram-привязку.
```json
{
"telegramId": 123456789,
"telegramTag": "example"
}
```
Оба поля nullable; `null` используется для отвязки. Успех: `200 PlayerProfile`. Ошибки: `400 invalid_body / invalid_uuid`, `401`, `404 player_not_found`.
### `POST /internal/players/{uuid}/discord`
Устанавливает либо очищает Discord-привязку. Это endpoint, используемый ShbDiscordBot после погашения локального кода.
```json
{
"discordId": "123456789012345678"
}
```
`discordId: null` означает отвязку. Успех: `200 PlayerProfile`. Ошибки: `400 invalid_body / invalid_uuid`, `401`, `404 player_not_found`.
## Player API
### `GET /api/players/online`
Возвращает массив `Player` со всеми онлайн-игроками. Ошибки: `401 missing/invalid token`, `403 player_offline`.
### `GET /api/players/registered`
Возвращает массив `Player` со всеми зарегистрированными игроками. Ошибки: `401 missing/invalid token`, `403 player_offline`.
### `GET /api/players/me/state`
Возвращает `MyPlayerStateResponse` для владельца bearer-токена. Ошибки: `401 missing/invalid token`, `403 player_offline`.
### `GET /api/players/{uuid}`
Возвращает зарегистрированного игрока как `Player`.
Ошибки: `400 invalid_uuid`, `401 missing/invalid token`, `403 player_offline`, `404 player_not_found`.
## Схемы данных
`required` ниже означает обязательность по OpenAPI. Nullable-поле может явно содержать `null`.
### `ApiMessage`
| Поле | Тип | required |
| --- | --- | --- |
| `message` | string | да |
### `JoinRequest`
| Поле | Тип | required |
| --- | --- | --- |
| `uuid` | string | да |
| `playerName` | string или null | нет |
### `UuidRequest`, `VerificationCodeRequest`, `PasswordResetRequest`
Каждая схема содержит одно обязательное поле `uuid: string`.
### `TokenResponse`
| Поле | Тип | required |
| --- | --- | --- |
| `token` | string | да |
### `VerificationCodeResponse`
| Поле | Тип | required |
| --- | --- | --- |
| `code` | string | да |
| `expiresAt` | int64 | да |
OpenAPI не уточняет единицу `expiresAt`; клиенту следует согласовать её с реализацией сервиса.
### `VerificationVerifyRequest`
| Поле | Тип | required |
| --- | --- | --- |
| `code` | string | да |
| `telegramId` | int64 или null | нет |
| `telegramTag` | string или null | нет |
| `discordId` | string или null | нет |
### `VerificationVerifyResponse`
| Поле | Тип | required |
| --- | --- | --- |
| `uuid` | string | да |
| `name` | string | да |
### `PasswordVerifyRequest`
Обязательные поля: `uuid: string`, `password: string`.
### `PasswordVerifyResponse`
Обязательное поле: `valid: boolean`.
### `PasswordChangeRequest`
Обязательные поля: `uuid: string`, `newPassword: string`.
### `UnlinkAccountsRequest`
| Поле | Тип | required |
| --- | --- | --- |
| `uuid` | string | да |
| `telegram` | boolean | нет |
| `discord` | boolean | нет |
### `PlayerStatusRequest`
Все поля необязательны/nullable, но сервер требует ровно один идентификатор:
| Поле | Тип |
| --- | --- |
| `uuid` | string или null |
| `name` | string или null |
| `telegramId` | int64 или null |
| `discordId` | string или null |
### `PlayerStatusResponse`
Только `exists` обязательно по схеме. Остальные поля могут отсутствовать при `exists: false`.
| Поле | Тип |
| --- | --- |
| `exists` | boolean |
| `uuid` | string или null |
| `name` | string или null |
| `registered` | boolean |
| `telegramLinked` | boolean |
| `telegramId` | int64 или null |
| `telegramTag` | string или null |
| `discordLinked` | boolean |
| `discordId` | string или null |
### `PlayerProfile`
Все поля обязательны; идентификаторы внешних аккаунтов nullable.
| Поле | Тип |
| --- | --- |
| `uuid` | string |
| `name` | string |
| `registered` | boolean |
| `online` | boolean |
| `telegramId` | int64 или null |
| `telegramTag` | string или null |
| `discordId` | string или null |
### `TelegramLinkRequest`
Необязательные nullable-поля: `telegramId: int64`, `telegramTag: string`.
### `DiscordLinkRequest`
Необязательное nullable-поле: `discordId: string`.
### `Player`
| Поле | Тип | required |
| --- | --- | --- |
| `uuid` | string | да |
| `name` | string или null | да |
### `MyPlayerStateResponse`
Обязательные поля: `uuid: string`, `name: string`.
## Пример привязки Discord напрямую
Проверка текущей связи:
```http
POST /internal/players/status HTTP/1.1
Host: api.shlakoblock.com
X-Internal-Secret: <secret>
Content-Type: application/json
```
Запись Discord ID игроку:
```http
POST /internal/players/11111111-1111-1111-1111-111111111111/discord HTTP/1.1
Host: api.shlakoblock.com
X-Internal-Secret: <secret>
Content-Type: application/json
```