
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
chat-adapter-qq
Advanced tools
npm install chat chat-adapter-qq
参考 NapCat 文档部署一个正向 WebSocket 服务端.
参考 node-napcat-ts 配置连接信息.
import { Chat } from 'chat';
import { createMemoryState } from '@chat-adapter/state-memory';
import { createQQAdapter } from 'chat-adapter-qq';
const bot = new Chat({
userName: '',
adapters: {
qq: createQQAdapter({
napcat: {
protocol: 'wss',
host: '<your napcat host>',
port: 443,
accessToken: '<your napcat access token>',
// ↓ 自动重连 (可选)
reconnection: {
enable: true,
attempts: 10,
delay: 5000
}
}
})
},
state: createMemoryState()
});
await bot.initialize();
bot.onNewMention(async (thread, message) => {
bot.getLogger(thread.adapter.name).info('onNewMention', message);
await thread.subscribe();
await thread.post(`订阅频道: ${message.text}`);
});
bot.onSubscribedMessage(async (thread, message) => {
bot.getLogger(thread.adapter.name).info('onSubscribedMessage', message);
await thread.post(`收到消息: ${message.text}`);
});
示例脚本见: examples/chat.ts.
bot.onNewMention(async (thread, message) => {
await thread.subscribe();
await thread.post(`已开始监听当前会话: ${message.text}`);
});
bot.onSubscribedMessage(async (thread, message) => {
await thread.post(`收到消息: ${message.text}`);
});
bot.onSubscribedMessage(async (thread, message) => {
await thread.post({
reply: message.id,
markdown: `@${message.author.userId} 收到`
});
await thread.post({
forward: thread.recentMessages.slice(-3).map((item) => item.id),
markdown: ''
});
});
import fs from 'node:fs';
import path from 'node:path';
const filename = 'assets/avatar.jpeg';
bot.onSubscribedMessage(async (thread, message) => {
await thread.post({
markdown: '本地文件上传',
files: [
{
data: await fs.promises.readFile(filename),
filename: path.basename(filename),
mimeType: 'image/jpeg'
}
]
});
});
收到的 QQ 消息会被统一解析成 text、formatted 和 attachments.
QQ 适配器会处理文本, @提及, 图片, 文件, 视频, 音频, 引用消息, 消息合并转发等格式.
import { stringifyMarkdown } from 'chat';
bot.onSubscribedMessage(async (_thread, message) => {
console.log('plain text:', message.text);
console.log('markdown:', stringifyMarkdown(message.formatted));
console.log('attachments:', message.attachments);
});
收到消息后,可以直接读取 message.attachments.
bot.onSubscribedMessage(async (_thread, message) => {
for (const attachment of message.attachments) {
console.log(attachment.type, attachment.name, attachment.url, attachment.size);
}
});
QQ 适配器额外提供了 refreshAttachment 方法, 用于在附件链接过期时可以重新获取资源.
const adapter = bot.getAdapter('qq');
bot.onSubscribedMessage(async (_thread, message) => {
for (const attachment of message.attachments) {
const refreshed = await adapter.refreshAttachment(attachment);
console.log('old url:', attachment.url);
console.log('new url:', refreshed.url);
}
});
如果你有持久化消息需求, 应该完整保存 attachment 对象, 以调用 refreshAttachment 方法获取新的资源临时链接.
const adapter = bot.getAdapter('qq');
const attachment = {
type: 'image',
name: 'image.png',
url: 'https://example.com/image.png',
size: 12,
qq: {
kind: 'image',
file: '...'
}
};
const refreshed = await adapter.refreshAttachment(attachment);
import { emoji } from 'chat';
const adapter = bot.getAdapter('qq');
bot.onSubscribedMessage(async (thread, message) => {
await thread.startTyping('typing');
await adapter.addReaction(thread.id, message.id, emoji.thumbs_up);
await adapter.removeReaction(thread.id, message.id, '128077');
});
const adapter = bot.getAdapter('qq');
const latest = await adapter.fetchMessages('qq:group:30003', { limit: 20 });
console.log(latest.messages.map((item) => [item.id, item.text]));
if (latest.nextCursor) {
const older = await adapter.fetchMessages('qq:group:30003', {
limit: 20,
cursor: latest.nextCursor
});
console.log(older.messages.map((item) => [item.id, item.text]));
}
const adapter = bot.getAdapter('qq');
const threadInfo = await adapter.fetchThread('qq:group:30003');
const members = await adapter.fetchThreadMembers('qq:group:30003');
const member = await adapter.fetchThreadMember('qq:group:30003', '20002');
const dmThreadId = await adapter.openDM('20002');
console.log(threadInfo.channelName);
console.log(members.length);
console.log(member?.userName);
console.log(dmThreadId); // qq:private:20002
MIT License © 2026 XLor
FAQs
QQ adapter for Chat SDK based on NapCat
The npm package chat-adapter-qq receives a total of 23 weekly downloads. As such, chat-adapter-qq popularity was classified as not popular.
We found that chat-adapter-qq demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.