轻量化「社区准入筛选系统」。用户填 QQ 号 + 答 15 题,全对才能看到群号与入群密码。
- 后端:FastAPI + Turso(云端 SQLite)
- 前端:单页 HTML(原生 JS)
- 部署:Render 免费版(自动 HTTPS)
- 题库:硬编码在
app.py
用户 ──> Render(跑你的 app.py)──> Turso(存答题记录)
↑
管理员通过 /admin 接口查询
- 在 GitHub 上新建一个仓库(私有公有都行),名字随便比如
qq-quiz - 把这几个文件原样推上去:
qq-quiz/
├── app.py
├── requirements.txt
├── render.yaml
├── .gitignore
└── static/
└── index.html
简单做法:
cd qq-quiz
git init
git add .
git commit -m "init"
git remote add origin https://github.com/你的用户名/qq-quiz.git
git push -u origin main- 打开 https://turso.tech,用 GitHub 账号登录
- 进入 Dashboard,点 Create Database
- 名字:
qq-quiz(随意) - 位置:选离你用户最近的(国内用户推荐
Tokyo / nrt或Singapore / sin) - 套餐:Free(5GB / 5亿次行读 / 1000万次行写,对你这个场景够用一万年)
- 名字:
- 创建好后,在数据库详情页找到 Connection String,里面有:
👉 这就是
libsql://qq-quiz-你的用户名.turso.ioTURSO_DATABASE_URL,复制下来 - 同一页面点 Create Token(或
Generate Token):- Permissions 选 Full Access
- Expiration 选 Never expire(图省事)
- 生成后是一长串
eyJhbGc...的字符串 👉 这是TURSO_AUTH_TOKEN,复制下来(只显示一次,保管好)
💡 不需要在 Turso 里手动建表——
app.py启动时会自动CREATE TABLE IF NOT EXISTS。
-
打开 https://render.com,用 GitHub 账号登录
-
点 New + → Web Service
-
选刚才推的那个 GitHub 仓库
qq-quiz,点 Connect -
设置页面 Render 会自动读取
render.yaml,大部分字段都填好了。你只需检查:- Region:选 Singapore(国内访问最快)
- Plan:Free
-
滑到 Environment Variables,添加这几个(这是关键):
Key Value ADMIN_TOKEN自己想一个长一点的字符串,比如 Kx9pQ2mNvR5tYwA8QQ_GROUP_NUMBER你的真实 QQ 群号 QQ_GROUP_PASSWORD入群密码 / 验证答案 TURSO_DATABASE_URL上一步复制的 libsql://...TURSO_AUTH_TOKEN上一步复制的那串 eyJhbGc... -
点 Create Web Service,开始构建(大概 3–5 分钟)
-
部署成功后,Render 会给你一个网址:
https://qq-quiz.onrender.com打开就能看到答题页面 ✅
打开 https://你的项目.onrender.com/healthz,应该看到:
{"ok": true, "db": "turso"}"db": "turso" 表示连上 Turso 了,如果显示 "local" 说明环境变量没配对。
就是访问主页,填 QQ → 答题 → 通过显示群号密码。
申请加群的人来 → 你拿到 ta 的 QQ 号 → 直接浏览器访问:
https://你的项目.onrender.com/admin/check?qq=10086&token=你的ADMIN_TOKEN
返回类似:
{
"qq": "10086",
"attempts": 2,
"passed": true,
"history": [
{"score": 15, "total": 15, "passed": true, "time": "2026-05-08 14:30:21"},
{"score": 13, "total": 15, "passed": false, "time": "2026-05-08 14:25:11"}
]
}passed: true→ 这人确实答过题且通过过 → 可以放行passed: false或attempts: 0→ 没答过/没通过 → 拒掉
浏览器访问:
https://你的项目.onrender.com/admin/export?token=你的ADMIN_TOKEN
直接下载一个 CSV,可以拖进 Excel 看。
https://你的项目.onrender.com/admin/stats?token=你的ADMIN_TOKEN
现象:15 分钟没人访问,服务就睡过去;下一个用户访问会等 30 秒左右冷启动。
对你的场景(零散的入群答题)影响不大,但如果嫌烦:
- 注册 https://cron-job.org(免费)
- 新建一个 cron job:
- URL:
https://你的项目.onrender.com/healthz - 频率:每 10 分钟
- URL:
- 这样 Render 永远不会休眠
✅ 数据不会丢(数据全在 Turso,跟 Render 重不重启没关系)
编辑 app.py 顶部 QUESTIONS 列表 → push 到 GitHub → Render 自动重新部署(约 2 分钟生效)
题型:
single单选,answer是字符串如"B"multi多选,answer是列表如["A","C","D"]judge判断,answer是字符串
不要改代码,去 Render 后台 → Environment → 改 QQ_GROUP_NUMBER / QQ_GROUP_PASSWORD,保存后会自动重启。
Render 后台改一下就行,立即生效。
不想每次都推到 Render 测,可以本地跑:
pip install -r requirements.txt
# 不设 TURSO_* 环境变量 → 自动用本地 quiz.db 文件
ADMIN_TOKEN=test123 python app.py或者用真 Turso 数据库测:
export TURSO_DATABASE_URL="libsql://..."
export TURSO_AUTH_TOKEN="eyJ..."
export ADMIN_TOKEN="test123"
python app.py按你最初的需求,本系统目标是过滤不看规则的人,不是密码学级安全:
- ✅ 答案在后端,前端看不到 → 抓接口虽可绕过但门槛已经高于"目标用户"
- ✅ 30 秒同 QQ 冷却,防暴力刷
- ✅ 记录 IP / UA / 答题用时,方便事后分析异常
- ✅ Turso 数据持久,不会因 Render 重启丢失
⚠️ QQ 号无法验证真实性 → 但配合事后/admin/check核查,不是真答过题的人进不来⚠️ 入群密码理论上会被通过的人传播 → 想再硬一点:定期手动改QQ_GROUP_PASSWORD环境变量
qq-quiz/
├── app.py # 后端主程序(题库、接口、Turso/SQLite 双模式)
├── requirements.txt # Python 依赖
├── render.yaml # Render 一键部署配置
├── .gitignore
├── README.md
└── static/
└── index.html # 前端页面
数据库表(Turso 自动创建):
attempts(
id, qq, score, total, passed, wrong_ids,
ip, ua, duration_ms, created_at
)