QXUIZ 自定义模板开发文档

QXUIZ 云管理 · 自定义模板开发文档

适用于在 QXUIZ 云管理平台上为「机器人托管」功能开发自定义模板的开发者。


一、模板是什么

模板就是一个单文件 Python 脚本.py),用户选中你的模板、绑定他自己的 QQ 机器人密钥后,平台会:

  1. 把模板复制一份到 apps/{应用ID}/bot.py
  2. 自动替换里面的 {APPID}{SECRET} 为用户自己的机器人密钥
  3. 服务器Linux 启动运行

用户拿到的就是一个能用的 QQ 群机器人(被 @ 触发回复),用户不需要服务器、不需要懂代码。

二、环境与依赖

平台运行环境(用户托管时):

内容
Python3.8+
已装依赖qq-botpy(官方 SDK)、aiohttprequests
运行目录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 权限,多数账号没有
2markdown需权限,别用
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 目录里,但别尝试越权)

七、本地测试

  1. 临时把占位符换成你自己的测试机器人密钥:
    APPID = "你的测试AppID"
    SECRET = "你的测试AppSecret"
  2. 直接运行:
    pip install qq-botpy
    python 我的模板.py
  3. 测试完改回占位符再提交平台。

八、上线到平台

  1. 把模板文件放到平台托管机的本地路径(如 /www/wwwroot/qqbot/temple/我的模板.py
    ⚠️ 用终端 cp 复制,不要用文件管理器拖(安卓权限问题会导致读不了)
  2. 在平台后台添加模板,填写:
    • 名称、本机路径、成本积分、描述
    • 可选:标签(逗号分隔,前端彩色展示)
    • 可选:截图/视频链接(逗号分隔,模板详情页展示)
    • 可选:勾选「定制模板」→ 限定可用等级 / 指定用户编号
  3. 用户:创建应用 → 选模板 → 绑定自己的机器人密钥(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 问答 + 内容过滤
  • 星座配对 — 接口查询 + 格式化输出

直接参考这两个文件改,最快上手。


— 文档结束 —

⚠️

确认跳转

您即将离开本站,前往外部链接。
请确认是否继续?