@han1549302096 改用json请求可以正常发送吗,这个formdata腾讯说是只用来发图片的,没试过发文本。
![](/assets/uploads/profile/4650-profileavatar-1653394220192.jpeg)
Dituon 发布的帖子
-
RE: 腾讯官方Bot接口扫盲
@han1549302096 删除Content-Type,由fetch函数自动添加。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type -
腾讯官方Bot接口扫盲
注意
由于楼主文化造纸不高,文中掺杂了很多废话,只阅读粗体字即可了解全部信息,细体字为背景信息补充。
前言
众所周知,腾讯几年前为了对标discord和一众竞品推出了秋秋频道,为了对标其它平台的Bot生态开放了仅限频道的官方接口,在开发频道Bot接口时顺便开发了群聊接口,不过仅限内部使用。
不久之后,腾讯官方的群聊Bot陆续上线,例如群聊管家,农药战绩Bot等;这些用新接口的Bot与腾讯之前与微软合作的QQ小冰,BabyQ等烂尾项目最大的区别是带有权限管理系统,例如群主可以指定Bot权限等。这是因为腾讯把内部接口开放给了缴纳保护费的公司开发对应游戏的战绩查询Bot。
经过漫长的便秘开发周期,腾讯终于在去年 (2023) 9月宣布对个人开发者开放群聊接口,代价是需要参加腾讯组织的比赛。
最近腾讯宣布比赛马上结束,现有的接口也基本稳定下来,所以就有了这篇文章。
资质 & 注册
注册成为个人开发者,只需要绑定个人身份信息的QQ账户即可;因为几年前的相关部门规定,反而很难找到没有绑定个人信息的账号。
注册网站: q.qq.com
注册后即可创建Bot,默认创建的Bot只有频道接口的开发权限,群聊权限会在近期开放申请,请期待本贴更新。
审核
接下来是大部分人关心的审核问题,Bot默认只能在测试频道/群聊中使用,添加到其它频道需要通过审核。
下面的内容包含大量黑框框 你知道的太多了
审核流程
-
平台上上传Bot头像, 指令等基本信息。
-
填写excel表格,包含bot的功能、用途、测试用例等信息
表格预览(可能近期失效,下方有截图)
-
等待过审 (三天到一周时间,周末放假)
-
更改Bot使用范围为公域 (下文附有腾讯黑话&专有名词解释)
-
等待过审 (两天到一周时间,周末放假)
(令人迷惑的是为什么腾讯一定要审核两遍,咱也不敢问)
审核时审核员会根据表格里的指令进行测试
也不一定按照表格里的指令测试,笔者就遇到过审核员没有按照表格内对应的格式回复导致审核不通过再等一周
还会假设bot有AI机能尝试聊天审核尺度
建议: 送审时尽可能阉割以免不通过再等一周,过审后可以随意编辑
文本
腾讯对文本审核尺度把握非常
迷惑严格,列举几个一般人觉得没问题但腾讯不允许出现的词汇:上瘾,生病,胸,腿(等身体部位),美国(或任何国家),迪士尼系列的所有名词(米奇,某只黄色的熊等)(任天堂没试过),警察,药
上面的词汇仅限中文,用英文可以过审
能否过审主要取决于审核的心情,每个审核的G点不一样
图片
想象一下你的祖母会如何评价Bot发送的图片,这就是腾讯的图片审核标准没有标准
封号
过审并不是腾讯拷打你的终点,而是起点,以下列举几个可能导致封号的行为
-
复读用户发过的消息或发送用户的ID。
-
复读用户的表情包/图片或处理后发送用户的头像。
-
在某些日子发送或回复某些词汇,强烈建议了解以避免踩雷。坦克,蛋炒饭等
-
被举报包含AI回复的功能,AI必须有对应资质。
接口 & SDK
接口架构
目前接口有两个大版本,旧版本只能发送频道,新版本群聊和频道皆可
websocket 用于事件通知与简单消息发送
也有http消息发送接口,例如使用formdata发送图片等
官方SDK
重要建议:不要使用腾讯官方 Go Node SDK!
重要建议:不要使用腾讯官方 Go Node SDK!
重要建议:不要使用腾讯官方 Go Node SDK!
有Python, Go, Node版本;不建议使用
Go
Node
,理由如下:-
使用旧版接口
-
缺少类型 (TS类型全是any之类的)
-
太长时间没更新 (截止到本文撰写,Go与Node SDK上次更新时间是2020年)
笔者没用过
Python SDK
,所以持中立态度。野生SDK
有很多,但笔者一个都没用过,体验过的欢迎评论点评,本贴也会积极更新。
Markdown & 按钮
大家朝思暮想的md腾讯也有提供,不过目前限制极大(下详)
腾讯把Markdown分为三种
专有名词 门槛 功能 审核/限制 主动 无 根据预先审核过的模板填充变量发送 每月只能发送4条, 模板需要通过审核(每月中旬集中审核) 被动 每日用户 >= 2000 根据预先审核过的模板填充变量发送 回复用户的指令, 模板需要通过审核(每月中旬集中审核) 原生 每日用户 >= 10000 可直接发送md格式的消息 无 限制
此外,腾讯还制定了一系列匪夷所思的规则,笔者挑选了几个具有代表性的罄竹难书
-
URL域名必须备案且经过认证(认证方式是在域名的某个路径放置一个文件)
-
服务器必须有公网IP(最近突然发公告说Bot必须绑定IP,被骂的挺惨的,腾讯说会考虑取消这个限制
只是套话 应该不会改) -
不能获取用户信息(无法获取用户QQ号,昵称,头像等,取而代之的是一长串
openid
,即使是同一用户在不同群也会有不同的ID,腾讯半年前说会更新)
黑话解释
列举一下文档里经常出现的黑话,欢迎补充
黑话 解释 备注 DAU 每日使用过bot的用户数量 主动消息 Bot主动推送的消息 每月只能发送4条,群主/管理员可关闭 被动消息 Bot回复用户的消息 相比主动消息没有发送数量限制 但是会随机吞消息私域 相对较小的使用场景 女生自用 有加群数量限制,相对限制较少,能监听的事件更多 公域 相对较大的使用场景 公交车 只能监听at相关的事件(目前群bot只能选这个 可能是接口没做好)全量 相对于白名单的概念,谁都可以用 bot默认是白名单,切换时要审核 后话
之前对第三方bot疯狂打压,在笔者看来只是为了给官方接口铺路,但腾讯做了五年还是这样实在令人失望。
以上,想到再补充,本文随意转载,
CC-BY-NC-SA 4.0
-
-
RE: 樱&花动漫接口逆向
更新: 爬虫示例代码
export const config = { fetchHeader: { "Sec-Ch-Ua": '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', "Dnt": '1', "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0" } } export interface VideoInfo { url: string // type: string } export abstract class Parser { public abstract parse(raw: string): Promise<VideoInfo> } import fetch from 'node-fetch' import * as cookie from 'cookie' const exp = /www\.yhmgo\.com\/vp\/(\d+)-(\d+)-(\d+)/ const API_BASE = 'https://www.yhmgo.com/playurl' const PAGE_BASE = 'https://www.yhmgo.com/vp' export class YhmgoParser extends Parser { async parse(url: string): Promise<VideoInfo> { const [match, id, channel, ep] = url.match(exp) if (!match) { throw new Error('Invalid url') } const pageUrl = `${PAGE_BASE}/${id}-${channel}-${ep}.html` const page = await fetch(pageUrl) let {t1, k1} = page.headers.raw()['set-cookie'].reduce((obj, str) => { return {...cookie.parse(str), ...obj} }, {}) let cookies = parseCookie(t1, k1) const raw = await fetch( `${API_BASE}?aid=${id}&playindex=${channel}&epindex=${ep}&r=${Math.random()}`, { headers: { ...config.fetchHeader, referer: pageUrl, cookie: Object.entries(cookies) .map(c => cookie.serialize(c[0], c[1])) .join('; ') } } ) const {vurl} = parseResult(await raw.text()) return { url: decodeURIComponent(vurl), // type: 'm3u8', } } } export function parseCookie(t1: number, k1: number) { let pos = Math.floor(t1 / 0x3e8) >> 0x5 let offset = 0x89a4 let k2 = '' + (((((pos * (pos % 0x100) + 0x1) + offset) * ((pos % 0x80) + 0x1)) * ((pos % 0x10) + 0x1)) + pos) let t2 = '' while (true) { t2 = '' + Math.floor(new Date().getTime()) let tOffset = t2.slice(t2.length - 0x3) let kOffset = k2.slice(k2.length - 0x1) if (tOffset.indexOf(kOffset) >= 0x0) { break } } let start = 0x0 let timeOffset = Math.floor(new Date().getTime() / 0x3e8) >> (0x11 + start) let m2t = ((((timeOffset * 0x15 + 0x9a) * (((timeOffset % 0x40) + 0xd)) * ((timeOffset % 0x20) + 0x22) * ((timeOffset % 0x10) + 0x57)) * ((timeOffset % 0x8) + 0x41)) + 0x2ef) return { t1, k1, t2, k2, m2t } } export function parseResult(raw: string): { purl: string, vurl: string, inv: string } { let result = '' const offset = 0x619 const rawLength = raw.length for (let i = 0x0; i < rawLength; i += 0x2) { let temp = parseInt(raw[i] + raw[i + 1], 0x10) temp = ( (temp + 0x100000 - offset) - (((rawLength / 0x2) - 0x1) - (i / 0x2)) ) % 0x100 result = String.fromCharCode(temp) + result } return JSON.parse(result) }
使用
import {YhmgoParser} from "./parser/yhmgo"; const parser = new YhmgoParser() const video = await parser.parse('https://www.yhmgo.com/vp/11141-2-0.html') console.log(video) // 输出: { url: 'https://vip.lz-cdn16.com/20230317/13224_75d9217b/index.m3u8' }
-
RE: [教程] 使用 cloud flare worker 实现免费接口代理
cloud flare worker 的域名
workers.dev
可能在中国某些地区被污染,挂梯子后重试,之后挂载到自己的域名上