Release v0.2.0 archive and space API update

This commit is contained in:
2026-04-11 01:56:47 +08:00
parent e07a9086b1
commit 07fc690e67
42 changed files with 3391 additions and 1316 deletions

View File

@@ -234,25 +234,66 @@ curl -X POST "https://brisk.lightyears.ltd/api/archives/slot/1/upload" \
说明:
- 空间数据当前为 `payload_json`
- 适合公开资料、展示文案、轻量个性化内容
- 如果是游戏主存档,请优先走云存档模块
- 空间主信息接口只返回元数据,不再内嵌内容本体
- 空间内容本体通过独立 `/content` 接口上传和下载
- 空间内容支持任意 bytes
- 可以上传二进制、文本、JSON、protobuf、msgpack、压缩包等格式
- 如果是多槽位私有主存档,仍优先走云存档模块;如果是空间自定义内容,可直接走空间内容接口
接口:
- `PUT /api/spaces/me`
- `PUT /api/spaces/me/content`
- `GET /api/spaces/{player_id}`
- `GET /api/spaces/{player_id}/content`
- `GET /api/spaces/{player_id}/stats`
- `GET /api/spaces/{player_id}/likes`
- `POST /api/spaces/{player_id}/like`
- `DELETE /api/spaces/{player_id}/like`
- `GET /api/spaces/me/visits`
- `GET /api/spaces/by-login`
- `GET /api/spaces/by-login/content`
- `GET /api/spaces/by-login/stats`
- `GET /api/spaces/by-login/likes`
- `POST /api/spaces/by-login/like`
- `DELETE /api/spaces/by-login/like`
主信息接口返回重点:
- `content_exists`
- `content_version`
- `content_type`
- `content_size_bytes`
- `content_checksum`
- `like_count`
- `visit_count`
- `updated_at`
上传表单字段:
- `base_version`:用于乐观锁;首次上传可传 `0`
- `content_type`:可选,建议传,例如 `application/octet-stream``text/plain``application/json`
- `checksum`:可选;如果传入,服务端会校验 SHA-256
- `file`:必传,内容本体
上传空间内容示例:
```bash
curl -X PUT "https://brisk.lightyears.ltd/api/spaces/me/content" \
-H "Authorization: Bearer <token>" \
-F "base_version=0" \
-F "content_type=application/octet-stream" \
-F "checksum=<sha256>" \
-F "file=@space-content.bin"
```
下载空间内容示例:
```bash
curl "https://brisk.lightyears.ltd/api/spaces/by-login/content?login_provider=tap&login_user_id=tap_user_10001" \
-H "Authorization: Bearer <token>" \
--output space-content.bin
```
按第三方身份查看空间示例:
```bash
@@ -312,6 +353,24 @@ curl -X POST "https://brisk.lightyears.ltd/api/spaces/by-login/like?login_provid
- `login_provider`
- `login_user_id`
### 10.5 空间管理
- `GET /api/admin/spaces/overview?project_id=...`
- `GET /api/admin/spaces?project_id=...`
- `GET /api/admin/spaces/{player_id}?project_id=...`
- `GET /api/admin/spaces/{player_id}/content?project_id=...`
- `GET /api/admin/spaces/{player_id}/likes?project_id=...`
- `GET /api/admin/spaces/{player_id}/visits?project_id=...`
说明:
- 后台空间详情返回内容元数据
- 如果需要查看空间内容本体,使用独立 `/content` 下载接口
- 下载响应会返回:
- `Content-Type`
- `X-Space-Version`
- `X-Space-Checksum`
## 11. OpenAPI
完整 OpenAPI 导出:

View File

@@ -2,17 +2,18 @@
## 1. 这份文档适合做什么
这份文档用于在 Unity 侧封装 Brisk SDK
这份文档用于说明当前 Brisk Unity SDK 的接入结构与推荐调用方式
建议把 SDK 拆成以下层次
当前 SDK 已采用静态总入口
- `BriskClient`
- `BriskAuth`
- `BriskConfig`
- `BriskAnnouncements`
- `BriskRanks`
- `BriskArchives`
- `BriskSpaces`
- `Brisk.InitializeAsync(...)`
- `Brisk.Auth.xxx`
- `Brisk.Player.xxx`
- `Brisk.Config.xxx`
- `Brisk.Announcements.xxx`
- `Brisk.Leaderboard.xxx`
- `Brisk.Archive.xxx`
- `Brisk.Space.xxx`
## 2. 初始化模型
@@ -141,16 +142,31 @@ Task LikeSpaceByLoginIdentityAsync(string loginProvider, string loginUserId)
- msgpack bytes
- 压缩后的存档二进制
Unity SDK 建议提供:
当前 SDK 提供:
- `GetArchiveSlotsAsync()`
- `GetArchiveMetaAsync(slotNo)`
- `UploadArchiveAsync(slotNo, baseVersion, checksum, byte[])`
- `UploadAsync(slotNo, byte[], baseVersion, checksum)`
- `UploadTextAsync(slotNo, text, baseVersion, checksum)`
- `UploadJsonAsync(slotNo, payload, baseVersion, checksum)`
- `DownloadArchiveAsync(slotNo)`
- `DownloadTextAsync(slotNo)`
- `DownloadJsonAsync(slotNo)`
推荐上层使用策略:
- 文本存档:优先直接用 `UploadTextAsync / DownloadTextAsync`
- JSON 存档:优先直接用 `UploadJsonAsync / DownloadJsonAsync`
- 二进制存档:继续用 `UploadAsync / DownloadAsync`
其中:
- SDK 会自动计算上传用 `checksum`
- 手动传 `checksum` 时也可以带 `sha256:` 前缀SDK 会自动归一化
## 9. 玩家空间模块建议
玩家空间适合承载公开展示数据,不建议放主存档
玩家空间适合承载公开展示数据或空间自定义内容,不再限制为 JSON
推荐放:
@@ -158,16 +174,48 @@ Unity SDK 建议提供:
- 头像展示字段
- 成就展示摘要
- 公开资料卡
- 小型二进制空间内容
- 文本、JSON、protobuf、msgpack 等自定义格式
当前接口核心是:
当前 SDK / 接口核心是:
- `UpdateMySpaceAsync(payloadJson)`
- `UploadMySpaceContentAsync(baseVersion, contentType, checksum, byte[])`
- `DownloadSpaceContentByPlayerIdAsync(playerId)`
- `DownloadSpaceContentByLoginIdentityAsync(loginProvider, loginUserId)`
- `GetSpaceByPlayerIdAsync(playerId)`
- `GetSpaceByLoginIdentityAsync(loginProvider, loginUserId)`
- `LikeSpaceAsync(playerId)`
- `LikeSpaceByLoginIdentityAsync(loginProvider, loginUserId)`
- `GetMyVisitsAsync(limit)`
当前 SDK 额外提供了一个极简便捷入口:
- `Brisk.Space.UpdateMyAsync(payload, baseVersion, contentType, checksum)`
它的行为是:
- `payload``string` 时,自动按 `text/plain` 上传
- `payload``byte[]` 时,自动按 `application/octet-stream` 上传
- `payload` 为其他对象时,自动序列化为 JSON 并按 `application/json` 上传
建议 SDK 暴露两层模型:
- 空间主信息:
- `ContentExists`
- `ContentVersion`
- `ContentType`
- `ContentSizeBytes`
- `ContentChecksum`
- `LikeCount`
- `VisitCount`
- 空间内容本体:
- 原始 `byte[]`
- 下载响应头中的 `X-Space-Version`
- 下载响应头中的 `X-Space-Checksum`
如果上层业务追求最省事,可以直接用 `UpdateMyAsync(string)``UpdateMyAsync(object)`
如果业务自己管理编码、压缩、protobuf、msgpack 等格式,则继续走 `byte[]` 上传下载接口。
## 10. 动态配置建议
动态配置拆为两层:

View File

@@ -36,6 +36,7 @@
| `41000 - 41999` | 后台公告 |
| `50000 - 50999` | 排行榜 |
| `51000 - 51999` | 后台榜单 |
| `52000 - 52999` | 后台空间 |
| `60000 - 60999` | 存档 |
| `70000 - 70999` | 玩家空间 |
| `80000 - 80999` | 限流 |
@@ -146,6 +147,18 @@
| `51013` | `admin/ranks` | 缺少榜单必填字段 |
| `51014` | `admin/ranks` | 创建榜单失败 |
| 错误码 | 接口/模块 | 含义 |
|---|---|---|
| `52010` | `admin/spaces` | project_id 非法 |
| `52011` | `admin/spaces` | 空间列表查询失败 |
| `52012` | `admin/spaces/overview` | 空间总览查询失败 |
| `52013` | `admin/spaces/{player_id}` | player_id 非法 |
| `52014` | `admin/spaces/{player_id}` | 空间不存在 |
| `52015` | `admin/spaces/{player_id}` | 空间详情查询失败 |
| `52016` | `admin/spaces/{player_id}/likes` | 空间点赞列表查询失败 |
| `52017` | `admin/spaces/{player_id}/visits` | 空间访客列表查询失败 |
| `52018` | `admin/spaces/{player_id}/content` | 空间内容下载失败 |
| 错误码 | 接口/模块 | 含义 |
|---|---|---|
| `60010` | `archives/meta` | 缺少会话 |
@@ -167,17 +180,36 @@
| `70010` | `spaces/{player_id}` | 缺少会话 |
| `70011` | `spaces/{player_id}` | 玩家不存在 |
| `70012` | `spaces/{player_id}` | 空间读取失败 |
| `70013` | `spaces/me` | 缺少会话 |
| `70014` | `spaces/me` | 请求体错误 |
| `70015` | `spaces/me` | 空间更新失败 |
| `70016` | `spaces/{player_id}/like` | 缺少会话 |
| `70017` | `spaces/{player_id}/like` | 玩家不存在 |
| `70018` | `spaces/{player_id}/like` | 点赞失败 |
| `70019` | `spaces/{player_id}/like` | 缺少会话 |
| `70020` | `spaces/{player_id}/like` | 玩家不存在 |
| `70021` | `spaces/{player_id}/like` | 取消点赞失败 |
| `70022` | `spaces/me/visits` | 缺少会话 |
| `70023` | `spaces/me/visits` | 访客列表查询失败 |
| `70013` | `spaces/me/content` | 缺少会话 |
| `70014` | `spaces/me/content` | multipart 表单错误 |
| `70015` | `spaces/me/content` | 缺少文件 |
| `70016` | `spaces/me/content` | 空间内容版本冲突 |
| `70017` | `spaces/me/content` | checksum 不匹配 |
| `70018` | `spaces/me/content` | 空间内容更新失败 |
| `70019` | `spaces/*/content` | 缺少会话 |
| `70020` | `spaces/*/content` | 玩家不存在 |
| `70021` | `spaces/*/content` | 空间内容不存在 |
| `70022` | `spaces/*/content` | 空间内容下载失败 |
| `70023` | `spaces/{player_id}/like` | 缺少会话 |
| `70024` | `spaces/{player_id}/like` | 玩家不存在 |
| `70025` | `spaces/{player_id}/like` | 点赞失败 |
| `70026` | `spaces/{player_id}/like` | 缺少会话 |
| `70027` | `spaces/{player_id}/like` | 玩家不存在 |
| `70028` | `spaces/{player_id}/like` | 取消点赞失败 |
| `70029` | `spaces/me/visits` | 缺少会话 |
| `70030` | `spaces` | 缺少空间目标参数 |
| `70031` | `spaces/*/content` | 缺少空间目标参数 |
| `70032` | `spaces/{player_id}/like` | 缺少空间目标参数 |
| `70033` | `spaces/{player_id}/like` | 缺少空间目标参数 |
| `70034` | `spaces/me/visits` | 访客列表查询失败 |
| `70035` | `spaces/{player_id}/stats` | 缺少会话 |
| `70036` | `spaces/{player_id}/stats` | 缺少空间目标参数 |
| `70037` | `spaces/{player_id}/stats` | 玩家不存在 |
| `70038` | `spaces/{player_id}/stats` | 空间统计读取失败 |
| `70039` | `spaces/{player_id}/likes` | 缺少会话 |
| `70040` | `spaces/{player_id}/likes` | 缺少空间目标参数 |
| `70041` | `spaces/{player_id}/likes` | 玩家不存在 |
| `70042` | `spaces/{player_id}/likes` | 点赞列表查询失败 |
| 错误码 | 接口/模块 | 含义 |
|---|---|---|

View File

@@ -66,7 +66,9 @@ docker compose up --build
- 云存档:
- 支持二进制文件上传/下载,适合直接存游戏存档 bytes
- 玩家空间:
- 当前为 `payload_json` 结构,适合资料卡、展示文本等轻量公开数据
- 主信息接口返回空间元数据
- 自定义空间内容通过独立二进制接口上传/下载
- 支持任意 bytes兼容二进制、文本、JSON、protobuf、msgpack 等格式
## 测试脚本
@@ -83,6 +85,7 @@ Windows PowerShell
- [0001_init.sql](/F:/OtherWork/BriskGameSerivce/internal/platform/db/migrations/0001_init.sql)
- [0008_identity_and_config_simplification.sql](/F:/OtherWork/BriskGameSerivce/internal/platform/db/migrations/0008_identity_and_config_simplification.sql)
- [0009_space_binary_content.sql](/F:/OtherWork/BriskGameSerivce/internal/platform/db/migrations/0009_space_binary_content.sql)
服务启动时会自动执行未应用迁移。

View File

@@ -350,13 +350,149 @@ components:
score:
type: integer
format: int64
SpaceUpdateRequest:
SpaceContentUploadRequest:
type: object
required: [payload_json]
required: [file]
properties:
payload_json:
type: object
additionalProperties: true
base_version:
type: integer
format: int64
description: Optimistic lock base version. Use 0 for the first upload.
content_type:
type: string
description: Optional MIME type. Defaults to application/octet-stream when omitted.
checksum:
type: string
description: Optional SHA-256 hex checksum. When provided, the server validates it before saving.
file:
type: string
format: binary
SpaceMetadata:
type: object
properties:
project_account_id:
type: string
player_id:
type: string
login_provider:
type: string
login_user_id:
type: string
nickname:
type: string
avatar_url:
type: string
content_exists:
type: boolean
content_version:
type: integer
format: int64
content_type:
type: string
content_size_bytes:
type: integer
format: int64
content_checksum:
type: string
like_count:
type: integer
format: int64
visit_count:
type: integer
format: int64
liked_by_me:
type: boolean
updated_at:
type: string
format: date-time
nullable: true
SpaceStats:
type: object
properties:
project_account_id:
type: string
player_id:
type: string
login_provider:
type: string
login_user_id:
type: string
nickname:
type: string
avatar_url:
type: string
content_exists:
type: boolean
content_version:
type: integer
format: int64
content_type:
type: string
content_size_bytes:
type: integer
format: int64
content_checksum:
type: string
like_count:
type: integer
format: int64
visit_count:
type: integer
format: int64
updated_at:
type: string
format: date-time
nullable: true
SpaceContentUpdateResult:
type: object
properties:
player_id:
type: string
content_version:
type: integer
format: int64
content_type:
type: string
content_size_bytes:
type: integer
format: int64
content_checksum:
type: string
updated_at:
type: string
format: date-time
SpaceLikeResult:
type: object
properties:
liked:
type: boolean
like_count:
type: integer
format: int64
SpaceVisitItem:
type: object
properties:
visitor_player_id:
type: string
nickname:
type: string
avatar_url:
type: string
visited_at:
type: string
format: date-time
SpaceLikeItem:
type: object
properties:
player_id:
type: string
nickname:
type: string
avatar_url:
type: string
created_at:
type: string
format: date-time
paths:
/client/bootstrap:
get:
@@ -644,7 +780,7 @@ paths:
get:
tags: [spaces]
security: [{ bearerAuth: [] }]
summary: Get player space
summary: Get player space metadata
parameters:
- in: path
name: player_id
@@ -659,7 +795,46 @@ paths:
schema: { type: string }
description: Optional target login user id used with login provider lookup.
responses:
'200': { description: Space payload }
'200':
description: Space metadata
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceMetadata'
/spaces/{player_id}/content:
get:
tags: [spaces]
security: [{ bearerAuth: [] }]
summary: Download player space content
parameters:
- in: path
name: player_id
required: true
schema: { type: string }
- in: query
name: login_provider
schema: { type: string }
description: Optional target login provider. When present, login_user_id is also required and overrides player_id lookup.
- in: query
name: login_user_id
schema: { type: string }
description: Optional target login user id used with login provider lookup.
responses:
'200':
description: Binary space content stream
headers:
X-Space-Version:
schema:
type: integer
format: int64
X-Space-Checksum:
schema:
type: string
content:
application/octet-stream:
schema:
type: string
format: binary
/spaces/{player_id}/stats:
get:
tags: [spaces]
@@ -677,7 +852,12 @@ paths:
name: login_user_id
schema: { type: string }
responses:
'200': { description: Space stats }
'200':
description: Space stats
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceStats'
/spaces/{player_id}/likes:
get:
tags: [spaces]
@@ -698,20 +878,33 @@ paths:
name: limit
schema: { type: integer }
responses:
'200': { description: Space likes }
/spaces/me:
'200':
description: Space likes
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SpaceLikeItem'
/spaces/me/content:
put:
tags: [spaces]
security: [{ bearerAuth: [] }]
summary: Update my space
summary: Upload my space content
requestBody:
required: true
content:
application/json:
multipart/form-data:
schema:
$ref: '#/components/schemas/SpaceUpdateRequest'
$ref: '#/components/schemas/SpaceContentUploadRequest'
responses:
'200': { description: Space updated }
'200':
description: Space content updated
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceContentUpdateResult'
'409': { description: Version conflict }
/spaces/{player_id}/like:
post:
tags: [spaces]
@@ -729,7 +922,12 @@ paths:
name: login_user_id
schema: { type: string }
responses:
'200': { description: Liked }
'200':
description: Liked
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceLikeResult'
'429': { description: Rate limited }
delete:
tags: [spaces]
@@ -747,13 +945,18 @@ paths:
name: login_user_id
schema: { type: string }
responses:
'200': { description: Unliked }
'200':
description: Unliked
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceLikeResult'
'429': { description: Rate limited }
/spaces/by-login:
get:
tags: [spaces]
security: [{ bearerAuth: [] }]
summary: Get player space by login identity
summary: Get player space metadata by login identity
parameters:
- in: query
name: login_provider
@@ -764,7 +967,42 @@ paths:
required: true
schema: { type: string }
responses:
'200': { description: Space payload }
'200':
description: Space metadata
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceMetadata'
/spaces/by-login/content:
get:
tags: [spaces]
security: [{ bearerAuth: [] }]
summary: Download player space content by login identity
parameters:
- in: query
name: login_provider
required: true
schema: { type: string }
- in: query
name: login_user_id
required: true
schema: { type: string }
responses:
'200':
description: Binary space content stream
headers:
X-Space-Version:
schema:
type: integer
format: int64
X-Space-Checksum:
schema:
type: string
content:
application/octet-stream:
schema:
type: string
format: binary
/spaces/by-login/stats:
get:
tags: [spaces]
@@ -780,7 +1018,12 @@ paths:
required: true
schema: { type: string }
responses:
'200': { description: Space stats }
'200':
description: Space stats
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceStats'
/spaces/by-login/likes:
get:
tags: [spaces]
@@ -799,7 +1042,14 @@ paths:
name: limit
schema: { type: integer }
responses:
'200': { description: Space likes }
'200':
description: Space likes
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SpaceLikeItem'
/spaces/by-login/like:
post:
tags: [spaces]
@@ -815,7 +1065,12 @@ paths:
required: true
schema: { type: string }
responses:
'200': { description: Liked }
'200':
description: Liked
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceLikeResult'
'429': { description: Rate limited }
delete:
tags: [spaces]
@@ -831,7 +1086,12 @@ paths:
required: true
schema: { type: string }
responses:
'200': { description: Unliked }
'200':
description: Unliked
content:
application/json:
schema:
$ref: '#/components/schemas/SpaceLikeResult'
'429': { description: Rate limited }
/spaces/me/visits:
get:
@@ -843,7 +1103,14 @@ paths:
name: limit
schema: { type: integer }
responses:
'200': { description: Visitor list }
'200':
description: Visitor list
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SpaceVisitItem'
/admin/auth/login:
post:
tags: [admin-auth]
@@ -1499,7 +1766,7 @@ paths:
get:
tags: [admin-spaces]
security: [{ bearerAuth: [] }]
summary: Get player space detail
summary: Get player space metadata detail
parameters:
- in: path
name: player_id
@@ -1511,6 +1778,36 @@ paths:
schema: { type: integer, format: int64 }
responses:
'200': { description: Space detail }
/admin/spaces/{player_id}/content:
get:
tags: [admin-spaces]
security: [{ bearerAuth: [] }]
summary: Download player space content
parameters:
- in: path
name: player_id
required: true
schema: { type: string }
- in: query
name: project_id
required: true
schema: { type: integer, format: int64 }
responses:
'200':
description: Binary space content stream
headers:
X-Space-Version:
schema:
type: integer
format: int64
X-Space-Checksum:
schema:
type: string
content:
application/octet-stream:
schema:
type: string
format: binary
/admin/spaces/{player_id}/likes:
get:
tags: [admin-spaces]