一个基于 mtcute 的 Telegram 入群验证机器人。新成员加入群组或通过入群申请进入时,必须先回答一道题目,验证通过后才被放行。
- 入群直接加入 / 入群申请两种验证流程
- 管理员添加或批准成员时自动跳过验证
- 验证状态后端支持
memory与sqlite - 可选 Sentry 错误监控与日志转发
/ping健康检查、/reload热重载题库- ReScript 核心状态机 + TypeScript 效果解释器
- docs/design.md — 设计意图与行为约定
- docs/deploy-non-docker.md — 非 Docker 手动部署详细说明
- docs/migration-from-ca305be.md — 从旧版 ca305be 实例迁移到最新 main 的指南
- docs/analysis/README.md — 架构分析索引(如已合入)
| 组件 | 要求 |
|---|---|
| Node.js | >= 22.13(代码使用 Node 内置 node:sqlite) |
| pnpm | 与 lockfile 匹配,当前为 pnpm@10.17.1 |
| 网络 | 能访问 Telegram API(出方向 443) |
| 磁盘 | bot-data/ 需要持久化:题库、SQLite state、mtcute session |
# 1. 获取代码
git clone git@github.com:OPaimon/genshin-group-verif.git
cd genshin-group-verif
corepack enable
pnpm --version # 期望 10.17.1
# 2. 安装依赖
pnpm install --frozen-lockfile
# 3. 准备题库(运行前必须存在;构建时可省略)
# 参考下方「题库 quizzes.json」
# 创建 bot-data/quizzes.json
# 4. 配置环境变量
cp .env.example .env
# 编辑 .env,填入 API_ID / API_HASH / BOT_TOKEN / LOG_PEER
# 5. 开发运行(tsx 直接运行源码)
pnpm start
pnpm start是开发/快速启动方式,直接通过tsx运行源码,不是生产部署方式。 生产环境请使用pnpm build+dist/main.mjs,见下方「手动部署」。
复制 .env.example 为 .env 后填写。
必填项:
API_ID— Telegram API IDAPI_HASH— Telegram API HashBOT_TOKEN— Telegram Bot TokenLOG_PEER— 接收验证日志的聊天/频道数字 peer id
常用可选项:
ADMIN_IDS— 允许执行/reload的用户 id,逗号分隔;留空表示禁用AD_LIST_URL— 验证消息底部附加的加群广告链接;留空用默认值,设为空字符串禁用STATE_BACKEND—memory(默认)或sqliteSTATE_SQLITE_PATH—STATE_BACKEND=sqlite时的数据库路径,默认bot-data/state.dbSENTRY_DSN— 留空则完全禁用 SentrySENTRY_ENVIRONMENT— Sentry 环境标签,默认production(生产构建)/development(本地)SENTRY_LOG_LEVEL— 转发到 Sentry Logs 的最低级别:debug | info | warn | error
Redis 状态后端已从主包移除并归档到
archive/state-redis/。当前STATE_BACKEND只接受memory和sqlite,不再支持REDIS_URL。
bot-data/quizzes.json 不会被 git 跟踪,属于需要手动提供的运行时数据文件。
- 构建脚本在文件存在时将其复制到
dist/bot-data/ - 文件缺失时,构建会输出一条明确警告并继续,不会生成占位题库
- 运行时
src/interpreter/quizSource.ts读取process.cwd()/bot-data/quizzes.json - 运行时缺少或无法读取题库时,机器人保持运行并拒绝新的验证请求;提供或修复文件后可执行
/reload或重启恢复
因此运行机器人前必须手动创建 bot-data/quizzes.json。最小合法格式如下:
[
{
"Id": 1,
"Question": "示例问题?",
"Options": ["选项A", "选项B"],
"CorrectOptionIndex": 0
}
]字段说明:
Id— 题目数字 idQuestion— 题目文本Options— 选项数组CorrectOptionIndex— 正确选项在Options中的下标,从 0 开始
以下步骤适用于直接在 Linux 主机 / VM 上部署,不使用 Docker。
git clone git@github.com:OPaimon/genshin-group-verif.git
cd genshin-group-verif
corepack enable
pnpm --version # 期望 10.17.1mkdir -p bot-data
# 将生产题库放到 bot-data/quizzes.json
# 或先按上面的示例创建最小文件pnpm install --frozen-lockfile如果只打算在服务器上运行构建产物,而不在服务器上重新构建,可以只装 production 依赖:
pnpm install --prod --frozen-lockfile注意:即使运行的是
dist/main.mjs,node_modules里仍需要better-sqlite3和@mtcute/wasm,因为 esbuild 将 native addon 和 wasm 作为运行时外部资源处理。better-sqlite3已作为直接依赖保留,因此pnpm install --prod会把它安装到 顶层node_modules/better-sqlite3,dist/main.mjs才能正确解析到它。 如果遇到模块解析问题,最稳妥的方式是直接执行完整的pnpm install --frozen-lockfile。
cp .env.example .env
# 编辑 .env生产环境建议启用 SQLite 持久化:
STATE_BACKEND=sqlite
STATE_SQLITE_PATH=bot-data/state.dbpnpm build构建输出包含:
dist/main.mjs
dist/main.mjs.map
dist/metafile.json
dist/bot-data/quizzes.json # 仅当构建时源题库存在
前台运行(快速验证):
node --env-file=.env --enable-source-maps dist/main.mjs
pnpm start:prod不会自动读取.env,所以上面使用 Node 的--env-file显式加载。
推荐使用 systemd 常驻运行。创建 /etc/systemd/system/genshin-group-verif.service:
[Unit]
Description=genshin-group-verif Telegram bot
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=genshin-bot
Group=genshin-bot
WorkingDirectory=/opt/genshin-group-verif
EnvironmentFile=/opt/genshin-group-verif/.env
Environment=NODE_ENV=production
ExecStart=/usr/bin/node --enable-source-maps dist/main.mjs
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target启用并启动:
sudo systemctl daemon-reload
sudo systemctl enable --now genshin-group-verif
sudo systemctl status genshin-group-verif
journalctl -u genshin-group-verif -f/opt/genshin-group-verif/
├── .env
├── bot-data/
│ ├── quizzes.json
│ ├── state.db # STATE_BACKEND=sqlite 时生成
│ └── session/ # mtcute 登录会话
├── dist/
│ ├── main.mjs
│ └── main.mjs.map
└── node_modules/
运行用户需要对 bot-data/ 有读写权限。备份时优先备份:
bot-data/quizzes.jsonbot-data/state.dbbot-data/session/
| 后端 | 是否跨重启保留验证会话 | 说明 |
|---|---|---|
memory(默认) |
否 | 适合本地/临时测试;重启后 pending session 丢失 |
sqlite |
是 | 推荐单机生产;单文件 DB,无需额外服务 |
Redis 后端已归档到 archive/state-redis/,不作为主包默认后端;重新引入计划见对应 GitHub issue。
cd /opt/genshin-group-verif
git pull
pnpm install --frozen-lockfile
pnpm build
sudo systemctl restart genshin-group-verifSQLite 升级前建议备份:
cp bot-data/state.db bot-data/state.db.bak仓库附带 Dockerfile 和 docker-compose.yaml。
构建镜像时不需要把
bot-data/quizzes.json放入构建上下文。题库属于运行时数据,应在启动前放到宿主机的./bot-data/quizzes.json;缺失时镜像仍能构建,但验证服务会保持不可用。
# 在宿主机准备运行时题库
mkdir -p bot-data
# 将题库放到 bot-data/quizzes.json
# 构建并启动
docker compose up -d --builddocker-compose.yaml 会把宿主机的 ./bot-data 挂载到容器 /app/bot-data,因此题库、SQLite state 和 session 都会持久化在宿主机目录中。
pnpm lint
pnpm test当前 pnpm test 覆盖 Flow 测试与 memory/sqlite 状态后端测试;Redis 测试已随 Redis 后端一起移入 archive/state-redis/,不作为默认测试运行。