diff --git a/CHANGELOG.md b/CHANGELOG.md index db94192..a3d3aad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # 3.1.0 +* 支持协议端:GSUIDCore、微信 * 重构CK与UID管理逻辑 * 支持多UID绑定,可绑定多个UID并进行切换 * 支持原神与星铁UID共存,可针对查询命令分配对应UID diff --git a/README.md b/README.md index 9a2094b..ad6fc65 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # TRSS-Yunzai -Yunzai 应用端,支持多账号,支持协议端:go-cqhttp、ComWeChat、ICQQ、QQ频道、KOOK、Telegram、Discord +Yunzai 应用端,支持多账号,支持协议端:go-cqhttp、ComWeChat、GSUIDCore、ICQQ、QQ频道、微信、KOOK、Telegram、Discord [![访问量](https://visitor-badge.glitch.me/badge?page_id=TimeRainStarSky.Yunzai&right_color=red&left_text=访%20问%20量)](https://github.com/TimeRainStarSky/Yunzai) [![Stars](https://img.shields.io/github/stars/TimeRainStarSky/Yunzai?color=yellow&label=收藏)](../../stargazers) @@ -110,6 +110,16 @@ websocket_url = ["ws://localhost:2536/ComWeChat"] +
GSUIDCore + +下载运行 [GenshinUID 插件](http://docs.gsuid.gbots.work/#/AdapterList),GSUIDCore 连接地址 修改为: + +``` +ws://localhost:2536/GSUIDCore +``` + +
+
ICQQ [TRSS-Yunzai ICQQ Plugin](../../../Yunzai-ICQQ-Plugin) @@ -122,6 +132,12 @@ websocket_url = ["ws://localhost:2536/ComWeChat"]
+
微信 + +[TRSS-Yunzai WeChat Plugin](../../../Yunzai-WeChat-Plugin) + +
+
KOOK [TRSS-Yunzai KOOK Plugin](../../../Yunzai-KOOK-Plugin) diff --git a/lib/bot.js b/lib/bot.js index 70d1925..1ed3cd7 100644 --- a/lib/bot.js +++ b/lib/bot.js @@ -23,21 +23,16 @@ export default class Yunzai extends EventEmitter { this.emit("online", this) } - serverRequest(req) { - logger.info(`${logger.blue(`[${req.ip}]`)} HTTP ${req.method} 请求:${req.url} ${JSON.stringify(req.rawHeaders)}`) - req.res.redirect("https://github.com/TimeRainStarSky/Yunzai") - } - serverLoad() { - this.server.get("*", this.serverRequest) - this.server.post("*", this.serverRequest) + this.server.all("*", req => { + logger.info(`${logger.blue(`[${req.ip}]`)} HTTP ${req.method} 请求:${req.url} ${JSON.stringify(req.rawHeaders)}`) + req.res.redirect("https://github.com/TimeRainStarSky/Yunzai") + }) this.server = http.createServer(this.server) this.server.on("upgrade", (req, socket, head) => { - for (const i of Object.keys(this.wss)) - if (req.url == `/${i}`) - return this.wss[i].handleUpgrade(req, socket, head, conn => - this.wss[i].emit("connection", conn, req)) + const wss = this.wss[req.url.split("/")[1]] + if (wss) wss.handleUpgrade(req, socket, head, conn => wss.emit("connection", conn, req)) }) this.server.listen(cfg.bot.port, () => { @@ -197,4 +192,11 @@ export default class Yunzai extends EventEmitter { msg.replace = () => msg return { type: "node", data: msg } } + + async sendForwardMsg(send, msg) { + const messages = [] + for (const i of msg) + messages.push(await send(i.message)) + return messages + } } \ No newline at end of file diff --git a/lib/config/init.js b/lib/config/init.js index ab51632..2cd1cc2 100644 --- a/lib/config/init.js +++ b/lib/config/init.js @@ -11,16 +11,15 @@ process.env.TZ = 'Asia/Shanghai' /** 捕获未处理的Promise错误 */ process.on('unhandledRejection', (error, promise) => { - let err = error if (logger) { - logger.error(err) + logger.error(error) } else { - console.log(err) + console.log(error) } }) /** 退出事件 */ -process.on('exit', async (code) => { +process.on('exit', async code => { if (typeof redis != 'undefined' && typeof test == 'undefined') await redis.save() logger.mark(logger.magenta('TRSS-Yunzai 已停止运行')) @@ -29,7 +28,7 @@ process.on('exit', async (code) => { await checkInit() /** 初始化事件 */ -async function checkInit () { +async function checkInit() { /** 日志设置 */ setLog() diff --git a/lib/plugins/stdin.js b/lib/plugins/stdin.js index c8e0b2a..8ce2e88 100644 --- a/lib/plugins/stdin.js +++ b/lib/plugins/stdin.js @@ -16,8 +16,7 @@ Bot.adapter.push(new class stdinAdapter { return Buffer.from(await (await fetch(file)).arrayBuffer()) else if (fs.existsSync(file)) return Buffer.from(fs.readFileSync(file)) - else - return file + return file } async fileType(data) { @@ -69,7 +68,7 @@ Bot.adapter.push(new class stdinAdapter { case "at": break case "node": - this.sendForwardMsg(i.data) + Bot.sendForwardMsg(msg => this.sendMsg(msg), i.data) break default: i = JSON.stringify(i) @@ -85,13 +84,6 @@ Bot.adapter.push(new class stdinAdapter { logger.info(`${logger.blue(`[${this.id}]`)} 撤回消息:${message_id}`) } - sendForwardMsg(msg) { - const messages = [] - for (const i of msg) - messages.push(this.sendMsg(i.message)) - return messages - } - async sendFile(file, name = path.basename(file)) { const buffer = await this.makeBuffer(file) if (!Buffer.isBuffer(buffer)) { @@ -109,7 +101,7 @@ Bot.adapter.push(new class stdinAdapter { sendMsg: msg => this.sendMsg(msg), recallMsg: message_id => this.recallMsg(message_id), makeForwardMsg: Bot.makeForwardMsg, - sendForwardMsg: msg => this.sendForwardMsg(msg), + sendForwardMsg: msg => Bot.sendForwardMsg(msg => this.sendMsg(msg), msg), sendFile: (file, name) => this.sendFile(file, name), } } @@ -140,8 +132,8 @@ Bot.adapter.push(new class stdinAdapter { version: { id: this.id, name: this.name }, pickFriend: () => this.pickFriend(), pickUser: () => this.pickFriend(), - pickGroup: () => this.pickFriend(), pickMember: () => this.pickFriend(), + pickGroup: () => this.pickFriend(), fl: new Map().set(this.id, { user_id: this.id, diff --git a/package.json b/package.json index 6bf4863..e56dac4 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "yaml": "^2.3.1" }, "devDependencies": { - "eslint": "^8.43.0", + "eslint": "^8.44.0", "eslint-config-standard": "^17.1.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^16.0.1", diff --git a/plugins/adapter/ComWeChat.js b/plugins/adapter/ComWeChat.js index 9855731..d1230bd 100644 --- a/plugins/adapter/ComWeChat.js +++ b/plugins/adapter/ComWeChat.js @@ -7,6 +7,7 @@ Bot.adapter.push(new class ComWeChatAdapter { constructor() { this.id = "WeChat" this.name = "ComWeChat" + this.path = this.name } toStr(data) { @@ -21,6 +22,7 @@ Bot.adapter.push(new class ComWeChatAdapter { else return JSON.stringify(data) } + return data } makeLog(msg) { @@ -37,8 +39,23 @@ Bot.adapter.push(new class ComWeChatAdapter { resolve({ ...data, ...data.data }))) } - uploadFile(data, file, name = randomUUID()) { - const opts = { name } + async fileName(file) { + try { + if (file.match(/^base64:\/\//)) { + const buffer = Buffer.from(file.replace(/^base64:\/\//, ""), "base64") + const type = await fileTypeFromBuffer(buffer) + return `${Date.now()}.${type.ext}` + } else { + return path.basename(file) + } + } catch (err) { + logger.error(`文件类型检测错误:${logger.red(err)}`) + } + return false + } + + async uploadFile(data, file, name) { + const opts = { name: name || await this.fileName(file) || randomUUID() } if (file.match(/^https?:\/\//)) { opts.type = "url" @@ -54,6 +71,7 @@ Bot.adapter.push(new class ComWeChatAdapter { opts.path = file } + logger.info(`${logger.blue(`[${data.self_id}]`)} 上传文件:${this.makeLog(opts)}`) return data.sendApi("upload_file", opts) } @@ -68,53 +86,61 @@ Bot.adapter.push(new class ComWeChatAdapter { i = { type: i.type, data: { ...i, type: undefined }} if (i.data.file) i.data = { file_id: (await this.uploadFile(data, i.data.file)).file_id } + switch (i.type) { + case "text": + break + case "image": + break + case "record": + i.type = "file" + break + case "video": + i.type = "file" + break case "at": if (i.data.qq == "all") - msgs.push({ type: "mention_all", data: {}}) + i = { type: "mention_all", data: {}} else - msgs.push({ type: "mention", data: { user_id: i.data.qq }}) + i = { type: "mention", data: { user_id: i.data.qq }} break case "reply": + i = { type: "text", data: { text: `回复:${i.data.id}\n` }} break default: - msgs.push(i) + i = { type: "text", data: { text: JSON.stringify(i) }} } + msgs.push(i) } return msgs } async sendFriendMsg(data, msg) { if (msg?.type == "node") - return this.sendForwardMsg(msg => this.sendFriendMsg(data, msg), msg.data) + return Bot.sendForwardMsg(msg => this.sendFriendMsg(data, msg), msg.data) - logger.info(`${logger.blue(`[${data.self_id}]`)} 发送好友消息:[${data.user_id}] ${this.makeLog(msg)}`) + const message = await this.makeMsg(data, msg) + logger.info(`${logger.blue(`[${data.self_id}]`)} 发送好友消息:[${data.user_id}] ${this.makeLog(message)}`) return data.sendApi("send_message", { detail_type: "private", user_id: data.user_id, - message: await this.makeMsg(data, msg), + message, }) } async sendGroupMsg(data, msg) { if (msg?.type == "node") - return this.sendForwardMsg(msg => this.sendGroupMsg(data, msg), msg.data) + return Bot.sendForwardMsg(msg => this.sendGroupMsg(data, msg), msg.data) - logger.info(`${logger.blue(`[${data.self_id}]`)} 发送群消息:[${data.group_id}] ${this.makeLog(msg)}`) + const message = await this.makeMsg(data, msg) + logger.info(`${logger.blue(`[${data.self_id}]`)} 发送群消息:[${data.group_id}] ${this.makeLog(message)}`) return data.sendApi("send_message", { detail_type: "group", group_id: data.group_id, - message: await this.makeMsg(data, msg), + message, }) } - async sendForwardMsg(send, msg) { - const messages = [] - for (const i of msg) - messages.push(await send(i.message)) - return messages - } - async getFriendArray(data) { const array = [] for (const i of (await data.sendApi("get_friend_list")).data) @@ -196,7 +222,7 @@ Bot.adapter.push(new class ComWeChatAdapter { }) } - async sendFile(data, send, file, name = path.basename(file)) { + async sendFile(data, send, file, name) { logger.info(`${logger.blue(`[${data.self_id}]`)} 发送文件:${name}(${file})`) return send(segment.custom("file", { file_id: (await this.uploadFile(data, file, name)).file_id @@ -214,7 +240,7 @@ Bot.adapter.push(new class ComWeChatAdapter { sendMsg: msg => this.sendFriendMsg(i, msg), recallMsg: () => false, makeForwardMsg: Bot.makeForwardMsg, - sendForwardMsg: msg => this.sendForwardMsg(msg => this.sendFriendMsg(i, msg), msg), + sendForwardMsg: msg => Bot.sendForwardMsg(msg => this.sendFriendMsg(i, msg), msg), sendFile: (file, name) => this.sendFile(i, msg => this.sendFriendMsg(i, msg), file, name), getInfo: () => this.getFriendInfo(i), getAvatarUrl: async () => (await this.getFriendInfo(i))["wx.avatar"], @@ -247,7 +273,7 @@ Bot.adapter.push(new class ComWeChatAdapter { sendMsg: msg => this.sendGroupMsg(i, msg), recallMsg: () => false, makeForwardMsg: Bot.makeForwardMsg, - sendForwardMsg: msg => this.sendForwardMsg(msg => this.sendGroupMsg(i, msg), msg), + sendForwardMsg: msg => Bot.sendForwardMsg(msg => this.sendGroupMsg(i, msg), msg), sendFile: (file, name) => this.sendFile(i, msg => this.sendGroupMsg(i, msg), file, name), getInfo: () => this.getGroupInfo(i), getAvatarUrl: async () => (await this.getGroupInfo(i))["wx.avatar"], @@ -263,9 +289,11 @@ Bot.adapter.push(new class ComWeChatAdapter { data.self_id = bot.self.user_id Bot[data.self_id] = { + adapter: this, sendApi: data.sendApi, stat: { ...data.status, start_time: data.time }, + pickUser: user_id => this.pickFriend(data, user_id), pickFriend: user_id => this.pickFriend(data, user_id), getFriendArray: () => this.getFriendArray(data), @@ -279,7 +307,6 @@ Bot.adapter.push(new class ComWeChatAdapter { getGroupList: () => this.getGroupList(data), getGroupMap: () => this.getGroupMap(data), } - Bot[data.self_id].pickUser = Bot[data.self_id].pickFriend Bot[data.self_id].info = (await data.sendApi("get_self_info")).data Bot[data.self_id].uin = Bot[data.self_id].info.user_id @@ -411,8 +438,8 @@ Bot.adapter.push(new class ComWeChatAdapter { } load() { - Bot.wss[this.name] = new WebSocketServer({ noServer: true }) - Bot.wss[this.name].on("connection", ws => { + Bot.wss[this.path] = new WebSocketServer({ noServer: true }) + Bot.wss[this.path].on("connection", ws => { ws.on("error", logger.error) ws.on("message", data => this.message(data, ws)) }) diff --git a/plugins/adapter/GSUIDCore.js b/plugins/adapter/GSUIDCore.js new file mode 100644 index 0000000..f16010a --- /dev/null +++ b/plugins/adapter/GSUIDCore.js @@ -0,0 +1,265 @@ +import { WebSocketServer } from "ws" +import { randomUUID } from "crypto" +import path from "node:path" +import fs from "node:fs" + +Bot.adapter.push(new class GSUIDCoreAdapter { + constructor() { + this.id = "GSUIDCore" + this.name = "早柚核心" + this.path = "GSUIDCore" + } + + toStr(data) { + switch (typeof data) { + case "string": + return data + case "number": + return String(data) + case "object": + if (Buffer.isBuffer(data)) + return Buffer.from(data, "utf8").toString() + else + return JSON.stringify(data) + } + return data + } + + makeLog(msg) { + return this.toStr(msg).replace(/("type":"(image|file)","data":").*?(")/g, "$1...$3") + } + + async makeBase64(file) { + if (file.match(/^base64:\/\//)) + return file.replace(/^base64:\/\//, "") + else if (file.match(/^https?:\/\//)) + return Buffer.from(await (await fetch(file)).arrayBuffer()).toString("base64") + return file + } + + async makeMsg(msg) { + if (!Array.isArray(msg)) + msg = [msg] + const msgs = [] + 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 }} + if (i.data.file) + i.data = await this.makeBase64(i.data.file) + + switch (i.type) { + case "text": + i.data = i.data.text + break + case "image": + break + case "file": + break + case "at": + i.data = i.data.qq + break + case "reply": + i.data = i.data.id + break + case "record": + i.type = "file" + break + case "video": + i.type = "file" + break + case "node": + for (const n in i.data) + i.data[n] = await this.makeMsg(i.data[n]) + default: + i = { type: "text", data: JSON.stringify(i) } + } + msgs.push(i) + } + return msgs + } + + async sendFriendMsg(data, msg) { + const content = await this.makeMsg(msg) + logger.info(`${logger.blue(`[${data.self_id}]`)} 发送好友消息:[${data.user_id}] ${this.makeLog(content)}`) + return data.bot.send(JSON.stringify({ + bot_id: data.bot.bot_id, + bot_self_id: data.bot.bot_self_id, + target_type: "direct", + target_id: data.user_id, + content, + })) + } + + async sendGroupMsg(data, msg) { + data.group_id = data.group_id.split("-") + const content = await this.makeMsg(msg) + logger.info(`${logger.blue(`[${data.self_id}]`)} 发送群消息:[${data.group_id}] ${this.makeLog(content)}`) + return data.bot.send(JSON.stringify({ + bot_id: data.bot.bot_id, + bot_self_id: data.bot.bot_self_id, + target_type: data.group_id[0], + target_id: data.group_id[1], + content, + })) + } + + pickFriend(id, user_id) { + const i = { + ...Bot[id].fl.get(user_id), + self_id: id, + bot: Bot[id], + user_id: user_id.replace(/^gc_/, ""), + } + return { + ...i, + sendMsg: msg => this.sendFriendMsg(i, msg), + recallMsg: () => false, + makeForwardMsg: Bot.makeForwardMsg, + sendForwardMsg: msg => Bot.sendForwardMsg(msg => this.sendFriendMsg(i, msg), msg), + } + } + + pickMember(id, group_id, user_id) { + const i = { + ...Bot[id].fl.get(user_id), + self_id: id, + bot: Bot[id], + group_id: group_id.replace(/^gc_/, ""), + user_id: user_id.replace(/^gc_/, ""), + } + return { + ...this.pickFriend(id, user_id), + ...i, + } + } + + pickGroup(id, group_id) { + const i = { + ...Bot[id].gl.get(group_id), + self_id: id, + bot: Bot[id], + group_id: group_id.replace(/^gc_/, ""), + } + return { + ...i, + sendMsg: msg => this.sendGroupMsg(i, msg), + recallMsg: message_id => this.recallMsg(i, message_id => i.bot.API.message.delete(message_id), message_id), + makeForwardMsg: Bot.makeForwardMsg, + sendForwardMsg: msg => Bot.sendForwardMsg(msg => this.sendGroupMsg(i, msg), msg), + pickMember: user_id => this.pickMember(id, group_id, user_id), + } + } + + makeBot(data, send) { + Bot[data.self_id] = { + adapter: this, + send, + uin: data.self_id, + bot_id: data.bot_id, + bot_self_id: data.bot_self_id, + stat: { start_time: Date.now()/1000 }, + version: { + id: this.id, + name: this.name, + }, + pickFriend: user_id => this.pickFriend(data.self_id, user_id), + pickMember: (group_id, user_id) => this.pickMember(data.self_id, group_id, user_id), + pickGroup: group_id => this.pickGroup(data.self_id, group_id), + fl: new Map(), + gl: new Map(), + } + Bot[data.self_id].pickUser = Bot[data.self_id].pickFriend + + logger.mark(`${logger.blue(`[${data.self_id}]`)} ${this.name}(${this.id}) 已连接`) + Bot.emit(`connect.${data.self_id}`, Bot[data.self_id]) + Bot.emit(`connect`, Bot[data.self_id]) + } + + message(data, ws) { + try { + data = JSON.parse(data) + } catch (err) { + return logger.error(`解码数据失败:${logger.red(err)}`) + } + + data.self_id = `gc_${data.bot_self_id}` + if (Bot[data.self_id]) + Bot[data.self_id].send = ws.send + else + this.makeBot(data, ws.send) + data.bot = Bot[data.self_id] + + data.post_type = "message" + data.message_id = data.msg_id + data.user_id = `gc_${data.user_id}` + data.sender = { + user_id: data.user_id, + user_pm: data.user_pm, + } + if (!data.bot.fl.has(data.user_id)) + data.bot.fl.set(data.user_id, data.sender) + + data.message = [] + data.raw_message = "" + for (const i of data.content) { + switch (i.type) { + case "text": + data.message.push({ type: "text", text: i.data }) + data.raw_message += i.data + break + case "image": + data.message.push({ type: "image", url: i.data }) + data.raw_message += `[图片:${i.data}]` + break + case "file": + data.message.push({ type: "file", url: i.data }) + data.raw_message += `[文件:${i.data}]` + break + case "at": + data.message.push({ type: "at", qq: i.data }) + data.raw_message += `[提及:${i.data}]` + break + case "reply": + data.message.push({ type: "reply", id: i.data }) + data.raw_message += `[回复:${i.data}]` + break + case "node": + data.message.push({ type: "node", data: i.data }) + data.raw_message += `[合并转发:${JSON.stringify(i.data)}]` + break + default: + data.message.push(i) + data.raw_message += JSON.stringify(i) + } + } + + if (data.user_type == "direct") { + data.message_type = "private" + logger.info(`${logger.blue(`[${data.self_id}]`)} 好友消息:[${data.user_id}] ${data.raw_message}`) + data.friend = data.bot.pickFriend(data.user_id) + } else { + data.message_type = "group" + data.group_id = `gc_${data.user_type}-${data.group_id}` + if (!data.bot.gl.has(data.group_id)) + data.bot.gl.set(data.group_id, { group_id: data.group_id }) + logger.info(`${logger.blue(`[${data.self_id}]`)} 群消息:[${data.group_id}, ${data.user_id}] ${data.raw_message}`) + data.friend = data.bot.pickFriend(data.user_id) + data.group = data.bot.pickGroup(data.group_id) + data.member = data.group.pickMember(data.user_id) + } + console.log(data) + Bot.emit(`${data.post_type}.${data.message_type}`, data) + Bot.emit(`${data.post_type}`, data) + } + + load() { + Bot.wss[this.path] = new WebSocketServer({ noServer: true }) + Bot.wss[this.path].on("connection", ws => { + ws.on("error", logger.error) + ws.on("message", data => this.message(data, ws)) + }) + return true + } +}) \ No newline at end of file diff --git a/plugins/adapter/go-cqhttp.js b/plugins/adapter/go-cqhttp.js index 6552c20..d99b870 100644 --- a/plugins/adapter/go-cqhttp.js +++ b/plugins/adapter/go-cqhttp.js @@ -6,6 +6,7 @@ Bot.adapter.push(new class gocqhttpAdapter { constructor() { this.id = "QQ" this.name = "go-cqhttp" + this.path = this.name } toStr(data) { @@ -20,6 +21,7 @@ Bot.adapter.push(new class gocqhttpAdapter { else return JSON.stringify(data) } + return data } makeLog(msg) { @@ -525,6 +527,7 @@ Bot.adapter.push(new class gocqhttpAdapter { async connect(data) { Bot[data.self_id] = { + adapter: this, sendApi: data.sendApi, stat: { start_time: data.time }, @@ -532,6 +535,7 @@ Bot.adapter.push(new class gocqhttpAdapter { recallMsg: message_id => this.recallMsg(data, message_id), getForwardMsg: message_id => this.getForwardMsg(data, message_id), + pickUser: user_id => this.pickFriend(data, user_id), pickFriend: user_id => this.pickFriend(data, user_id), getFriendArray: () => this.getFriendArray(data), @@ -545,7 +549,6 @@ Bot.adapter.push(new class gocqhttpAdapter { getGroupList: () => this.getGroupList(data), getGroupMap: () => this.getGroupMap(data), } - Bot[data.self_id].pickUser = Bot[data.self_id].pickFriend Bot[data.self_id].info = (await data.sendApi("get_login_info")).data Bot[data.self_id].uin = Bot[data.self_id].info.user_id @@ -566,9 +569,8 @@ Bot.adapter.push(new class gocqhttpAdapter { Bot[data.self_id].version = (await data.sendApi("get_version_info")).data Bot[data.self_id].version = { ...Bot[data.self_id].version, - impl: Bot[data.self_id].version.app_name, - version: Bot[data.self_id].version.app_version, - onebot_version: Bot[data.self_id].version.protocol_version, + id: this.id, + name: this.name, } Bot[data.self_id].status = Bot[data.self_id].version.protocol_name @@ -829,8 +831,8 @@ Bot.adapter.push(new class gocqhttpAdapter { } load() { - Bot.wss[this.name] = new WebSocketServer({ noServer: true }) - Bot.wss[this.name].on("connection", ws => { + Bot.wss[this.path] = new WebSocketServer({ noServer: true }) + Bot.wss[this.path].on("connection", ws => { ws.on("error", logger.error) ws.on("message", data => this.message(data, ws)) }) diff --git a/plugins/other/install.js b/plugins/other/install.js index f76aba5..93525b5 100644 --- a/plugins/other/install.js +++ b/plugins/other/install.js @@ -16,6 +16,7 @@ const list = { "Telegram-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-Telegram-Plugin", "Discord-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-Discord-Plugin", "QQGuild-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-QQGuild-Plugin", + "WeChat-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-WeChat-Plugin", "ICQQ-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-ICQQ-Plugin", "KOOK-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-KOOK-Plugin", }