UNPKG

onebots

Version:

基于icqq的多例oneBot实现

419 lines (418 loc) 17.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _IcqqAdapter_password, _IcqqAdapter_disposes; Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultIcqqConfig = void 0; const adapter_1 = require("../../adapter"); const icqq_1 = require("@icqqjs/icqq"); const process_1 = __importDefault(require("process")); const fs_1 = require("fs"); const onebot_1 = require("../../onebot"); const path = __importStar(require("path")); const message_1 = require("@icqqjs/icqq/lib/message"); const utils_1 = require("../../adapters/icqq/utils"); class IcqqAdapter extends adapter_1.Adapter { constructor(app, config) { super(app, "icqq", config); _IcqqAdapter_password.set(this, void 0); _IcqqAdapter_disposes.set(this, new Map()); this.icon = `https://qzonestyle.gtimg.cn/qzone/qzact/act/external/tiqq/logo.png`; } async setOnline(uin) { const oneBot = this.getOneBot(uin); if (!oneBot) throw new Error("No one"); await oneBot.internal.login(parseInt(uin), __classPrivateFieldGet(this, _IcqqAdapter_password, "f")); } async setOffline(uin) { const oneBot = this.getOneBot(uin); if (!oneBot) throw new Error("No one"); await oneBot.internal.logout(); oneBot.status = onebot_1.OneBotStatus.OffLine; } callApi(uin, version, [name, args]) { const oneBot = this.getOneBot(uin); if (!oneBot) throw new Error("No one"); if (!oneBot.internal[name]) throw new Error(`internal no api ${name}`); return oneBot.internal[name](...args); } createOneBot(uin, protocol, versions) { const oneBot = super.createOneBot(uin, protocol, versions); __classPrivateFieldSet(this, _IcqqAdapter_password, this.app.config[`icqq.${uin}`].password, "f"); oneBot.avatar = `https://q1.qlogo.cn/g?b=qq&s=100&nk=` + uin; const pkg = require(path.resolve(path.dirname(require.resolve("@icqqjs/icqq")), "../package.json")); oneBot.dependency = `icqq v${pkg.version}`; oneBot.status = onebot_1.OneBotStatus.Pending; oneBot.internal = new icqq_1.Client({ ...exports.defaultIcqqConfig, log_level: this.app.config.log_level, ...protocol, }); return oneBot; } formatEventPayload(uin, version, event, data) { const oneBot = this.getOneBot(uin); const result = { id: data.id || Math.random().toString(36).slice(2), type: event, version: version, self: { platform: "qq", user_id: data.self_id, }, detail_type: data.message_type || data.notice_type || data.request_type, platform: "qq", ...data, sender: { ...(data?.sender || {}), user_id: data?.sender?.user_id || data?.sender?.tiny_id, }, user_id: data.user_id || data.sender?.user_id || data.sender?.tiny_id, }; delete result["group"]; delete result["member"]; delete result["discuss"]; delete result["friend"]; if (data.source) { const message_id = data.message_type === "group" ? (0, message_1.genGroupMessageId)(data.group_id, data.sender.user_id, data.source?.seq, data.source?.rand, data.source?.time, data.source?.pktnum) : (0, message_1.genDmMessageId)(data.sender.user_id, data.source?.seq, data.source?.rand, data.source?.time); const replyEl = { type: "reply", id: version === "V11" ? oneBot.V11.transformToInt("message_id", message_id) : message_id, }; /* 去除群聊消息的第一个引用消息段 */ if (result.detail_type === "group" && data.message[0]?.type === "at") { data.message[0] = replyEl; } else { data.message.unshift(replyEl); } } if (event === "message") { result.alt_message = result.raw_message || ""; } if (version === "V11" && result.message_id) { result.message_id = oneBot.V11.transformToInt("message_id", result.message_id); } return Object.fromEntries(Object.entries(result).filter(([_, value]) => { return typeof value !== "function"; })); } async sendPrivateMessage(uin, version, args) { const [user_id, message, source] = args; const client = this.oneBots.get(uin)?.internal; let quote; if (source) quote = await client.getMsg(source); const result = await client.sendPrivateMsg(parseInt(user_id), await utils_1.processMessages.call(this, uin, user_id, "private", message), quote); return { message_id: version === "V11" ? this.oneBots.get(uin).V11.transformToInt("message_id", result.message_id) : result.message_id, }; } deleteMessage(uin, version, args) { const bot = this.getOneBot(uin).internal; return bot.deleteMsg(args[0]); } async sendGroupMessage(uin, version, args) { const [group_id, message, source] = args; const client = this.oneBots.get(uin)?.internal; let quote; if (source) quote = await client.getMsg(source); const result = await client.sendGroupMsg(parseInt(group_id), await utils_1.processMessages.call(this, uin, group_id, "group", message), quote); return { message_id: version === "V11" ? this.oneBots.get(uin).V11.transformToInt("message_id", result.message_id) : result.message_id, }; } async sendGuildMessage(uin, version, args) { const [guild_id, channel_id, message, source] = args; const client = this.oneBots.get(uin)?.internal; const result = await client.sendGuildMsg(guild_id, channel_id, await utils_1.processMessages.call(this, uin, Number(channel_id), "guild", message)); const message_id = `${result.seq}:${result.rand}:${result.time}`; return { message_id: version === "V11" ? this.oneBots.get(uin).V11.transformToInt("message_id", message_id) : message_id, }; } async sendPrivateForwardMessage(uin, version, [user_id, messages]) { return this.sendPrivateMessage(uin, version, [ user_id, this.fromSegment(this.getOneBot(uin), version, messages.map(message => { return { type: "node", data: { user_id: message.uin || message.user_id, nickname: message.name || message.nickname, message: message.content, }, }; })), ]); } async sendGroupForwardMessage(uin, version, [group_id, messages]) { return this.sendGroupMessage(uin, version, [ group_id, this.fromSegment(this.getOneBot(uin), version, messages.map(message => { return { type: "node", data: { user_id: message.uin, nickname: message.name, message: message.content, }, }; })), ]); } async getMessage(uin, version, [message_id]) { const oneBot = this.getOneBot(uin); if (!oneBot) throw new Error("No one"); let { message, ...result } = await oneBot.internal.getMsg.call(oneBot.internal, message_id); const segments = version === "V11" ? message : this.toSegment(version, message); return { ...result, message: segments, }; } call(uin, version, method, args = []) { try { if (this[method]) return this[method](uin, version, args); const client = this.oneBots.get(uin)?.internal; return client[method].call(client, ...args); } catch { throw onebot_1.OneBot.UnsupportedMethodError; } } fromSegment(onebot, version, segment) { return [] .concat(segment) .map(segment => { if (version === "V12" && ["image", "video", "audio"].includes(segment.type)) { const result = onebot.V12.transformMedia(segment); result.data["file"] = result.data["file"] || result.data["file_id"] || result.data["url"]; return result; } return segment; }) .map(item => { if (typeof item === "string") return item; const { type, data } = item; if (type === "node") return { type, user_id: data.user_id, nickname: data.nickname, message: this.fromSegment(onebot, version, data.message), }; return { type, ...data }; }); } toSegment(version, message) { return [].concat(message).map(item => { if (typeof item !== "object") item = { type: "text", data: { text: item, }, }; const { type, ...data } = item; if (type === "node") return { type, data: { ...data, message: this.toSegment(version, data.message), }, }; return { type, data, }; }); } getSelfInfo(uin, version) { const client = this.oneBots.get(uin).internal; return { nickname: client.nickname, status: this.oneBots.get(uin).status, }; } async startOneBot(oneBot) { const _this = this; const disposeArr = []; const client = oneBot.internal; client.on("system.login.qrcode", function qrcodeHelper() { _this.logger.log("扫码后回车继续"); process_1.default.stdin.once("data", () => { client.login(); }); disposeArr.push(() => { client.off("system.login.qrcode"); }); }); client.on("system.login.device", function deviceHelper(e) { _this.logger.mark("请选择验证方式:1.短信验证 2.url验证"); process_1.default.stdin.once("data", buf => { const input = buf.toString().trim(); if (input === "1") { client.sendSmsCode(); _this.logger.mark("请输入短信验证码:"); const terminalInputHandler = buf => { client.submitSmsCode(buf.toString().trim()); }; process_1.default.stdin.once("data", terminalInputHandler); } else { _this.logger.mark(`请前往:${e.url} 完成验证后回车继续`); const terminalInputHandler = () => { client.login(); }; process_1.default.stdin.once("data", terminalInputHandler); } }); disposeArr.push(() => { client.off("system.login.device"); }); }); client.on("system.login.slider", function sliderHelper(e) { _this.logger.mark("请输入滑块验证返回的ticket"); process_1.default.stdin.once("data", e => { client.submitSlider(e.toString().trim()); }); disposeArr.push(() => { client.off("system.login.slider"); }); }); disposeArr.push(client.on("message", event => { this.emit("message.receive", oneBot.uin, event); })); disposeArr.push(client.on("notice", event => { this.emit("notice.receive", oneBot.uin, event); })); disposeArr.push(client.on("request", event => { this.emit("request.receive", oneBot.uin, event); })); await this.setOnline(oneBot.uin); return new Promise((resolve, reject) => { client.on("system.login.error", function errorHandler(e) { if (e.message.includes("密码错误")) { process_1.default.stdin.once("data", e => { client.login(e.toString().trim()); }); } else { _this.logger.error(e.message); oneBot.status = onebot_1.OneBotStatus.OffLine; clean(); } client.off("system.login.error"); }); const clean = () => { clearTimeout(timer); while (disposeArr.length) { disposeArr.shift()(); } }; client.on("system.online", () => { oneBot.nickname = client.nickname; oneBot.status = onebot_1.OneBotStatus.Online; this.app.ws.clients.forEach(client => { client.send(JSON.stringify({ event: "bot.change", data: oneBot.info, })); }); clearTimeout(timer); resolve(clean); }); const timer = setTimeout(() => { oneBot.status = onebot_1.OneBotStatus.OffLine; clean(); reject("登录超时"); }, this.app.config.timeout * 1000); }); } async start(uin) { const startOneBots = [...this.oneBots.values()].filter(oneBot => { return uin ? oneBot.uin === uin : true; }); for (const oneBot of startOneBots) { __classPrivateFieldGet(this, _IcqqAdapter_disposes, "f").set(oneBot.uin, await this.startOneBot(oneBot)); } await super.start(); } async stop(uin, force) { const stopOneBots = [...this.oneBots.values()].filter(oneBot => { return uin ? oneBot.uin === uin : true; }); for (const oneBot of stopOneBots) { const dispose = __classPrivateFieldGet(this, _IcqqAdapter_disposes, "f").get(oneBot.uin); if (dispose) { dispose(); } if (force) { (0, fs_1.rmSync)(oneBot.internal.dir, { force: true, recursive: true }); } } await super.stop(); } } _IcqqAdapter_password = new WeakMap(), _IcqqAdapter_disposes = new WeakMap(); exports.default = IcqqAdapter; exports.defaultIcqqConfig = { platform: 2, data_dir: path.join(process_1.default.cwd(), "data"), };