MD 权限的申请
基本权限
在 QQ 机器人的开发-高阶能力菜单中可以申请 MD 基本权限,申请后会获得4个模板额度,可以添加 MD 模板或按钮模板
进阶权限
在月平均 DAU 达到门槛后可以填写机器人激励-报名表获得更多权限, 详见机器人激励体系
银牌机器人:DAU400-2000
- 获得被动 ARK 权限
- 可添加模板提升至 10 个
- 获得按钮模板权限
金牌机器人:DAU2000-10000DAU
- 获得被动 MD 权限
- 可添加模板提升至 20 个
- 获得每周两次紧急提审机会
钻石机器人:DAU10000+
- 获得原生 MD 和自定义按钮权限
- 建立机器人专属服务群
QQ 频道严格遵守以上权限,QQ 群可以直接发送被动 MD 和自定义按钮
特殊权限
有些权限可通过其他渠道申请,方法如下
回调按钮权限:发送邮件申请
订阅消息权限:联系官方人员申请
没有回调按钮权限也可以发送回调按钮并接收到回调信息,但无法确认,具体表现为用户点击按钮显示访问远程服务超时
MD 的使用
本部分默认观看者有一定的 QQ 官方机器人使用基础并且掌握了基本的 Markdown 语法
申请 MD 模板
申请基础 MD 权限通过后,可以在 QQ 机器人的开发-高阶能力菜单申请 MD 模板
- MD 模板最多包含 10 个插值,用以在发送时动态提交
- 插值内不允许使用 MD 语法和\n 换行符
- MD 模板的实际使用不需要和填写的内容一致,可以申请比较通用的 MD 模板用于多个场景
插值的 MD 语法检测只针对单个插值
MD 语法支持情况
- 桌面端 QQNT 支持所有 MD 语法,包括 HTML 标签
- 安卓只支持列表/图片/链接/文字加粗斜体/引用等基础语法,新版本支持代码块
- IOS 在安卓的基础上全版本支持代码块,同时在某些语法的表现上与安卓不同,例如安卓可以展示超链接文本,图片可以使用![img#0 #0]进行自动缩放,但 IOS 不行
发送 MD
示例 1: 使用 MD 模板发送消息
import {} from "@satorijs/adapter-qq";
import { Context } from "koishi";
export async function apply(ctx: Context) {
ctx.command("test").action(async ({ session }) => {
await session.qq.sendMessage(session.channelId, {
msg_type: 2,
msg_id: session.messageId,
markdown: {
custom_template_id: "102076388_1707387724",
params: [
{
key: "t1",
values: ["你好"],
},
{
key: "t2",
values: ["芝士Kooshi"],
},
],
},
});
});
}
示例 2: 发送图片
MD 的图片会在第一次被用户加载时从图片链接下载并保存,如果同时在看群的用户较多,在缓存完成之前就会有多次访问
官方 server-temp 会在第一次访问后删除图片造成同时看群的其他用户加载不出图片,需要重新点开群才能正常加载,所以建议使用支持多次访问的第三方 server-temp 或其它图床服务
import {} from "@satorijs/adapter-qq";
import { Context } from "koishi";
import {} from "@satorijs/server-temp";
import { readFile } from "fs/promises";
export async function apply(ctx: Context) {
ctx.command("test").action(async ({ session }) => {
const image: Buffer = await readFile("test.png");
const width = 100;
const height = 100;
const { url } = await ctx.get("server.temp").create(image);
await session.qq.sendMessage(session.channelId, {
msg_type: 2,
msg_id: session.messageId,
markdown: {
custom_template_id: "102076388_1707387221",
params: [
{
key: "info",
values: [`![img#${width} #${height}]`],
},
{
key: "url",
values: [`(${url})`],
},
],
},
});
});
}
示例 3: 发送消息按钮
详细参数见官方文档
import {} from "@satorijs/adapter-qq";
import { Context } from "koishi";
export async function apply(ctx: Context) {
ctx.command("test").action(async ({ session }) => {
await session.qq.sendMessage(session.channelId, {
msg_type: 2,
msg_id: session.messageId,
markdown: {
custom_template_id: "102076388_1707387724",
params: [
{
key: "t1",
values: ["你好"],
},
{
key: "t2",
values: ["芝士Kooshi"],
},
],
},
keyboard: {
content: {
rows: [
{
// 第一行
buttons: [
{
// 第一行的第一个按钮
render_data: { label: "这是指令" }, // 按钮名称
action: {
type: 2, // 指令按钮
permission: { type: 2 }, // 所有人可点击
data: `/你好`, // 点击后会发送 @机器人 /你好
enter: true, // 点击直接发送, 若 false 则填入输入框
},
},
{
// 第一行的第二个按钮
render_data: { label: "这是链接" },
action: {
type: 0, // 链接按钮
permission: { type: 1 }, // 群管理员可点击
data: "http://foo.bar", // 跳转到这个链接
},
},
],
},
{
// 第二行
buttons: [
{
// 第二行的第一个按钮
id: "VERIFICATION_FORUM", // 回调事件接收到的 ID
render_data: { label: "这是回调" },
action: {
type: 1,
permission: {
type: 0, // 指定的用户可点击
specify_user_ids: [session.userId], // 用户
},
data: `${Date.now()}`, // 回调事件接收到的 data
},
},
],
},
],
},
},
});
});
}