npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@karinjs/adapter-qqbot

v3.3.1

Published

karin adapter for QQ Official Bot (2.0)

Readme

@karinjs/adapter-qqbot

Karin 的 QQ 官方机器人适配器。

安装

pnpm add @karinjs/adapter-qqbot

要求:Node.js >= 22、Karin >= 1.15

配置

首次启动没有 QQBot 配置时,使用任意已连接的机器人或在控制台中发送 #QQBot登录 完成扫码授权。

也可以访问 Karin WebUI 可视化编辑 或者 手动编辑:@karinjs-adapter-qqbot/config/config.json。

[
  {
    "name": "我的机器人",
    "appId": "1234567890",
    "secret": "your-secret",
    "qqEnable": true,
    "guildEnable": true,
    "guildMode": 0,
    "event": { "type": 2 }
  }
]
  • event.type: 0 关闭、1 Webhook、2 WebSocket(默认)。
  • guildMode: 0 公域,只收 @ 消息;1 私域,接收全部频道消息。

旧版本里的 markdown.enable 已移除。发送通道现在由平台能力决定,不再需要用户配置: QQ 单聊和群聊的自定义 Markdown 已对所有机器人开放,固定走 Markdown 通道;频道场景仍需向 QQ 申请内邀开通,适配器会先尝试 Markdown,被平台以权限错误拒绝后自动降级为普通消息,并记住这个 机器人,本次运行内不再重试。开通后重启 Karin(或改一次配置)即可恢复。配置文件里残留的 markdown 字段会被忽略,下次保存配置时自动清除。

频道降级为普通消息后按钮无法发送——平台的 keyboard 只能挂在 Markdown 消息上。

按钮

按钮一般和 Markdown 一起发送,常用有三种:

  • 跳转按钮:点击后打开 link。
  • 指令按钮:点击后把 data 发送成一条普通消息。
  • 回调按钮:点击后不会在聊天框发消息,但适配器会下发一条 Karin 消息事件,消息内容就是 data。

下面这个示例先发送一组按钮,然后分别接住“指令按钮”和“回调按钮”的点击结果:

import karin, { segment } from 'node-karin'

export const buttonDemo = karin.command(/^按钮示例$/, async (e) => {
  await e.reply([
    segment.markdown('#### 按钮示例\n请选择一个操作:'),
    segment.button([
      { text: '打开文档', link: 'https://bot.q.qq.com/wiki/' },
      { text: '发送指令', data: '按钮示例 帮助', enter: true },
      { text: '回调确认', callback: true, data: '按钮示例 确认' },
    ]),
  ])
})

export const buttonHelp = karin.command(/^按钮示例 帮助$/, async (e) => {
  await e.reply('这是指令按钮发送出来的消息。')
})

export const buttonConfirm = karin.command(/^按钮示例 确认$/, async (e) => {
  await e.reply(`收到回调按钮:${e.msg}`)
})

如果你希望回复自动带上一组按钮,可以把按钮单独注册出来。下面这个分页示例会根据当前消息生成“上一页 / 下一页”:

import karin, { segment } from 'node-karin'

const getPage = (msg = '') => Number(msg.match(/^菜单(?:\s+(\d+))?$/)?.[1] || 1)

export const menuDemo = karin.command(/^菜单(?:\s+\d+)?$/, async (e) => {
  const page = getPage(e.msg)
  await e.reply(segment.markdown(`#### 菜单\n当前第 ${page} 页`))
})

export const menuKeyboard = karin.button(/^菜单(?:\s+\d+)?$/, (next, args) => {
  const page = getPage(args?.e?.msg)

  return segment.keyboard([
    [
      { text: '上一页', data: `菜单 ${Math.max(1, page - 1)}`, enter: true },
      { text: '下一页', data: `菜单 ${page + 1}`, enter: true },
    ],
  ])
})

简单理解:karin.button 是“自动追加按钮”的规则。适配器回复时会自动用 buttonHandle(e.msg, { e }) 查找匹配规则,所以用户发送 菜单 2,就会命中 /^菜单(?:\s+\d+)?$/,按钮函数再通过 args?.e?.msg 算出当前页。

自己调用 buttonHandle 时只记三点:

  • 参数一是匹配文本,通常填 e.msg,也可以是 '菜单'。
  • 参数二是给按钮函数的上下文,常用 { e };需要状态可以写 { e, page: 2 }。
  • 一个规则里调用 next(),才会继续匹配后面的规则。

回调按钮的 data 会变成一条 Karin 消息内容,所以建议直接写成插件能识别的命令,例如 按钮示例 确认、菜单 下一页。

发送消息与资源文件

适配器会尽量帮你发送图片、视频、语音和文件。推荐配置 fileToUrl 上传处理器,把本地文件、截图、Base64 等资源上传到你的图床、对象存储或 CDN,并返回一个 QQ 能访问的链接。

配置 fileToUrl 后:

  • 本地图片可以正常嵌入 Markdown 消息。
  • 视频、语音和文件会优先使用你返回的链接发送,通常比直接上传给 QQ 更稳定。
  • 如果资源本身已经是 http / https 链接,适配器会直接使用它。

没有配置 fileToUrl 时:

  • 单独发送图片、视频、语音、文件时,适配器会尝试直接交给 QQ 发送。
  • 较大的资源会使用 QQ 的大文件上传流程,优先保证消息能发出去。
  • 较大的图片或视频直接交给 QQ 发送时,QQ 客户端可能会把它显示成群文件,而不是图片或视频卡片;配置 fileToUrl 后通常可以避免这种显示问题。
  • 直接交给 QQ 只是兜底方案,生产环境仍然建议准备自己的文件服务。

注意:Markdown 里的图片依赖 fileToUrl。

Markdown 里的图片只能写成 QQ 能访问的链接,适配器不能把 Markdown 文本里的图片自动当成附件上传。QQ 单聊和群聊有下面提到的内置临时图床可以兜住,频道场景则必须自己配置 fileToUrl。

你可以在自己的 Karin 插件中编写并注册 fileToUrl Handler:

// plugins/karin-plugin-example/fileToUrl.js
import karin, { common } from 'node-karin'
import size from 'image-size'

export const uploadResource = karin.handler('fileToUrl', async (args) => {
  const { file, type, filename } = args
  const buffer = await common.buffer(file)

  // 由你实现:上传到图床/对象存储,返回可公开访问的 URL。
  const url = await uploadToYourStorage(buffer, filename || 'file.bin')

  if (type !== 'image') return { url }

  const dimension = size(buffer) // 获取图片宽高
  return {
    url,
    width: dimension.width || 100,
    height: dimension.height || 100
  }
})

注意:Handler 插件的 key 必须精确为 fileToUrl。

图片必须返回 { url, width, height };其他资源返回 { url }。

建议生产环境都配置 fileToUrl。这样图片、视频和文件都可以先上传到你自己的文件服务,再交给 QQ 发送,成功率和可控性都会更好。

没有自己的图床也不至于完全用不了 Markdown 图片:适配器内置了一个基于 QQ 官方分片上传的临时图床,QQ 单聊和群聊里会自动生效,把本地图片、截图、Base64 图片换成临时直链后嵌进 Markdown。它排在你自己的 fileToUrl 之后,只在你没有配置、或者你的图床这次没接手时才出手,拿到的地址会过期,因此仅供当次发送使用。频道场景和文件类型用不了它,仍然需要自备 fileToUrl。

事件

  • 支持 QQ 单聊、群聊、频道、频道私信和按钮回调。
  • 支持 GROUP_MESSAGE_CREATE 全量群消息和 author.member_role 身份字段。
  • 支持 GROUP_MEMBER_ADD、GROUP_MEMBER_REMOVE 群成员进退群事件。
  • 单聊同一 msg_id 最多回复 4 次;群聊规则保持官方限制。

开发

pnpm install
pnpm build

License

MIT