Files
farm_service/README.md
T

166 lines
8.7 KiB
Markdown
Raw 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.
# farm_service
真寻文字农场的 Rust 服务端起点。当前实现用户基础资料上报和查询,
另提供可选的公开素材分发接口,尚未实现活动发布中心,
也尚未接入 QQ 机器人自动上报。
## 当前能力
- `GET /health`:公开就绪检查,实际检查数据库。
- `GET /v1/assets/manifest.json`:公开素材清单,含版本、SHA256、大小及三源绝对URL。
- `GET /v1/assets/{sha256}/assets.zip`:下载启动时校验过的素材快照,支持ETag。
- `GET /v1/fonts/manifest.json`:独立字体资源清单。
- `GET /v1/fonts/{sha256}/assets.zip`:原版小赖字体与完整 OFL 许可,支持 ETag。
- `GET /v1/catalogue/manifest.json`:独立作物目录的最新完整版本。
- `GET /v1/catalogue/releases/{release}/{file}`:公开只读历史目录文件,支持 ETag。
- [作物数据、图片维护与不可变发布步骤](docs/catalogue.md);正式来源为
`catalogue/source/`,机器人启动时检查更新。
- [资源分发接口与三端接入约定](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 |
| `FARM_FONT_MANIFEST` | 可选,设为 `./fonts/manifest.json`;同目录须有 assets.zip;未设置时字体接口返回503 |
| `FARM_CATALOGUE_DIR` | 可选,设为 `./catalogue`;启动校验最新及全部历史版本,未设置返回503;更新后重启生效 |
相对目录以进程工作目录为基准;生产建议使用固定绝对路径。
`.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
python -m unittest discover -s tests -p test_prepare_catalogue.py
python scripts/prepare_catalogue.py --version catalogue-20261026-1 --check
```
测试覆盖鉴权、资料校验、昵称更新、重启持久化、平台隔离、并发建档、
请求大小及数据库不可用。测试使用临时目录,不写入实际用户数据库。
## 开源协议
字体资源独立于服务代码许可。`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 地址或上述服务接口分发,插件缓存时校验摘要。
资源迁移仅准备本地文件,须发布此仓库或部署服务后远端才能提供新版资源。
Copyright (c) 2026 Shu-Ying。
本项目采用 GNU Affero General Public License v3.0,
SPDX 标识为 `AGPL-3.0-only`,完整条款见 [LICENSE](LICENSE)。
允许使用、修改、分发及商用,但须遵守协议的版权、源码提供等要求。
特别是修改后的版本通过网络与用户交互时,应按第 13 节向这些用户
显著提供免费取得该修改版本对应源码的机会。
源码地址应指向实际运行版本,不能仅指向不包含这些修改的上游仓库。
协议针对程序及其对应源码,不要求公开 API 令牌、用户资料或数据库内容。
## 致谢
- [小赖字体](https://github.com/lxgw/kose-font) *lxgw 提供的开源中文手写字体,采用 SIL OFL 1.1,分发时附带完整字体许可*