UNPKG

yunzai-micro-plugin

Version:

Yunzai开发管理面板

1,169 lines (1,168 loc) 54.8 kB
import path from 'node:path'; import { randomUUID } from 'crypto'; import '../../../../../utils/index.js'; import { botInfo } from '../../../../../env.js'; import { pokeMap, faceMap } from '../../common/face.js'; import BotAPI from '../tools.js'; import Stdlog from '../../../../../utils/stdlog.js'; class OnebotV11 { bot; id; name; path; echo; timeout; constructor(bot, req) { this.bot = bot; this.id = "114514"; if (req) this.id = req.headers['x-self-id'] ?? ''; this.name = "OneBotv11"; this.path = this.name; this.echo = {}; this.timeout = 60000; bot.on('message', async (data) => { await this.message(data, bot); }); bot.on('error', async (error) => Stdlog.error('', error)); bot.on('close', () => Stdlog.info('Onebotv11', `${this.id} 连接已断开!`)); Stdlog.info('Onebotv11', '载入成功!'); } makeLog(msg) { return BotAPI.String(msg).replace(/base64:\/\/.*?(,|]|")/g, "base64://...$1"); } sendApi(data, ws, action, params = {}) { const echo = randomUUID(); const request = { action, params, echo }; ws.send(JSON.stringify(request)); return new Promise((resolve, reject) => this.echo[echo] = { request, resolve, reject, timeout: setTimeout(() => { reject(Object.assign(request, { timeout: this.timeout })); delete this.echo[echo]; Stdlog.error(data.self_id, "请求超时", request); ws.terminate(); }, this.timeout), }); } async getReceivedMsg(message_id) { const msg = (await Bot[this.id].sendApi("get_msg", { message_id })).data; return msg; } async getMsg(data, message_id) { const msg = (await data.bot.sendApi("get_msg", { message_id })).data; if (msg?.message) msg.message = (await this.parseMsg(msg.message, data)).message; return msg; } async source(i, data) { const msg_id = i.data.id; if (!msg_id) return false; let source; try { let retryCount = 0; while (retryCount < 2) { source = await this.getReceivedMsg(msg_id); if (typeof source === 'string') { Stdlog.error(this.id, `获取引用消息内容失败,正在重试:第 ${retryCount} 次`); retryCount++; } else { break; } } if (typeof source === 'string') { Stdlog.error(this.id, '获取引用消息内容失败,重试次数上限,已终止'); return false; } Stdlog.debug('', source); let { message, raw_message } = await this.parseMsg(source.message, data, false); source = { ...source, time: source.message_id, seq: source.message_id, user_id: source.sender.user_id, message: message, raw_message }; return source; } catch (error) { Stdlog.error('', error); return false; } } async makeFile(file) { file = await BotAPI.Buffer(file, { http: true }); if (Buffer.isBuffer(file)) file = `base64://${file.toString("base64")}`; return file; } async makeMsg(msg) { if (!Array.isArray(msg)) msg = [msg]; const msgs = []; const forward = []; for (let i of msg) { if (typeof i !== "object") { i = { type: "text", data: { text: i } }; } else if (!i.data) { i = { type: i.type, data: { ...i, type: undefined } }; } switch (i.type) { case "at": i.data.qq = String(i.data.qq); break; case "face": i.data.id = String(i.data.id); break; case "poke": i.data.id = String(i.data.id ? i.data.id : i.data.qq); break; case "dice": i.data.id = String(i.data.id); break; case 'new_dice': i.data.id = String(i.data.id); break; case "rps": i.data.id = String(i.data.id); break; case "reply": i.data.id = String(i.data.id); break; case "button": console.log(i); break; case "node": forward.push(...i.data); continue; case "raw": i = i.data; break; } if (i.data.file) i.data.file = await this.makeFile(i.data.file); msgs.push(i); } return [msgs, forward]; } async sendMsg(msg, send, sendForwardMsg) { const [message, forward] = await this.makeMsg(msg); const ret = []; if (forward.length) { const data = await sendForwardMsg(forward); if (Array.isArray(data)) ret.push(...data); else ret.push(data); } if (message.length) ret.push(await send(message)); if (ret.length === 1) return ret[0]; const message_id = []; for (const i of ret) if (i?.message_id) message_id.push(i.message_id); return { data: ret, message_id }; } sendFriendMsg(data, msg) { return this.sendMsg(msg, message => { Stdlog.info(`${data.self_id} => ${data.user_id}`, `发送好友消息:${this.makeLog(message)}`); data.bot.sendApi("send_msg", { user_id: data.user_id, message, }); }, msg => this.sendFriendForwardMsg(data, msg)); } sendGroupMsg(data, msg) { return this.sendMsg(msg, message => { Stdlog.info(`${data.self_id} => ${data.group_id}`, `发送群消息:${this.makeLog(message)}`); return data.bot.sendApi("send_msg", { group_id: data.group_id, message, }); }, msg => this.sendGroupForwardMsg(data, msg)); } sendGuildMsg(data, msg) { return this.sendMsg(msg, message => { Stdlog.info(`${data.self_id}] => ${data.guild_id}-${data.channel_id}`, `发送频道消息:${this.makeLog(message)}`); return data.bot.sendApi("send_guild_channel_msg", { guild_id: data.guild_id, channel_id: data.channel_id, message, }); }, msg => Bot.sendForwardMsg ? Bot.sendForwardMsg(msg => this.sendGuildMsg(data, msg), msg) : BotAPI.sendForwardMsg(msg => this.sendGuildMsg(data, msg), msg)); } async recallMsg(data, message_id) { Stdlog.info(data.self_id, `撤回消息:${message_id}`); if (!Array.isArray(message_id)) message_id = [message_id]; const msgs = []; for (const i of message_id) msgs.push(await data.bot.sendApi("delete_msg", { message_id: i })); return msgs; } async parseMsg(msg, data, parseReply = true) { let file; let source; let message = []; let ToString_arr = []; let log_message_arr = []; let raw_message_arr = []; for (let i of Array.isArray(msg) ? msg : [msg]) { switch (i.type) { case 'at': message.push({ type: 'at', ...i.data }); try { let qq = i.data.qq; ToString_arr.push(`{at:${qq}}`); let groupMemberList = data.group_id ? (Bot[this.id].gml.get(data.group_id)?.get(qq)) : (Bot[this.id].gl.get(data.user_id)?.get(qq)); let at = groupMemberList?.nickname || groupMemberList?.card || qq; raw_message_arr.push(`@${at}`); log_message_arr.push(at == qq ? `@${qq}` : `<@${at}:${qq}>`); } catch (err) { raw_message_arr.push(`@${i.data.qq}`); log_message_arr.push(`@${i.data.qq}`); } break; case 'text': message.push({ type: 'text', text: i.data.text }); raw_message_arr.push(i.data.text); log_message_arr.push(i.data.text); ToString_arr.push(i.data.text); break; case 'face': message.push({ type: 'face', ...i.data }); raw_message_arr.push(`[${faceMap[Number(i.data.id)] || '动画表情'}]`); log_message_arr.push(`<${faceMap[Number(i.data.id)] || `动画表情:${i.data.id}`}>`); ToString_arr.push(`{face:${i.data.id}}`); break; case 'reply': if (parseReply) source = await this.source(i, data); if (source && data.group_id) { let qq = Number(source.sender.user_id); let text = source.sender.nickname; message.unshift({ type: 'at', qq, text }); raw_message_arr.unshift(`@${text}`); log_message_arr.unshift(`<回复:${text}(${qq})>`); } break; case 'image': message.push({ ...i.data, type: 'image' }); raw_message_arr.push('[图片]'); log_message_arr.push(`<图片:${i.data?.url || i.data.file}>`); ToString_arr.push(`{image:${i.data.file}}`); break; case 'record': message.push({ type: 'record', ...i.data }); raw_message_arr.push('[语音]'); log_message_arr.push(`<语音:${i.data?.url || i.data.file}>`); ToString_arr.push(`{record:${i.data.file}}`); break; case 'video': message.push({ type: 'video', ...i.data }); raw_message_arr.push('[视频]'); log_message_arr.push(`<视频:${i.data?.url || i.data.file}>`); ToString_arr.push(`{video:${i.data.file}}`); break; case 'file': file = { ...i.data, fid: i.data.id }; message.push({ type: 'file', ...i.data, fid: i.data.id }); raw_message_arr.push('[文件]'); log_message_arr.push(`<视频:${i.data?.url || i.data.file}>`); ToString_arr.push(`{file:${i.data.id}}`); redis.set(i.data.id, JSON.stringify(i.data)); break; case 'forward': message.push({ type: 'node', ...i.data }); raw_message_arr.push('[转发消息]'); log_message_arr.push(`<转发消息:${JSON.stringify(i.data)}>`); ToString_arr.push(`{forward:${i.data.id}}`); break; case 'json': message.push({ type: 'json', ...i.data }); raw_message_arr.push('[json消息]'); log_message_arr.push(`<json消息:${i.data.data}>`); ToString_arr.push(i.data.data); break; case 'xml': message.push({ type: 'xml', ...i.data }); raw_message_arr.push('[xml消息]'); log_message_arr.push(`<xml消息:${i.data}>`); ToString_arr.push(i.data.data); break; case 'basketball': message.push({ type: 'basketball', ...i.data }); raw_message_arr.push('[篮球]'); log_message_arr.push(`<篮球:${i.data.id}>`); ToString_arr.push(`{basketball:${i.data.id}}`); break; case 'new_rps': message.push({ type: 'new_rps', ...i.data }); raw_message_arr.push('[猜拳]'); log_message_arr.push(`<猜拳:${i.data.id}>`); ToString_arr.push(`{new_rps:${i.data.id}}`); break; case 'new_dice': message.push({ type: 'new_dice', ...i.data }); raw_message_arr.push('[骰子]'); log_message_arr.push(`<骰子:${i.data.id}>`); ToString_arr.push(`{new_dice:${i.data.id}}`); break; case 'dice': message.push({ type: 'dice', ...i.data }); raw_message_arr.push('[骰子]'); log_message_arr.push(`<骰子:${i.data.id}>`); ToString_arr.push(`{dice:${i.data}}`); break; case 'rps': message.push({ type: 'rps', ...i.data }); raw_message_arr.push('[剪刀石头布]'); log_message_arr.push(`<剪刀石头布:${i.data.id}>`); ToString_arr.push(`{rps:${i.data}}`); break; case 'poke': message.push({ type: 'poke', ...i.data }); raw_message_arr.push(`[${pokeMap[Number(i.data.id)]}]`); log_message_arr.push(`<${pokeMap[Number(i.data.id)]}>`); ToString_arr.push(`{poke:${i.data.id}}`); break; case 'touch': message.push({ type: 'touch', ...i.data }); raw_message_arr.push('[双击头像]'); log_message_arr.push(`<<双击头像:${i.data.id}>`); ToString_arr.push(`{touch:${i.data.id}}`); break; case 'music': message.push({ type: 'music', ...i.data }); raw_message_arr.push('[音乐]'); log_message_arr.push(`<音乐:${i.data.id}>`); ToString_arr.push(`{music:${i.data.id}}`); break; case 'custom': message.push({ type: 'custom', ...i.data }); raw_message_arr.push('[自定义音乐]'); log_message_arr.push(`<自定义音乐:${i.data.url}>`); ToString_arr.push(`{custom:${i.data.url}}`); break; case 'weather': message.push({ type: 'weather', ...i.data }); raw_message_arr.push('[天气]'); log_message_arr.push(`<天气:${i.data.city}>`); ToString_arr.push(`{weather:${i.data.city}}`); break; case 'location': message.push({ type: 'location', ...i.data }); raw_message_arr.push('[位置分享]'); log_message_arr.push(`<位置分享:${i.data.lat}-${i.data.lon}>`); ToString_arr.push(`{location:${i.data.lat}-${i.data.lon}}`); break; case 'share': message.push({ type: 'share', ...i.data }); raw_message_arr.push('[链接分享]'); log_message_arr.push(`<<链接分享:${i.data.url}>`); ToString_arr.push(`{share:${i.data.url}}`); break; case 'gift': message.push({ type: 'gift', ...i.data }); raw_message_arr.push('[礼物]'); log_message_arr.push(`<礼物:${i.data.id}>`); ToString_arr.push(`{gift:${i.data.id}}`); break; case 'markdown': message.push({ type: 'markdown', ...i.data }); raw_message_arr.push('[markdown]'); log_message_arr.push(`<markdown:${i.data}>`); ToString_arr.push(`{markdown:${i.data}}`); break; case 'button': message.push({ type: 'button', ...i.data }); raw_message_arr.push('[button]'); log_message_arr.push(`<button:${i.data}>`); ToString_arr.push(`{button:${i.data}}`); break; case 'keyboard': message.push({ type: 'keyboard', ...i.data }); raw_message_arr.push('[keyboard]'); log_message_arr.push(`<keyboard:${i.data}>`); ToString_arr.push(`{keyboard:${i.data}}`); break; default: message.push({ type: i.type, ...i.data }); i = JSON.stringify(i); raw_message_arr.push(i); log_message_arr.push(i); ToString_arr.push(i); break; } } const ToString = ToString_arr.join('').trim(); const raw_message = raw_message_arr.join('').trim(); const log_message = log_message_arr.join(' ').trim(); return { message, ToString, raw_message, log_message, source, file }; } async getGroupMsgHistory(data, message_seq, count) { const msgs = (await data.bot.sendApi("get_group_msg_history", { group_id: data.group_id, message_seq, message_id: message_seq, count, })).data?.messages; for (const i of Array.isArray(msgs) ? msgs : [msgs]) { if (i?.message) i.message = (await this.parseMsg(i.message, data, false)).message; if (!i?.group_name) i.group_name = data?.group_name || data?.group_id; } return msgs; } async getFriendMsgHistory(data, message_seq, count) { const msgs = (await data.bot.sendApi("get_friend_msg_history", { user_id: data.user_id, message_seq, message_id: message_seq, count, })).data?.messages; for (const i of Array.isArray(msgs) ? msgs : [msgs]) { if (i?.message) i.message = (await this.parseMsg(i.message, data, false)).message; } return msgs; } async getForwardMsg(data, message_id) { const msgs = (await data.bot.sendApi("get_forward_msg", { message_id, id: message_id })).data?.messages; for (const i of Array.isArray(msgs) ? msgs : [msgs]) if (i?.message) i.message = (await this.parseMsg(i.message || i.content, data)).message; return msgs; } async makeForwardMsg(msg) { const msgs = []; for (const i of msg) { const [content, forward] = await this.makeMsg(i.message); if (forward.length) msgs.push(...await this.makeForwardMsg(forward)); if (content.length) msgs.push({ type: "node", data: { name: i.nickname || "匿名消息", uin: String(Number(i.user_id) || 80000000), content, time: i.time, } }); } return msgs; } async sendFriendForwardMsg(data, msg) { Stdlog.info(`${data.self_id} => ${data.user_id}`, `发送好友转发消息:${this.makeLog(msg)}`); return data.bot.sendApi("send_private_forward_msg", { user_id: data.user_id, messages: await this.makeForwardMsg(msg), }); } async sendGroupForwardMsg(data, msg) { Stdlog.info(`${data.self_id} => ${data.group_id}`, `发送群转发消息:${this.makeLog(msg)}`); return data.bot.sendApi("send_group_forward_msg", { group_id: data.group_id, messages: await this.makeForwardMsg(msg), }); } async getFriendArray(data) { return (await data.bot.sendApi("get_friend_list")).data || []; } async getFriendList(data) { const array = []; for (const { user_id } of await this.getFriendArray(data)) array.push(user_id); return array; } async getFriendMap(data) { const map = new Map; for (const i of await this.getFriendArray(data)) map.set(i.user_id, i); data.bot.fl = map; return map; } getFriendInfo(data) { return data.bot.sendApi("get_stranger_info", { user_id: data.user_id, }); } async getGroupArray(data) { const array = (await data.bot.sendApi("get_group_list")).data; try { for (const guild of await this.getGuildArray(data)) for (const channel of await this.getGuildChannelArray({ ...data, guild_id: guild.guild_id, })) array.push({ guild, channel, group_id: `${guild.guild_id}-${channel.channel_id}`, group_name: `${guild.guild_name}-${channel.channel_name}`, }); } catch (err) { } return array; } async getGroupList(data) { const array = []; for (const { group_id } of await this.getGroupArray(data)) array.push(group_id); return array; } async getGroupMap(data) { const map = new Map; for (const i of await this.getGroupArray(data)) map.set(i.group_id, i); data.bot.gl = map; return map; } getGroupInfo(data) { return data.bot.sendApi("get_group_info", { group_id: data.group_id }); } async getMemberArray(data) { return (await data.bot.sendApi("get_group_member_list", { group_id: data.group_id, })).data || []; } async getMemberList(data) { const array = []; for (const { user_id } of await this.getMemberArray(data)) array.push(user_id); return array; } async getMemberMap(data) { const map = new Map; for (const i of await this.getMemberArray(data)) map.set(i.user_id, i); data.bot.gml.set(data.group_id, map); return map; } async getGroupMemberMap(data) { for (const [group_id, group] of await this.getGroupMap(data)) { if (group.guild) continue; await this.getMemberMap({ ...data, group_id }); } } getMemberInfo(data) { return data.bot.sendApi("get_group_member_info", { group_id: data.group_id, user_id: data.user_id, }); } async getGuildArray(data) { return (await data.bot.sendApi("get_guild_list")).data || []; } getGuildInfo(data) { return data.bot.sendApi("get_guild_meta_by_guest", { guild_id: data.guild_id, }); } async getGuildChannelArray(data) { return (await data.bot.sendApi("get_guild_channel_list", { guild_id: data.guild_id, })).data || []; } async getGuildChannelMap(data) { const map = new Map; for (const i of await this.getGuildChannelArray(data)) map.set(i.channel_id, i); return map; } async getGuildMemberArray(data) { const array = []; let next_token = ""; while (true) { const list = (await data.bot.sendApi("get_guild_member_list", { guild_id: data.guild_id, next_token, })).data; if (!list) break; for (const i of list.members) array.push({ ...i, user_id: i.tiny_id, }); if (list.finished) break; next_token = list.next_token; } return array; } async getGuildMemberList(data) { const array = []; for (const { user_id } of await this.getGuildMemberArray(data)) array.push(user_id); return array.push; } async getGuildMemberMap(data) { const map = new Map; for (const i of await this.getGuildMemberArray(data)) map.set(i.user_id, i); data.bot.gml.set(data.group_id, map); return map; } getGuildMemberInfo(data) { return data.bot.sendApi("get_guild_member_profile", { guild_id: data.guild_id, user_id: data.user_id, }); } setProfile(data, profile) { Stdlog.info(data.self_id, `设置资料:${BotAPI.String(profile)}`); return data.bot.sendApi("set_qq_profile", profile); } async setAvatar(data, file) { Stdlog.info(data.self_id, `设置头像:${file}`); return data.bot.sendApi("set_qq_avatar", { file: await this.makeFile(file), }); } sendLike(data, times) { Stdlog.info(`${data.self_id} => ${data.user_id}`, `点赞:${times}次`); return data.bot.sendApi("send_like", { user_id: data.user_id, times, }); } setGroupName(data, group_name) { Stdlog.info(`${data.self_id} => ${data.group_id}`, `设置群名:${group_name}`); return data.bot.sendApi("set_group_name", { group_id: data.group_id, group_name, }); } async setGroupAvatar(data, file) { Stdlog.info(`${data.self_id} => ${data.group_id}`, `设置群头像:${file}`); return data.bot.sendApi("set_group_portrait", { group_id: data.group_id, file: await this.makeFile(file), }); } setGroupAdmin(data, user_id, enable) { Stdlog.info(`${data.self_id} => ${data.group_id}`, `${enable ? "设置" : "取消"}群管理员:${user_id}`); return data.bot.sendApi("set_group_admin", { group_id: data.group_id, user_id, enable, }); } setGroupCard(data, user_id, card) { Stdlog.info(`${data.self_id} => ${data.group_id}, ${user_id}`, `设置群名片:${card}`); return data.bot.sendApi("set_group_card", { group_id: data.group_id, user_id, card, }); } setGroupTitle(data, user_id, special_title, duration) { Stdlog.info(`${data.self_id} => ${data.group_id}, ${user_id}`, `设置群头衔:${special_title} ${duration}`); return data.bot.sendApi("set_group_special_title", { group_id: data.group_id, user_id, special_title, duration, }); } sendGroupSign(data) { Stdlog.info(`${data.self_id} => ${data.group_id}`, "群打卡"); return data.bot.sendApi("send_group_sign", { group_id: data.group_id, }); } setGroupBan(data, user_id, duration) { Stdlog.info(`${data.self_id} => ${data.group_id}, ${user_id}`, `禁言群成员:${duration}秒`); return data.bot.sendApi("set_group_ban", { group_id: data.group_id, user_id, duration, }); } setGroupWholeKick(data, enable) { Stdlog.info(`${data.self_id} => ${data.group_id}`, `${enable ? "开启" : "关闭"}全员禁言`); return data.bot.sendApi("set_group_whole_ban", { group_id: data.group_id, enable, }); } setGroupKick(data, user_id, reject_add_request) { Stdlog.info(`${data.self_id} => ${data.group_id}, ${user_id}`, `踢出群成员${reject_add_request ? "拒绝再次加群" : ""}`); return data.bot.sendApi("set_group_kick", { group_id: data.group_id, user_id, reject_add_request, }); } setGroupLeave(data, is_dismiss) { Stdlog.info(`${data.self_id} => ${data.group_id}`, is_dismiss ? "解散" : "退群"); return data.bot.sendApi("set_group_leave", { group_id: data.group_id, is_dismiss, }); } downloadFile(data, url, thread_count, headers) { return data.bot.sendApi("download_file", { url, thread_count, headers, }); } async sendFriendFile(data, file, name = path.basename(file.slice(0, 16))) { Stdlog.info(`${data.self_id} => ${data.user_id}`, `发送好友文件:${name}(${file})`); return data.bot.sendApi("upload_private_file", { user_id: data.user_id, file: await this.makeFile(file), name, }); } async sendGroupFile(data, file, folder, name = path.basename(file.slice(0, 16))) { Stdlog.info(`${data.self_id} => ${data.group_id}`, `发送群文件:${folder || ""}/${name}(${file})`); return data.bot.sendApi("upload_group_file", { group_id: data.group_id, folder, file: await this.makeFile(file), name, }); } deleteGroupFile(data, file_id, busid) { Stdlog.info(`${data.self_id} => ${data.group_id}`, `删除群文件:${file_id}(${busid})`); return data.bot.sendApi("delete_group_file", { group_id: data.group_id, file_id, busid, }); } createGroupFileFolder(data, name) { Stdlog.info(`${data.self_id} => ${data.group_id}`, `创建群文件夹:${name}`); return data.bot.sendApi("create_group_file_folder", { group_id: data.group_id, name, }); } getGroupFileSystemInfo(data) { return data.bot.sendApi("get_group_file_system_info", { group_id: data.group_id, }); } getGroupFiles(data, folder_id) { if (folder_id) return data.bot.sendApi("get_group_files_by_folder", { group_id: data.group_id, folder_id, }); return data.bot.sendApi("get_group_root_files", { group_id: data.group_id, }); } getGroupFileUrl(data, file_id, busid) { return data.bot.sendApi("get_group_file_url", { group_id: data.group_id, file_id, busid, }); } getGroupFs(data) { return { upload: (file, folder, name) => this.sendGroupFile(data, file, folder, name), rm: (file_id, busid) => this.deleteGroupFile(data, file_id, busid), mkdir: name => this.createGroupFileFolder(data, name), df: () => this.getGroupFileSystemInfo(data), ls: folder_id => this.getGroupFiles(data, folder_id), download: (file_id, busid) => this.getGroupFileUrl(data, file_id, busid), }; } setFriendAddRequest(data, flag, approve, remark) { return data.bot.sendApi("set_friend_add_request", { flag, approve, remark, }); } setGroupAddRequest(data, flag, sub_type, approve, reason) { return data.bot.sendApi("set_group_add_request", { flag, sub_type, approve, reason, }); } pickFriend(data, user_id) { const i = { ...data.bot.fl.get(user_id), ...data, user_id, }; return { ...i, sendMsg: msg => this.sendFriendMsg(i, msg), getMsg: message_id => this.getMsg(i, message_id), recallMsg: message_id => this.recallMsg(i, message_id), getForwardMsg: message_id => this.getForwardMsg(i, message_id), getChatHistory: (seq, cnt) => this.getFriendMsgHistory(i, seq, cnt), sendForwardMsg: msg => this.sendFriendForwardMsg(i, msg), sendFile: (file, name) => this.sendFriendFile(i, file, name), getInfo: () => this.getFriendInfo(i), getAvatarUrl: () => i.avatar || `https://q.qlogo.cn/g?b=qq&s=0&nk=${user_id}`, thumbUp: times => this.sendLike(i, times), }; } pickMember(data, group_id, user_id) { if (typeof group_id === "string" && group_id.match("-")) { const guild_id = group_id.split("-"); const i = { ...data, guild_id: guild_id[0], channel_id: guild_id[1], user_id, }; return { ...this.pickGroup(i, group_id), ...i, getInfo: () => this.getGuildMemberInfo(i), getAvatarUrl: async () => (await this.getGuildMemberInfo(i)).avatar_url, }; } const i = { ...data.bot.fl.get(user_id), ...data.bot.gml.get(group_id)?.get(user_id), ...data, group_id, user_id, }; return { ...this.pickFriend(i, user_id), ...i, getInfo: () => this.getMemberInfo(i), getAvatarUrl: () => i.avatar || `https://q.qlogo.cn/g?b=qq&s=0&nk=${user_id}`, poke: () => this.sendGroupMsg(i, { type: "poke", qq: user_id, id: String(user_id) }), mute: duration => this.setGroupBan(i, i.user_id, duration), kick: reject_add_request => this.setGroupKick(i, i.user_id, reject_add_request), get is_friend() { return data.bot.fl.has(user_id); }, get is_owner() { return i.role === "owner"; }, get is_admin() { return i.role === "admin"; }, }; } pickGroup(data, group_id) { if (typeof group_id === "string" && group_id.match("-")) { const guild_id = group_id.split("-"); const i = { ...data.bot.gl.get(group_id), ...data, guild_id: guild_id[0], channel_id: guild_id[1], }; return { ...i, sendMsg: msg => this.sendGuildMsg(i, msg), getMsg: message_id => this.getMsg(i, message_id), recallMsg: message_id => this.recallMsg(i, message_id), getForwardMsg: message_id => this.getForwardMsg(i, message_id), getInfo: () => this.getGuildInfo(i), getChannelArray: () => this.getGuildChannelArray(i), getChannelList: () => this.getGuildChannelMap(i), getChannelMap: () => this.getGuildChannelMap(i), getMemberArray: () => this.getGuildMemberArray(i), getMemberList: () => this.getGuildMemberList(i), getMemberMap: () => this.getGuildMemberMap(i), pickMember: user_id => this.pickMember(i, group_id, user_id), }; } const i = { ...data.bot.gl.get(group_id), ...data, group_id, }; return { ...i, sendMsg: msg => this.sendGroupMsg(i, msg), getMsg: message_id => this.getMsg(i, message_id), recallMsg: message_id => this.recallMsg(i, message_id), getForwardMsg: message_id => this.getForwardMsg(i, message_id), sendForwardMsg: msg => this.sendGroupForwardMsg(i, msg), sendFile: (file, name) => this.sendGroupFile(i, file, undefined, name), getInfo: () => this.getGroupInfo(i), getAvatarUrl: () => i.avatar || `https://p.qlogo.cn/gh/${group_id}/${group_id}/0`, getChatHistory: (seq, cnt) => this.getGroupMsgHistory(i, seq, cnt), getMemberArray: () => this.getMemberArray(i), getMemberList: () => this.getMemberList(i), getMemberMap: () => this.getMemberMap(i), pickMember: user_id => this.pickMember(i, group_id, user_id), pokeMember: qq => this.sendGroupMsg(i, { type: "poke", qq }), setName: group_name => this.setGroupName(i, group_name), setAvatar: file => this.setGroupAvatar(i, file), setAdmin: (user_id, enable) => this.setGroupAdmin(i, user_id, enable), setCard: (user_id, card) => this.setGroupCard(i, user_id, card), setTitle: (user_id, special_title, duration) => this.setGroupTitle(i, user_id, special_title, duration), sign: () => this.sendGroupSign(i), muteMember: (user_id, duration) => this.setGroupBan(i, user_id, duration), muteAll: enable => this.setGroupWholeKick(i, enable), kickMember: (user_id, reject_add_request) => this.setGroupKick(i, user_id, reject_add_request), quit: is_dismiss => this.setGroupLeave(i, is_dismiss), fs: this.getGroupFs(i), get is_owner() { return data.bot.gml.get(group_id)?.get(data.self_id)?.role === "owner"; }, get is_admin() { return data.bot.gml.get(group_id)?.get(data.self_id)?.role === "admin"; }, }; } async connect(data, ws) { if (!data.self_id) Stdlog.warn('Onebotv11', '未找到self_id!'); Bot[data.self_id] = { adapter: this.name, ws: ws, sendApi: (action, params) => this.sendApi(data, ws, action, params), stat: { start_time: data.time, stat: {}, get lost_pkt_cnt() { return this.stat.packet_lost; }, get lost_times() { return this.stat.lost_times; }, get recv_msg_cnt() { return this.stat.message_received; }, get recv_pkt_cnt() { return this.stat.packet_received; }, get sent_msg_cnt() { return this.stat.message_sent; }, get sent_pkt_cnt() { return this.stat.packet_sent; }, }, model: botInfo.BOT_NAME, info: { user_id: data.self_id, nickname: data.nickname }, self_id: data.self_id, uin: data.self_id, get nickname() { return this.info.nickname ?? data.self_id; }, get avatar() { return `https://q.qlogo.cn/g?b=qq&s=0&nk=${this.uin}`; }, setProfile: profile => this.setProfile(data, profile), setNickname: nickname => this.setProfile(data, { nickname }), setAvatar: file => this.setAvatar(data, file), pickFriend: user_id => this.pickFriend(data, user_id), sendPrivateMsg: (user_id, msg) => this.pickFriend(data, user_id).sendMsg(msg), get pickUser() { return this.pickFriend; }, getFriendArray: () => this.getFriendArray(data), getFriendList: () => this.getFriendList(data), getFriendMap: () => this.getFriendMap(data), fl: new Map, pickMember: (group_id, user_id) => this.pickMember(data, group_id, user_id), pickGroup: group_id => this.pickGroup(data, group_id), sendGroupMsg: (group_id, msg) => this.pickGroup(data, group_id).sendMsg(msg), getGroupArray: () => this.getGroupArray(data), getGroupList: () => this.getGroupList(data), getGroupMap: () => this.getGroupMap(data), getGroupMemberMap: () => this.getGroupMemberMap(data), gl: new Map, gml: new Map, request_list: [], getSystemMsg: () => data.bot.request_list, makeForwardMsg: msg => this.makeForwardMsg(msg), setFriendAddRequest: (flag, approve, remark) => this.setFriendAddRequest(data, flag, approve, remark), setGroupAddRequest: (flag, sub_type, approve, reason) => this.setGroupAddRequest(data, flag, sub_type, approve, reason), }; data.bot = Bot[data.self_id]; if (!Bot.adapter) Bot.adapter = []; if (!Bot.adapter?.includes(data.self_id)) Bot.adapter.push(data.self_id); data.bot.sendApi("_set_model_show", { model: data.bot.model, model_show: data.bot.model, }).catch(() => { }); data.bot.info = (await data.bot.sendApi("get_login_info").catch(i => i.error)).data; data.bot.guild_info = (await data.bot.sendApi("get_guild_service_profile").catch(i => i.error)).data; data.bot.clients = (await data.bot.sendApi("get_online_clients").catch(i => i.error)).clients; data.bot.version = { ...(await data.bot.sendApi("get_version_info").catch(i => i.error)).data, id: this.id, name: this.name, get version() { return this.app_full_name || `${this.app_name} v${this.app_version}`; }, }; data.bot.getFriendMap(); data.bot.getGroupMemberMap(); Stdlog.mark(data.self_id, `${this.name}(${this.id}) ${data.bot.version.version} 连接成功,协议通过,执行消息处理...`); BotAPI.$emit(`connect.${data.self_id}`, data); BotAPI.$emit("system.online", data.bot); } async sendReplyMsg(data, msg, quote, option) { if (typeof msg == 'string') { msg = [{ type: 'text', data: { text: msg } }]; } if (!Array.isArray(msg)) { msg = [msg]; } if (quote && data.message_id) { msg.unshift({ type: 'reply', data: { id: String(data.message_id) } }); } if (option?.at) { msg.unshift({ type: 'at', data: { qq: String(data.user_id) } }); } if (option?.recallMsg || option?.recallMsg === 0) { setTimeout(async () => { await this.recallMsg(data, data.message_id); }, option.recallMsg * 1000); } if (data.group_id) return await data.bot.sendGroupMsg(data.group_id, msg); return await data.bot.sendPrivateMsg(data.user_id, msg); } async makeMessage(data) { const { message, ToString, log_message, source, file } = await this.parseMsg(data.message, data); data.message = message; data.uin = this.id; data.log_message = log_message; data.toString = () => ToString; if (!data.reply) data.reply = async (msg, quote, option) => await this.sendReplyMsg(data, msg, quote, option); if (!data.getAvatarUrl) data.getAvatarUrl = (size = 0) => data.avatar || `https://q1.qlogo.cn/g?b=qq&s=${size}&nk=${data.user_id}`; if (!data.recall) data.recall = async () => await this.recallMsg(data, data.message_id); if (file) data.file = file; if (source) data.source = source; switch (data.message_type) { case "private": { const name = data.sender?.card || data.sender?.nickname || data.bot.fl.get(data.user_id)?.nickname; Stdlog.info(`${data.self_id} <= ${data.user_id}`, `好友消息:${name ? `[${name}] ` : ""}${log_message}`); break; } case "group": { if (!data.group_name) data.group_name = data.bot.gl.get(data.group_id)?.group_name; const group_name = data.group_name; let user_name = data.sender?.card || data.sender?.nickname; if (!user_name) { const user = data.bot.gml.get(data.group_id)?.get(data.user_id) || data.bot.fl.get(data.user_id); if (user) user_name = user?.card || user?.nickname; } Stdlog.info(`${data.self_id} <= ${data.group_id}, ${data.user_id}`, `群消息:${user_name ? (group_name ? '[群:' + group_name + '][成员:' + user_name + ']' : '') : ''}${log_message}`); break; } case "guild": data.message_type = "group"; data.group_id = `${data.guild_id}-${data.channel_id}`; Stdlog.info(`${data.self_id} <= ${data.group_id}, ${data.user_id}`, `频道消息:[${data.sender.nickname}] ${log_message}`); Object.defineProperty(data, "friend", { get() { return this.member || {}; } }); break; default: Stdlog.warn(data.self_id, `未知消息:${data.raw}`); } BotAPI.$emit(`${data.post_type}.${data.message_type}.${data.sub_type}`, data); } async makeNotice(data) { switch (data.notice_type) { case "friend_recall": Stdlog.info(`${data.self_id} <= ${data.user_id}`, `好友消息撤回:${data.message_id}`); break; case "group_recall": Stdlog.info(`${data.self_id} <= ${data.group_id}`, `群消息撤回:${data.operator_id} => ${data.user_id} ${data.message_id}`); break; case "group_increase": Stdlog.info(`${data.self_id} <= ${data.group_id}`, `群成员增加:${data.operator_id} => ${data.user_id} ${data.sub_type}`); if (data.user_id === data.self_id) data.bot.getGroupMemberMap(); else data.bot.pickGroup(data.group_id).getMemberMap(); break; case "group_decrease": Stdlog.info(`${data.self_id} <= ${data.group_id}`, `群成员减少:${data.operator_id} => ${data.user_id} ${data.sub_type}`); if (data.user_id === data.self_id) data.bot.getGroupMemberMap(); else data.bot.pickGroup(data.group_id).getMemberMap(); break; case "group_admin": Stdlog.info(`${data.self_id} <= ${data.group_id}, ${data.user_id}`, `群管理员变动:${data.sub_type}`); data.set = data.sub_type === "set"; break; case "group_upload": Stdlog.info(`${data.self_id} <= ${data.group_id}, ${data.user_id}`, `群文件上传:${BotAPI.String(data.file)}`); break; case "group_ban": Stdlog.info(`${data.self_id} <= ${data.group_id}`, `群禁言:${data.operator_id} => ${data.user_id} ${data.sub_type} ${data.duration}秒`); break; case "friend_add": Stdlog.info(`${data.self_id} <= ${data.user_id}`, "好友添加"); data.bot.getFriendMap(); break; case "notify": if (data.group_id) data.notice_type = "group"; else data.notice_type = "friend"; switch (data.sub_type) { case "poke": data.operator_id = data.user_id; if (data.group_id) Stdlog.info(`${data.self_id} <= ${data.group_id}`, `群戳一戳:${data.operator_id} => ${data.target_id}`); else Stdlog.info(data.self_id, `好友戳一戳:${data.operator_id} => ${data.target_id}`); break; case "honor": Stdlog.info(`${data.self_id} <= ${data.group_id}, ${data.user_id}`, `群荣誉:${data.honor_type}`); break; case "title": Stdlog.info(`${data.self_id} <= ${data.group_id}, ${data.user_id}`, `群头衔:${data.title}`); break; default: Stdlog.warn(data.self_id, `未知通知:${data.raw}`); } break; case "group_card": Stdlog.info(`${data.self_id} <= ${data.group_id}, ${data.user_id}`, `群名片更新:${data.card_old} => ${data.card_new}`); break; case "offline_file": Stdlog.info(`${data.self_id} <= ${data.user_id}`, `离线文件:${BotAPI.String(data.file)}`); break; case "client_status": Stdlog.info(data.self_id, `客户端${data.online ? "上线" : "下线"}:${BotAPI.String(data.client)}`); data.clients = (await data.bot.sendApi("get_online_clients")).clients; data.bot.clients = data.clients; break; case "essence": data.notice_type = "group_essence"; Stdlog.info(`${data.self_id} <= ${data.group_id}`, `群精华消息:${data.operator_id} => ${data.sender_id} ${data.sub_type} ${data.message_id}`); break; case "guild_channel_recall": Stdlog.info(`${data.self_id} <= ${data.guild_id}-${data.channel_id}`, `频道消息撤回:${data.operator_id} => ${data.user_id} ${data.message_id}`); break; case "message_reactions_updated": data.notice_type = "guild_message_reactions_updated"; Stdlog.info(`${data.self_id} <= ${data.guild_id}-${data.channel_id}, ${data.user_id}`, `频道消息表情贴:${data.message_id} ${BotAPI.String(data.current_reactions)}`); break; case "channel_updated": data.notice_type = "guild_channel_updated"; Stdlog.info(`${data.self_id} <= ${data.guild_id}-${data.channel_id}, ${data.user_id}`, `子频道更新:${BotAPI.String(data.old_info)} => ${BotAPI.String(data.new_info)}`); break; case "channel_created": data.notice_type = "guild_channel_created"; Stdlog.info(`${data.self_id} <= ${data.guild_id}-${data.channel_id}, ${data.user_id}`, `子频道创建:${BotAPI.String(data.channel_info)}`); data.bot.getGroupMap(); break; case "channel_destroyed": data.notice_type = "guild_channel_destroyed"; Stdlog.info(`${data.self_id} <= ${data.guild_id}-${data.channel_id}, ${data.user_id}`, `子频道删除:${BotAPI.String(data.channel_info)}`); data.bot.getGroupMap(); break; default: Stdlog.warn(data.self_id, `未知通知:${data.raw}`); } let notice = data.notice_type.split("_"); data.notice_type = notice.shift(); notice = notice.j