Files
farm_service/README.md
T

159 lines
8.1 KiB
Markdown
Raw Normal View History

2026-10-23 19:18:50 +08:00
# farm_service
真寻文字农场的 Rust 服务端起点。当前实现用户基础资料上报和查询,
另提供可选的公开素材分发接口,尚未实现活动发布中心,
也尚未接入 QQ 机器人自动上报。
## 当前能力
- `GET /health`:公开就绪检查,实际检查数据库。
- `GET /v1/assets/manifest.json`:公开素材清单,含版本、SHA256、大小及三源绝对URL。
- `GET /v1/assets/{sha256}/assets.zip`:下载启动时校验过的素材快照,支持ETag。
2026-10-26 11:35:04 +08:00
- `GET /v1/fonts/manifest.json`:独立字体资源清单。
- `GET /v1/fonts/{sha256}/assets.zip`:原版小赖字体与完整 OFL 许可,支持 ETag。
2026-10-23 19:18:50 +08:00
- [资源分发接口与三端接入约定](docs/assets.md)。
- 素材发布文件位于根目录 `assets/manifest.json` 和 `assets/assets.zip`;
ZIP 仅由本服务仓库发布,三个插件分发包不包含 ZIP。
- `PUT /v1/users`:受保护的用户资料新增/更新;重复上报不会重复建档。
- `GET /v1/users/{platform}/{platform_user_id}`:受保护的单用户查询。
- 独立 SQLite 数据库,启动自动迁移;不访问农场插件的数据库。
- 每日 JSON 文件日志;不记录 QQ 号、昵称、令牌、完整请求或 SQL 参数。
- AGPL v3 开源协议(`AGPL-3.0-only`)。二进制应用的 `Cargo.lock` 应纳入版本控制。
此阶段用 SQLite 降低首次运行门槛。此前活动规划中的 PostgreSQL、
发布目录、活动账户和跨库奖励交付尚未实施,不创建占位字段或空模块。
## 用户字段与身份
| 字段 | 用途与约束 |
|---|---|
| `platform` | 平台命名空间:`qq`、`telegram`、`discord` |
| `platform_user_id` | 字符串形式的正整数 ID,不接受前导零;QQ 最多 20 位,其他最多 32 位 |
| `nickname` | 当前昵称,去除首尾空白后 1~64 个 Unicode 字符,禁止控制字符 |
| `created_at` | 首次建档 UTC 时间,更新昵称时保留 |
| `updated_at` | 最近资料写入 UTC 时间 |
`platform + platform_user_id` 是唯一键。同一 QQ 在不同机器人上报时
对应同一份基础资料,不包含农场余额、机器人内玩家归属或群成员信息。
这些资料来自持有令牌的受信机器人,不代表服务端已向 QQ 验证身份。
`qq` 只表示普通 QQ 号码(如 OneBot 适配器提供的标识),
不接受官方 QQ OpenID/UnionID,也不把它们自动转换成 QQ 号。
以后接入官方 QQ 时须增加应用作用域,避免不同应用的 OpenID 被混用。
不要另外添加与 `platform_user_id` 重复、无独立用途的 `qq_number` 字段。
## 启动
需要 stable Rust 工具链和本机 C/C++ 构建工具(SQLite 原生依赖需要)。
Windows 推荐 Visual Studio Build Tools 的“使用 C++ 的桌面开发”。
依赖版本由 `Cargo.lock` 固定;首次构建需要访问 crates.io。
PowerShell 示例:
```powershell
# 仅供本地启动。生成令牌后妥善保存,调用方使用同一令牌。
$env:FARM_API_TOKEN = [Convert]::ToHexString(
[System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32)
)
$env:FARM_BIND = "127.0.0.1:8080"
cargo run --locked
```
| 环境变量 | 默认值 / 作用 |
|---|---|
| `FARM_API_TOKEN` | 必填,32~256 个可见 ASCII 字符;建议随机生成 |
| `FARM_BIND` | `127.0.0.1:8080` |
| `FARM_DATA_DIR` | `./data`,保存 `farm_service.sqlite3` |
| `FARM_LOG_DIR` | `./logs`,保存每日滚动日志 |
| `RUST_LOG` | `farm_service=info` |
| `FARM_ASSET_MANIFEST` | 可选,建议 `./assets/manifest.json`;同目录须有assets.zip;未设置时资源接口返回503 |
2026-10-26 11:35:04 +08:00
| `FARM_FONT_MANIFEST` | 可选,设为 `./fonts/manifest.json`;同目录须有 assets.zip;未设置时字体接口返回503 |
2026-10-23 19:18:50 +08:00
相对目录以进程工作目录为基准;生产建议使用固定绝对路径。
`.env.example` 只是模板,程序**不会自动加载 .env**。
Ctrl+C 停止;Unix 同时支持 SIGTERM,等待在途 HTTP 请求结束后关闭连接池。
日志按日切分,不自动清理历史日志;部署时配置保留期限和磁盘监控。
插件的「资源获取地址」与「farm_service 地址」始终同时保留。
资源源可选 `Github`、`Gitea`、`farm_service`,默认 `Github`;
服务地址独立供资源、活动等功能使用,活动接口当前尚未实现。
GitHub/Gitea 的清单及 ZIP 均从本服务仓库根目录 `assets/` 的 raw 直链读取,
详见[资源发布位置](docs/assets.md#仓库文件与发布位置)。
当前本地清单中的 `https://farm.example` 明确为占位地址,
客户端选择服务源时使用其独立配置的真实基础地址。
本轮仅准备本地文件,未提交、推送或部署,远端可用性尚未验证。
## 调用示例
在启动服务时设置过令牌的 PowerShell 会话中执行:
```powershell
$headers = @{ Authorization = "Bearer $env:FARM_API_TOKEN" }
$profile = @{
platform = "qq"
platform_user_id = "12345678"
nickname = "农场玩家"
} | ConvertTo-Json
Invoke-RestMethod -Method Put -Uri "http://127.0.0.1:8080/v1/users" `
-Headers $headers -ContentType "application/json; charset=utf-8" `
-Body ([System.Text.Encoding]::UTF8.GetBytes($profile))
Invoke-RestMethod -Uri "http://127.0.0.1:8080/v1/users/qq/12345678" `
-Headers $headers
```
写入和更新均返回 HTTP 200 与完整资料。JSON 只接受上述三个输入字段。
请求体上限 4 KiB。非法资料返回 400;JSON 类型/格式错误可能返回
400/415/422;超大请求返回 413;鉴权失败返回 401;用户不存在返回 404;
存储不可用返回 503,不向客户端泄漏数据库细节。
## 接入与部署边界
插件需要在接入层从可信事件取得用户 ID、昵称及平台,再显式上报;
当前不会自动读取 QQ、扫描群成员或收集历史消息。
只在确有业务用途时上报这些字段,并向用户说明用途及保留策略。
本版本一个令牌对应一个受信服务访问范围,持有者可以查询或更新已知 ID
的资料,尚无租户级权限或管理员账户。令牌不能放进群消息、前端或日志。
暂不提供用户枚举/批量查询接口。
默认仅监听本机;公网部署需 HTTPS 反向代理、限流及访问控制。
反向代理的 URL 访问日志可能包含查询路径中的用户 ID,应关闭该路径的
访问日志或脱敏。数据目录/备份仅授予服务账户权限,备份按个人资料保护。
用户删除和保留政策需在正式收集前落实,本轮未实现删除接口或自动清理。
## 开发验证
```text
cargo fmt --check
cargo test --locked --all-targets
cargo clippy --locked --all-targets -- -D warnings
```
测试覆盖鉴权、资料校验、昵称更新、重启持久化、平台隔离、并发建档、
请求大小及数据库不可用。测试使用临时目录,不写入实际用户数据库。
## 开源协议
2026-10-26 11:35:04 +08:00
字体资源独立于服务代码许可。`fonts/Xiaolai-Regular.ttf` 为未经修改的
小赖字体 v3.126,采用 SIL OFL 1.1;完整版权与许可见
[OFL-Xiaolai.txt](fonts/OFL-Xiaolai.txt)。`fonts/assets.zip` 同时包含字体
和许可,不得单独出售字体文件。字体包通过 GitHub/Gitea 的本仓库
`fonts/assets.zip` raw 地址或上述服务接口分发,插件缓存时校验摘要。
资源迁移仅准备本地文件,须发布此仓库或部署服务后远端才能提供新版资源。
2026-10-23 19:18:50 +08:00
Copyright (c) 2026 Shu-Ying。
本项目采用 GNU Affero General Public License v3.0,
SPDX 标识为 `AGPL-3.0-only`,完整条款见 [LICENSE](LICENSE)。
允许使用、修改、分发及商用,但须遵守协议的版权、源码提供等要求。
特别是修改后的版本通过网络与用户交互时,应按第 13 节向这些用户
显著提供免费取得该修改版本对应源码的机会。
源码地址应指向实际运行版本,不能仅指向不包含这些修改的上游仓库。
协议针对程序及其对应源码,不要求公开 API 令牌、用户资料或数据库内容。
2026-10-26 11:35:04 +08:00
## 致谢
- [小赖字体](https://github.com/lxgw/kose-font) *lxgw 提供的开源中文手写字体,采用 SIL OFL 1.1,分发时附带完整字体许可*