farm_service
真寻文字农场的 Rust 服务端起点。当前实现用户基础资料上报和查询, 另提供可选的公开素材分发接口,尚未实现活动发布中心, 也尚未接入 QQ 机器人自动上报。
当前能力
GET /health:公开就绪检查,实际检查数据库。GET /v1/assets/manifest.json:公开素材清单,含版本、SHA256、大小及三源绝对URL。GET /v1/assets/{sha256}/assets.zip:下载启动时校验过的素材快照,支持ETag。- 资源分发接口与三端接入约定。
- 素材发布文件位于根目录
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 示例:
# 仅供本地启动。生成令牌后妥善保存,调用方使用同一令牌。
$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 |
相对目录以进程工作目录为基准;生产建议使用固定绝对路径。
.env.example 只是模板,程序不会自动加载 .env。
Ctrl+C 停止;Unix 同时支持 SIGTERM,等待在途 HTTP 请求结束后关闭连接池。
日志按日切分,不自动清理历史日志;部署时配置保留期限和磁盘监控。
插件的「资源获取地址」与「farm_service 地址」始终同时保留。
资源源可选 Github、Gitea、farm_service,默认 Github;
服务地址独立供资源、活动等功能使用,活动接口当前尚未实现。
GitHub/Gitea 的清单及 ZIP 均从本服务仓库根目录 assets/ 的 raw 直链读取,
详见资源发布位置。
当前本地清单中的 https://farm.example 明确为占位地址,
客户端选择服务源时使用其独立配置的真实基础地址。
本轮仅准备本地文件,未提交、推送或部署,远端可用性尚未验证。
调用示例
在启动服务时设置过令牌的 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,应关闭该路径的 访问日志或脱敏。数据目录/备份仅授予服务账户权限,备份按个人资料保护。 用户删除和保留政策需在正式收集前落实,本轮未实现删除接口或自动清理。
开发验证
cargo fmt --check
cargo test --locked --all-targets
cargo clippy --locked --all-targets -- -D warnings
测试覆盖鉴权、资料校验、昵称更新、重启持久化、平台隔离、并发建档、 请求大小及数据库不可用。测试使用临时目录,不写入实际用户数据库。
开源协议
Copyright (c) 2026 Shu-Ying。
本项目采用 GNU Affero General Public License v3.0,
SPDX 标识为 AGPL-3.0-only,完整条款见 LICENSE。
允许使用、修改、分发及商用,但须遵守协议的版权、源码提供等要求。 特别是修改后的版本通过网络与用户交互时,应按第 13 节向这些用户 显著提供免费取得该修改版本对应源码的机会。 源码地址应指向实际运行版本,不能仅指向不包含这些修改的上游仓库。 协议针对程序及其对应源码,不要求公开 API 令牌、用户资料或数据库内容。