QXUIZ 云管理 · 自定义模板开发文档
适用于在 QXUIZ 云管理平台上为「机器人托管」功能开发自定义模板的开发者。
一、模板是什么
模板就是一个单文件 Python 脚本(.py),用户选中你的模板、绑定他自己的 QQ 机器人密钥后,平台会:
- 把模板复制一份到
apps/{应用ID}/bot.py - 自动替换里面的
{APPID}和{SECRET}为用户自己的机器人密钥 - 用
服务器Linux启动运行
用户拿到的就是一个能用的 QQ 群机器人(被 @ 触发回复),用户不需要服务器、不需要懂代码。
二、环境与依赖
平台运行环境(用户托管时):
| 项 | 内容 |
|---|---|
| Python | 3.8+ |
| 已装依赖 | qq-botpy(官方 SDK)、aiohttp、requests |
| 运行目录 | apps/{应用ID}/(模板文件被复制到这里运行) |
| 日志 | stdout/stderr 自动写入 apps/{应用ID}/bot.log,用户可在云端「机器人日志」查看 |
| 网络 | 可访问外网(接口盒子等第三方 API 可用) |
⚠️ 你的模板只能依赖上面列出的包,不要 import 平台没装的库(除非你确认环境有)。
三、模板必备结构
1. 占位符(必须)
文件里必须有这两行,平台靠它们替换密钥:
APPID = "{APPID}"
SECRET = "{SECRET}"
注意:占位符必须原样是 {APPID} / {SECRET}(花括号包裹),平台替换后变成用户真实的 AppID/Secret。
2. 基础骨架(照抄即可)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""我的模板 - 功能说明"""
import logging
import re
import sys
import botpy
from botpy.message import GroupMessage
# ===== 平台自动替换,不要删除 =====
APPID = "{APPID}"
SECRET = "{SECRET}"
# ==================================
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
log = logging.getLogger("tpl")
def build_intents():
"""兼容不同版本 qq-botpy(照抄)"""
try:
return botpy.Intents(group_and_c2c_event=True)
except TypeError:
return botpy.Intents(public_messages=True)
def clean_question(content):
"""去掉消息里的 @ 提及(照抄)"""
if not content:
return ""
text = re.sub(r"<@![^>]*>\s*", "", content)
text = re.sub(r"^@\S+\s*", "", text)
return re.sub(r"\s+", " ", text).strip()[:500]
class MyBot(botpy.Client):
async def on_ready(self):
log.info("=== 模板已上线 ===")
async def on_group_at_message_create(self, message: GroupMessage):
"""群里被 @ 时触发"""
try:
text = clean_question(message.content)
if not text:
await self.reply(message, "请 @我 并带上指令~")
return
if text in ("帮助", "菜单"):
await self.reply(message, "这是我的使用说明……")
return
# ===== 在这里写你的业务逻辑 =====
await self.reply(message, "收到:" + text)
except Exception as e:
log.exception("处理失败: %s", e)
async def reply(self, message, text):
"""被动回复(照抄)"""
await self.api.post_group_message(
group_openid=message.group_openid,
msg_type=0,
msg_id=message.id,
content=text,
)
def main():
# 防止直接运行未替换的模板
if not APPID or APPID.startswith("{") or APPID.startswith("你的"):
log.error("模板未替换 ID/KEY,请通过平台授权后运行")
sys.exit(1)
client = MyBot(intents=build_intents())
client.run(appid=APPID, secret=SECRET)
if __name__ == "__main__":
main()
3. 三处"照抄"代码
| 函数 | 作用 |
|---|---|
build_intents() | 兼容不同 qq-botpy 版本的事件订阅 |
clean_question() | 去掉 @提及、合并空格、限长 500 |
reply() | 群内被动回复(必须带 msg_id) |
main() 的占位符检查 | 防止未替换就跑 |
四、消息类型(进阶)
| msg_type | 用途 | 说明 |
|---|---|---|
| 0 | 文本 | 最常用 |
| 1 | 图文混排 | 需 markdown 权限,多数账号没有 |
| 2 | markdown | 需权限,别用 |
| 7 | 富媒体(图片) | 发图片:先 post_group_file 上传拿 file_info |
发图片示例:
media = await self.api.post_group_file(
group_openid=message.group_openid,
file_type=1, # 1=图片
url="https://xxx.com/a.jpg",
)
file_info = media.get("file_info") if isinstance(media, dict) else getattr(media, "file_info", None)
await self.api.post_group_message(
group_openid=message.group_openid,
msg_type=7,
msg_id=message.id,
media={"file_info": file_info},
)
五、接第三方接口
import aiohttp
async def query(self, words):
params = {"id": "你的API_ID", "key": "你的API_KEY", "words": words}
try:
async with aiohttp.ClientSession() as session:
async with session.get("https://cn.acc.cn/api/ai/xxx.php",
params=params,
timeout=aiohttp.ClientTimeout(total=15)) as resp:
data = await resp.json(content_type=None)
if isinstance(data, dict) and data.get("code") == 200:
return data.get("msg")
except Exception as e:
log.warning("接口失败: %s", e)
return None
注意:第三方接口要自己处理超时和异常,接口挂了不能卡死机器人,要兜底回复。
六、开发规范与建议
✅ 必须
- 单文件,
{APPID}/{SECRET}占位符 - 每个 handler 用 try/except 包住
- 接口调用设超时
- 提供「帮助」指令,让用户知道怎么用
⚠️ 强烈建议
- 内容过滤:AI 类模板加敏感词/域名拦截(参考平台内置模板),防止用户触发违规内容
- 回复格式美观(分隔线、表情适度)
- 日志用
log.info(用户能在云端看到启动日志,别打太多刷屏日志)
❌ 禁止
- 黄赌毒、诈骗、政治敏感内容(会被封号,并连累平台)
- 依赖同目录其他文件(模板只有一个文件,会被单独复制走)
- 在群里主动发消息骚扰(平台限制主动消息频次)
- 读取用户手机/平台的其他文件(你的代码跑在隔离的 app 目录里,但别尝试越权)
七、本地测试
- 临时把占位符换成你自己的测试机器人密钥:
APPID = "你的测试AppID" SECRET = "你的测试AppSecret" - 直接运行:
pip install qq-botpy python 我的模板.py - 测试完改回占位符再提交平台。
八、上线到平台
- 把模板文件放到平台托管机的本地路径(如
/www/wwwroot/qqbot/temple/我的模板.py)⚠️ 用终端cp复制,不要用文件管理器拖(安卓权限问题会导致读不了) - 在平台后台添加模板,填写:
- 名称、本机路径、成本积分、描述
- 可选:标签(逗号分隔,前端彩色展示)
- 可选:截图/视频链接(逗号分隔,模板详情页展示)
- 可选:勾选「定制模板」→ 限定可用等级 / 指定用户编号
- 用户:创建应用 → 选模板 → 绑定自己的机器人密钥(2AF 验证)→ 授权 → 上线
九、常见问题
| 问题 | 解决 |
|---|---|
| 启动失败「模板实例化失败」 | 检查占位符是否原样为 {APPID}/{SECRET};文件是否可读 |
| 用户 @ 没反应 | 确认消息走的是 on_group_at_message_create;模板密钥是否替换成功 |
| 报「无效 markdown content」 | 图片发错了:用 msg_type=7 + post_group_file,别用 msg_type=2 |
| 接口超时卡死 | 所有网络请求加 timeout |
| 想发多条回复 | 同一条 msg_id 多次回复要递增 msg_seq(1、2、3…) |
十、参考模板
平台已内置:
ai— 最简单,AI 问答 + 内容过滤星座配对— 接口查询 + 格式化输出
直接参考这两个文件改,最快上手。
— 文档结束 —
确认跳转
您即将离开本站,前往外部链接。
请确认是否继续?