优化 适配器加载

This commit is contained in:
🌌 2023-06-26 23:32:52 +08:00
parent 8088a85aae
commit 94b3519100
9 changed files with 231 additions and 186 deletions

5
app.js
View File

@ -1,4 +1,3 @@
import Yunzai from './lib/bot.js' import Yunzai from './lib/bot.js'
global.Bot = new Yunzai()
/** 全局变量 bot */ Bot.run()
await Yunzai.run()

View File

@ -1,45 +0,0 @@
import fs from "node:fs"
import cfg from "../config/config.js"
import express from "express"
import http from "http"
export default class WebSocketAdapter {
request(req) {
logger.info(`${logger.blue(`[${req.ip}]`)} HTTP ${req.method} 请求:${req.url} ${JSON.stringify(req.rawHeaders)}`)
req.res.redirect("https://github.com/TimeRainStarSky/Yunzai")
}
async load() {
const wss = {}
for (const file of fs.readdirSync('./lib/adapter/WebSocket').filter(file => file.endsWith('.js'))) {
try {
let adapter = await import(`./WebSocket/${file}`)
if (!adapter.default) continue
adapter = new adapter.default()
wss[file.replace(/.js$/, "")] = await adapter.load()
} catch (e) {
logger.mark(`加载 WebSocket 适配器错误:${file}`)
logger.error(e)
}
}
const app = express()
app.get("*", this.request)
app.post("*", this.request)
const server = http.createServer(app)
server.on("upgrade", (req, socket, head) => {
for (const i of Object.keys(wss))
if (req.url == `/${i}`)
return wss[i].handleUpgrade(req, socket, head, conn => wss[i].emit("connection", conn, req))
})
server.listen(cfg.bot.port, () => {
const host = server.address().address
const port = server.address().port
logger.mark(`启动 WebSocket 服务器:${logger.green(`ws://[${host}]:${port}`)}`)
for (const i of Object.keys(wss))
logger.info(`本机 ${i} 连接地址:${logger.blue(`ws://localhost:${port}/${i}`)}`)
})
}
}

View File

@ -1,37 +1,73 @@
import './config/init.js' import "./config/init.js"
import cfg from './config/config.js' import cfg from "./config/config.js"
import PluginsLoader from './plugins/loader.js' import PluginsLoader from "./plugins/loader.js"
import ListenerLoader from './listener/loader.js' import ListenerLoader from "./listener/loader.js"
import { EventEmitter } from 'events' import { EventEmitter } from "events"
import express from "express"
import http from "http"
export default class Yunzai extends EventEmitter { export default class Yunzai extends EventEmitter {
static async run() { constructor() {
global.Bot = new Yunzai() super()
this.uin = []
this.adapter = []
this.server = express()
this.wss = {}
}
async run() {
await PluginsLoader.load() await PluginsLoader.load()
await ListenerLoader.load() await ListenerLoader.load()
Bot.emit("online") this.serverLoad()
this.emit("online")
}
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 = 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))
})
this.server.listen(cfg.bot.port, () => {
const host = this.server.address().address
const port = this.server.address().port
logger.mark(`启动 HTTP 服务器:${logger.green(`http://[${host}]:${port}`)}`)
for (const i of Object.keys(this.wss))
logger.info(`本机 ${i} 连接地址:${logger.blue(`ws://localhost:${port}/${i}`)}`)
})
} }
getFriendArray() { getFriendArray() {
const array = [] const array = []
for (const i of Bot.uin) for (const i of this.uin)
Bot[i].fl?.forEach(value => this[i].fl?.forEach(value =>
array.push({ ...value, bot_id: i })) array.push({ ...value, bot_id: i }))
return array return array
} }
getFriendList() { getFriendList() {
const array = [] const array = []
for (const i of Bot.uin) for (const i of this.uin)
Bot[i].fl?.forEach((value, key) => this[i].fl?.forEach((value, key) =>
array.push(key)) array.push(key))
return array return array
} }
getFriendMap() { getFriendMap() {
const map = new Map() const map = new Map()
for (const i of Bot.uin) for (const i of this.uin)
Bot[i].fl?.forEach((value, key) => this[i].fl?.forEach((value, key) =>
map.set(key, { ...value, bot_id: i })) map.set(key, { ...value, bot_id: i }))
return map return map
} }
@ -42,24 +78,24 @@ export default class Yunzai extends EventEmitter {
getGroupArray() { getGroupArray() {
const array = [] const array = []
for (const i of Bot.uin) for (const i of this.uin)
Bot[i].gl?.forEach(value => this[i].gl?.forEach(value =>
array.push({ ...value, bot_id: i })) array.push({ ...value, bot_id: i }))
return array return array
} }
getGroupList() { getGroupList() {
const array = [] const array = []
for (const i of Bot.uin) for (const i of this.uin)
Bot[i].gl?.forEach((value, key) => this[i].gl?.forEach((value, key) =>
array.push(key)) array.push(key))
return array return array
} }
getGroupMap() { getGroupMap() {
const map = new Map() const map = new Map()
for (const i of Bot.uin) for (const i of this.uin)
Bot[i].gl?.forEach((value, key) => this[i].gl?.forEach((value, key) =>
map.set(key, { ...value, bot_id: i })) map.set(key, { ...value, bot_id: i }))
return map return map
} }
@ -74,8 +110,8 @@ export default class Yunzai extends EventEmitter {
pickFriend(user_id) { pickFriend(user_id) {
user_id = Number(user_id) || String(user_id) user_id = Number(user_id) || String(user_id)
const user = Bot.fl.get(user_id) const user = this.fl.get(user_id)
if (user) return Bot[user.bot_id].pickFriend(user_id) if (user) return this[user.bot_id].pickFriend(user_id)
logger.error(`获取用户对象失败:找不到用户 ${logger.red(user_id)}`) logger.error(`获取用户对象失败:找不到用户 ${logger.red(user_id)}`)
return false return false
@ -83,8 +119,8 @@ export default class Yunzai extends EventEmitter {
pickGroup(group_id) { pickGroup(group_id) {
group_id = Number(group_id) || String(group_id) group_id = Number(group_id) || String(group_id)
const group = Bot.gl.get(group_id) const group = this.gl.get(group_id)
if (group) return Bot[group.bot_id].pickGroup(group_id) if (group) return this[group.bot_id].pickGroup(group_id)
logger.error(`获取群对象失败:找不到群 ${logger.red(group_id)}`) logger.error(`获取群对象失败:找不到群 ${logger.red(group_id)}`)
return false return false
@ -100,13 +136,13 @@ export default class Yunzai extends EventEmitter {
sendFriendMsg(bot_id, user_id, msg) { sendFriendMsg(bot_id, user_id, msg) {
try { try {
if (!bot_id) if (!bot_id)
return Bot.pickFriend(user_id).sendMsg(msg) return this.pickFriend(user_id).sendMsg(msg)
if (Bot[bot_id]) if (this[bot_id])
return Bot[bot_id].pickFriend(user_id).sendMsg(msg) return this[bot_id].pickFriend(user_id).sendMsg(msg)
return new Promise(resolve => return new Promise(resolve =>
Bot.once(`connect.${bot_id}`, data => this.once(`connect.${bot_id}`, data =>
resolve(data.pickFriend(user_id).sendMsg(msg)))) resolve(data.pickFriend(user_id).sendMsg(msg))))
} catch (err) { } catch (err) {
logger.error(`${logger.blue(`[${bot_id}]`)} 发送好友消息失败:[$${user_id}] ${err}`) logger.error(`${logger.blue(`[${bot_id}]`)} 发送好友消息失败:[$${user_id}] ${err}`)
@ -116,13 +152,13 @@ export default class Yunzai extends EventEmitter {
sendGroupMsg(bot_id, group_id, msg) { sendGroupMsg(bot_id, group_id, msg) {
try { try {
if (!bot_id) if (!bot_id)
return Bot.pickGroup(group_id).sendMsg(msg) return this.pickGroup(group_id).sendMsg(msg)
if (Bot[bot_id]) if (this[bot_id])
return Bot[bot_id].pickGroup(group_id).sendMsg(msg) return this[bot_id].pickGroup(group_id).sendMsg(msg)
return new Promise(resolve => return new Promise(resolve =>
Bot.once(`connect.${bot_id}`, data => this.once(`connect.${bot_id}`, data =>
resolve(data.pickGroup(group_id).sendMsg(msg)))) resolve(data.pickGroup(group_id).sendMsg(msg))))
} catch (err) { } catch (err) {
logger.error(`${logger.blue(`[${bot_id}]`)} 发送群消息失败:[$${group_id}] ${err}`) logger.error(`${logger.blue(`[${bot_id}]`)} 发送群消息失败:[$${group_id}] ${err}`)
@ -138,7 +174,7 @@ export default class Yunzai extends EventEmitter {
async getMasterMsg() { async getMasterMsg() {
while (true) { while (true) {
const msg = await new Promise(resolve => { const msg = await new Promise(resolve => {
Bot.once("message", data => { this.once("message", data => {
if (cfg.master[data.self_id]?.includes(String(data.user_id)) && data.message) { if (cfg.master[data.self_id]?.includes(String(data.user_id)) && data.message) {
let msg = "" let msg = ""
for (let i of data.message) for (let i of data.message)

View File

@ -13,6 +13,7 @@ class ListenerLoader {
logger.info("加载监听事件中...") logger.info("加载监听事件中...")
let eventCount = 0 let eventCount = 0
for (const file of fs.readdirSync('./lib/events').filter(file => file.endsWith('.js'))) { for (const file of fs.readdirSync('./lib/events').filter(file => file.endsWith('.js'))) {
logger.debug(`加载监听事件:${file}`)
try { try {
let listener = await import(`../events/${file}`) let listener = await import(`../events/${file}`)
if (!listener.default) continue if (!listener.default) continue
@ -39,15 +40,13 @@ class ListenerLoader {
logger.info("-----------") logger.info("-----------")
logger.info("加载适配器中...") logger.info("加载适配器中...")
let adapterCount = 0 let adapterCount = 0
for (const file of fs.readdirSync('./lib/adapter').filter(file => file.endsWith('.js'))) { for (const adapter of Bot.adapter) {
try { try {
let adapter = await import(`../adapter/${file}`) logger.debug(`加载适配器:${adapter.name}(${adapter.id})`)
if (!adapter.default) continue
adapter = new adapter.default()
await adapter.load() await adapter.load()
adapterCount++ adapterCount++
} catch (e) { } catch (e) {
logger.mark(`加载适配器错误:${file}`) logger.mark(`加载适配器错误:${adapter.name}(${adapter.id})`)
logger.error(e) logger.error(e)
} }
} }

View File

@ -41,7 +41,7 @@
"eslint": "^8.43.0", "eslint": "^8.43.0",
"eslint-config-standard": "^17.1.0", "eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.27.5", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-n": "^16.0.0", "eslint-plugin-n": "^16.0.1",
"eslint-plugin-promise": "^6.1.1" "eslint-plugin-promise": "^6.1.1"
}, },
"imports": { "imports": {

9
plugins/.gitignore vendored
View File

@ -1,10 +1,11 @@
* *
!.gitignore !.gitignore
!adapter
!adapter/**
!system
!system/** !system/**
!other
!other/** !other/**
!example/一言.js !example/一言.js
!example/主动复读.js !example/主动复读.js
!example/进群退群通知.js !example/进群退群通知.js

View File

@ -3,7 +3,12 @@ import { randomUUID } from "crypto"
import path from "node:path" import path from "node:path"
import fs from "node:fs" import fs from "node:fs"
export default class ComWeChatAdapter { Bot.adapter.push(new class ComWeChatAdapter {
constructor() {
this.id = "WeChat"
this.name = "ComWeChat"
}
toStr(data) { toStr(data) {
switch (typeof data) { switch (typeof data) {
case "string": case "string":
@ -198,8 +203,13 @@ export default class ComWeChatAdapter {
} }
pickFriend(data, user_id) { pickFriend(data, user_id) {
const i = { ...data, user_id } const i = {
...Bot[data.self_id].fl.get(user_id),
...data,
user_id,
}
return { return {
...i,
sendMsg: msg => this.sendFriendMsg(i, msg), sendMsg: msg => this.sendFriendMsg(i, msg),
recallMsg: () => false, recallMsg: () => false,
makeForwardMsg: Bot.makeForwardMsg, makeForwardMsg: Bot.makeForwardMsg,
@ -211,17 +221,28 @@ export default class ComWeChatAdapter {
} }
pickMember(data, group_id, user_id) { pickMember(data, group_id, user_id) {
const i = { ...data, group_id, user_id } const i = {
...Bot[data.self_id].fl.get(user_id),
...data,
group_id,
user_id,
}
return { return {
...this.pickFriend(i, user_id), ...this.pickFriend(i, user_id),
...i,
getInfo: () => this.getGroupMemberInfo(i), getInfo: () => this.getGroupMemberInfo(i),
getAvatarUrl: async () => (await this.getGroupMemberInfo(i))["wx.avatar"], getAvatarUrl: async () => (await this.getGroupMemberInfo(i))["wx.avatar"],
} }
} }
pickGroup(data, group_id) { pickGroup(data, group_id) {
const i = { ...data, group_id } const i = {
...Bot[data.self_id].gl.get(group_id),
...data,
group_id,
}
return { return {
...i,
sendMsg: msg => this.sendGroupMsg(i, msg), sendMsg: msg => this.sendGroupMsg(i, msg),
recallMsg: () => false, recallMsg: () => false,
makeForwardMsg: Bot.makeForwardMsg, makeForwardMsg: Bot.makeForwardMsg,
@ -264,19 +285,19 @@ export default class ComWeChatAdapter {
Bot[data.self_id].nickname = Bot[data.self_id].info.user_name Bot[data.self_id].nickname = Bot[data.self_id].info.user_name
Bot[data.self_id].avatar = Bot[data.self_id].info["wx.avatar"] Bot[data.self_id].avatar = Bot[data.self_id].info["wx.avatar"]
Bot[data.self_id].version = (await data.sendApi("get_version")).data Bot[data.self_id].version = {
...(await data.sendApi("get_version")).data,
Bot[data.self_id].fl = await this.getFriendMap(data) id: this.id,
Bot[data.self_id].gl = await this.getGroupMap(data) name: this.name,
if (Array.isArray(Bot.uin)) {
if (!Bot.uin.includes(data.self_id))
Bot.uin.push(data.self_id)
} else {
Bot.uin = [data.self_id]
} }
logger.mark(`${logger.blue(`[${data.self_id}]`)} ComWeChat 已连接`) Bot[data.self_id].fl = await Bot[data.self_id].getFriendMap()
Bot[data.self_id].gl = await Bot[data.self_id].getGroupMap()
if (!Bot.uin.includes(data.self_id))
Bot.uin.push(data.self_id)
logger.mark(`${logger.blue(`[${data.self_id}]`)} ${this.name}(${this.id}) 已连接`)
Bot.emit(`connect.${data.self_id}`, Bot[data.self_id]) Bot.emit(`connect.${data.self_id}`, Bot[data.self_id])
Bot.emit(`connect`, Bot[data.self_id]) Bot.emit(`connect`, Bot[data.self_id])
} }
@ -343,15 +364,17 @@ export default class ComWeChatAdapter {
return logger.error(err) return logger.error(err)
} }
data.sendApi = (action, params) => this.sendApi(ws, action, params)
if (data.self?.user_id) { if (data.self?.user_id) {
data.self_id = data.self.user_id data.self_id = data.self.user_id
data.bot = Bot[data.self_id]
} else { } else {
data.self_id = data.id data.self_id = data.id
} }
if (data.type) { if (data.type) {
if (data.detail_type != "status_update" && !Bot.uin.includes(data.self_id))
return false
data.sendApi = (action, params) => this.sendApi(ws, action, params)
data.bot = Bot[data.self_id]
switch (data.type) { switch (data.type) {
case "meta": case "meta":
this.makeMeta(data) this.makeMeta(data)
@ -379,11 +402,11 @@ export default class ComWeChatAdapter {
} }
load() { load() {
const wss = new WebSocketServer({ noServer: true }) Bot.wss[this.name] = new WebSocketServer({ noServer: true })
wss.on("connection", ws => { Bot.wss[this.name].on("connection", ws => {
ws.on("error", logger.error) ws.on("error", logger.error)
ws.on("message", data => this.message(data, ws)) ws.on("message", data => this.message(data, ws))
}) })
return wss return true
} }
} })

View File

@ -2,7 +2,12 @@ import { WebSocketServer } from "ws"
import { randomUUID } from "crypto" import { randomUUID } from "crypto"
import path from "node:path" import path from "node:path"
export default class gocqhttpAdapter { Bot.adapter.push(new class gocqhttpAdapter {
constructor() {
this.id = "QQ"
this.name = "go-cqhttp"
}
toStr(data) { toStr(data) {
switch (typeof data) { switch (typeof data) {
case "string": case "string":
@ -407,42 +412,65 @@ export default class gocqhttpAdapter {
} }
pickFriend(data, user_id) { pickFriend(data, user_id) {
const i = { ...data, user_id } const i = {
...Bot[data.self_id].fl.get(user_id),
...data,
user_id,
}
return { return {
...i,
sendMsg: msg => this.sendFriendMsg(i, msg), sendMsg: msg => this.sendFriendMsg(i, msg),
recallMsg: message_id => this.recallMsg(i, message_id), recallMsg: message_id => this.recallMsg(i, message_id),
makeForwardMsg: Bot.makeForwardMsg, makeForwardMsg: Bot.makeForwardMsg,
sendForwardMsg: msg => this.sendFriendForwardMsg(i, msg), sendForwardMsg: msg => this.sendFriendForwardMsg(i, msg),
sendFile: (file, name) => this.sendFriendFile(i, file, name), sendFile: (file, name) => this.sendFriendFile(i, file, name),
getInfo: () => this.getFriendInfo(i), getInfo: () => this.getFriendInfo(i),
getAvatarUrl: () => `https://q1.qlogo.cn/g?b=qq&s=0&nk=${i.user_id}`, getAvatarUrl: () => `https://q1.qlogo.cn/g?b=qq&s=0&nk=${user_id}`,
} }
} }
pickMember(data, group_id, user_id) { pickMember(data, group_id, user_id) {
if (typeof group_id == "string" && group_id.match("-")) { if (typeof group_id == "string" && group_id.match("-")) {
group_id = group_id.split("-") const guild_id = group_id.split("-")
const i = { ...data, guild_id: group_id[0], channel_id: group_id[1], user_id } const i = {
...data,
guild_id: guild_id[0],
channel_id: guild_id[1],
user_id,
}
return { return {
...this.pickGroup(i, `${i.guild_id}-${i.channel_id}`), ...this.pickGroup(i, group_id),
...i,
getInfo: () => this.getGuildMemberInfo(i), getInfo: () => this.getGuildMemberInfo(i),
getAvatarUrl: async () => (await this.getGuildMemberInfo(i)).avatar_url, getAvatarUrl: async () => (await this.getGuildMemberInfo(i)).avatar_url,
} }
} else { }
const i = { ...data, group_id, user_id }
return { const i = {
...this.pickFriend(i, i.user_id), ...Bot[data.self_id].fl.get(user_id),
getInfo: () => this.getGroupMemberInfo(i), ...data,
poke: () => this.sendGroupMsg(i, segment.poke(i.user_id)), group_id,
} user_id,
}
return {
...this.pickFriend(i, user_id),
...i,
getInfo: () => this.getGroupMemberInfo(i),
poke: () => this.sendGroupMsg(i, segment.poke(user_id)),
} }
} }
pickGroup(data, group_id) { pickGroup(data, group_id) {
if (typeof group_id == "string" && group_id.match("-")) { if (typeof group_id == "string" && group_id.match("-")) {
group_id = group_id.split("-") const guild_id = group_id.split("-")
const i = { ...data, guild_id: group_id[0], channel_id: group_id[1] } const i = {
...Bot[data.self_id].gl.get(group_id),
...data,
guild_id: guild_id[0],
channel_id: guild_id[1],
}
return { return {
...i,
sendMsg: msg => this.sendGuildMsg(i, msg), sendMsg: msg => this.sendGuildMsg(i, msg),
recallMsg: message_id => this.recallMsg(i, message_id), recallMsg: message_id => this.recallMsg(i, message_id),
makeForwardMsg: Bot.makeForwardMsg, makeForwardMsg: Bot.makeForwardMsg,
@ -454,23 +482,28 @@ export default class gocqhttpAdapter {
getMemberArray: () => this.getGuildMemberArray(i), getMemberArray: () => this.getGuildMemberArray(i),
getMemberList: () => this.getGuildMemberList(i), getMemberList: () => this.getGuildMemberList(i),
getMemberMap: () => this.getGuildMemberMap(i), getMemberMap: () => this.getGuildMemberMap(i),
pickMember: user_id => this.pickMember(i, `${i.guild_id}-${i.channel_id}`, user_id), pickMember: user_id => this.pickMember(i, group_id, user_id),
} }
} }
const i = { ...data, group_id } const i = {
...Bot[data.self_id].gl.get(group_id),
...data,
group_id,
}
return { return {
...i,
sendMsg: msg => this.sendGroupMsg(i, msg), sendMsg: msg => this.sendGroupMsg(i, msg),
recallMsg: message_id => this.recallMsg(i, message_id), recallMsg: message_id => this.recallMsg(i, message_id),
makeForwardMsg: Bot.makeForwardMsg, makeForwardMsg: Bot.makeForwardMsg,
sendForwardMsg: msg => this.sendGroupForwardMsg(i, msg), sendForwardMsg: msg => this.sendGroupForwardMsg(i, msg),
sendFile: (file, name) => this.sendGroupFile(i, file, undefined, name), sendFile: (file, name) => this.sendGroupFile(i, file, undefined, name),
getInfo: () => this.getGroupInfo(i), getInfo: () => this.getGroupInfo(i),
getAvatarUrl: () => `https://p.qlogo.cn/gh/${i.group_id}/${i.group_id}/0`, getAvatarUrl: () => `https://p.qlogo.cn/gh/${group_id}/${group_id}/0`,
getMemberArray: () => this.getGroupMemberArray(i), getMemberArray: () => this.getGroupMemberArray(i),
getMemberList: () => this.getGroupMemberList(i), getMemberList: () => this.getGroupMemberList(i),
getMemberMap: () => this.getGroupMemberMap(i), getMemberMap: () => this.getGroupMemberMap(i),
pickMember: user_id => this.pickMember(i, i.group_id, user_id), pickMember: user_id => this.pickMember(i, group_id, user_id),
pokeMember: user_id => this.sendGroupMsg(i, segment.poke(user_id)), pokeMember: user_id => this.sendGroupMsg(i, segment.poke(user_id)),
setName: group_name => this.setGroupName(i, group_name), setName: group_name => this.setGroupName(i, group_name),
setAvatar: file => this.setGroupAvatar(i, file), setAvatar: file => this.setGroupAvatar(i, file),
@ -508,7 +541,7 @@ export default class gocqhttpAdapter {
Bot[data.self_id].info = (await data.sendApi("get_login_info")).data Bot[data.self_id].info = (await data.sendApi("get_login_info")).data
Bot[data.self_id].uin = Bot[data.self_id].info.user_id Bot[data.self_id].uin = Bot[data.self_id].info.user_id
Bot[data.self_id].nickname = Bot[data.self_id].info.nickname Bot[data.self_id].nickname = Bot[data.self_id].info.nickname
Bot[data.self_id].avatar = Bot[data.self_id].pickFriend(data.self_id).getAvatarUrl() Bot[data.self_id].avatar = `https://q1.qlogo.cn/g?b=qq&s=0&nk=${data.self_id}`
Bot[data.self_id].guild_info = (await data.sendApi("get_guild_service_profile")).data Bot[data.self_id].guild_info = (await data.sendApi("get_guild_service_profile")).data
Bot[data.self_id].tiny_id = Bot[data.self_id].guild_info.tiny_id Bot[data.self_id].tiny_id = Bot[data.self_id].guild_info.tiny_id
@ -530,17 +563,13 @@ export default class gocqhttpAdapter {
} }
Bot[data.self_id].status = Bot[data.self_id].version.protocol_name Bot[data.self_id].status = Bot[data.self_id].version.protocol_name
Bot[data.self_id].fl = await this.getFriendMap(data) Bot[data.self_id].fl = await Bot[data.self_id].getFriendMap()
Bot[data.self_id].gl = await this.getGroupMap(data) Bot[data.self_id].gl = await Bot[data.self_id].getGroupMap()
if (Array.isArray(Bot.uin)) { if (!Bot.uin.includes(data.self_id))
if (!Bot.uin.includes(data.self_id)) Bot.uin.push(data.self_id)
Bot.uin.push(data.self_id)
} else {
Bot.uin = [data.self_id]
}
logger.mark(`${logger.blue(`[${data.self_id}]`)} go-cqhttp 已连接`) logger.mark(`${logger.blue(`[${data.self_id}]`)} ${this.name}(${this.id}) 已连接`)
Bot.emit(`connect.${data.self_id}`, Bot[data.self_id]) Bot.emit(`connect.${data.self_id}`, Bot[data.self_id])
Bot.emit(`connect`, Bot[data.self_id]) Bot.emit(`connect`, Bot[data.self_id])
} }
@ -685,7 +714,7 @@ export default class gocqhttpAdapter {
if (data.group_id) { if (data.group_id) {
data.group = data.bot.pickGroup(data.group_id) data.group = data.bot.pickGroup(data.group_id)
data.member = data.group.pickMember(data.user_id) data.member = data.group.pickMember(data.user_id)
} else if (data.guild_id && data.channel_id){ } else if (data.guild_id && data.channel_id) {
data.group_id = `${data.guild_id}-${data.channel_id}` data.group_id = `${data.guild_id}-${data.channel_id}`
data.group = data.bot.pickGroup(data.group_id) data.group = data.bot.pickGroup(data.group_id)
data.member = data.group.pickMember(data.user_id) data.member = data.group.pickMember(data.user_id)
@ -755,6 +784,8 @@ export default class gocqhttpAdapter {
} }
if (data.post_type) { if (data.post_type) {
if (data.meta_event_type != "lifecycle" && !Bot.uin.includes(data.self_id))
return false
data.sendApi = (action, params) => this.sendApi(ws, action, params) data.sendApi = (action, params) => this.sendApi(ws, action, params)
data.bot = Bot[data.self_id] data.bot = Bot[data.self_id]
switch (data.post_type) { switch (data.post_type) {
@ -786,11 +817,11 @@ export default class gocqhttpAdapter {
} }
load() { load() {
const wss = new WebSocketServer({ noServer: true }) Bot.wss[this.name] = new WebSocketServer({ noServer: true })
wss.on("connection", ws => { Bot.wss[this.name].on("connection", ws => {
ws.on("error", logger.error) ws.on("error", logger.error)
ws.on("message", data => this.message(data, ws)) ws.on("message", data => this.message(data, ws))
}) })
return wss return true
} }
} })

View File

@ -1,7 +1,12 @@
import fs from "node:fs" import fs from "node:fs"
import path from "node:path" import path from "node:path"
export default class stdinAdapter { Bot.adapter.push(new class stdinAdapter {
constructor() {
this.id = "stdin"
this.name = "标准输入"
}
async makeBuffer(file) { async makeBuffer(file) {
if (file.match(/^base64:\/\//)) if (file.match(/^base64:\/\//))
return Buffer.from(file.replace(/^base64:\/\//, ""), "base64") return Buffer.from(file.replace(/^base64:\/\//, ""), "base64")
@ -25,21 +30,21 @@ export default class stdinAdapter {
case "text": case "text":
if (i.data.text.match("\n")) if (i.data.text.match("\n"))
i.data.text = `\n${i.data.text}` i.data.text = `\n${i.data.text}`
logger.info(`${logger.blue(`[stdin]`)} 发送文本:${i.data.text}`) logger.info(`${logger.blue(`[${this.id}]`)} 发送文本:${i.data.text}`)
break break
case "image": case "image":
i.file = `${Bot.stdin.data_dir}${Date.now()}.png` i.file = `${Bot[this.id].data_dir}${Date.now()}.png`
logger.info(`${logger.blue(`[stdin]`)} 发送图片:${i.data.file.replace(/^base64:\/\/.*/, "base64://...")}\n文件已保存到:${logger.cyan(i.file)}`) logger.info(`${logger.blue(`[${this.id}]`)} 发送图片:${i.data.file.replace(/^base64:\/\/.*/, "base64://...")}\n文件已保存到:${logger.cyan(i.file)}`)
fs.writeFileSync(i.file, await this.makeBuffer(i.data.file)) fs.writeFileSync(i.file, await this.makeBuffer(i.data.file))
break break
case "record": case "record":
i.file = `${Bot.stdin.data_dir}${Date.now()}.mp3` i.file = `${Bot[this.id].data_dir}${Date.now()}.mp3`
logger.info(`${logger.blue(`[stdin]`)} 发送音频:${i.data.file.replace(/^base64:\/\/.*/, "base64://...")}\n文件已保存到:${logger.cyan(i.file)}`) logger.info(`${logger.blue(`[${this.id}]`)} 发送音频:${i.data.file.replace(/^base64:\/\/.*/, "base64://...")}\n文件已保存到:${logger.cyan(i.file)}`)
fs.writeFileSync(i.file, await this.makeBuffer(i.data.file)) fs.writeFileSync(i.file, await this.makeBuffer(i.data.file))
break break
case "video": case "video":
i.file = `${Bot.stdin.data_dir}${Date.now()}.mp4` i.file = `${Bot[this.id].data_dir}${Date.now()}.mp4`
logger.info(`${logger.blue(`[stdin]`)} 发送视频:${i.data.file.replace(/^base64:\/\/.*/, "base64://...")}\n文件已保存到:${logger.cyan(i.file)}`) logger.info(`${logger.blue(`[${this.id}]`)} 发送视频:${i.data.file.replace(/^base64:\/\/.*/, "base64://...")}\n文件已保存到:${logger.cyan(i.file)}`)
fs.writeFileSync(i.file, await this.makeBuffer(i.data.file)) fs.writeFileSync(i.file, await this.makeBuffer(i.data.file))
break break
case "reply": case "reply":
@ -53,14 +58,14 @@ export default class stdinAdapter {
i = JSON.stringify(i) i = JSON.stringify(i)
if (i.match("\n")) if (i.match("\n"))
i = `\n${i}` i = `\n${i}`
logger.info(`${logger.blue(`[stdin]`)} 发送消息:${i}`) logger.info(`${logger.blue(`[${this.id}]`)} 发送消息:${i}`)
} }
} }
return { message_id: Date.now() } return { message_id: Date.now() }
} }
recallMsg(message_id) { recallMsg(message_id) {
logger.info(`${logger.blue(`[stdin]`)} 撤回消息:${message_id}`) logger.info(`${logger.blue(`[${this.id}]`)} 撤回消息:${message_id}`)
} }
sendForwardMsg(msg) { sendForwardMsg(msg) {
@ -73,12 +78,12 @@ export default class stdinAdapter {
async sendFile(file, name = path.basename(file)) { async sendFile(file, name = path.basename(file)) {
const buffer = await this.makeBuffer(file) const buffer = await this.makeBuffer(file)
if (!Buffer.isBuffer(buffer)) { if (!Buffer.isBuffer(buffer)) {
logger.error(`${logger.blue(`[stdin]`)} 发送文件错误:找不到文件 ${logger.red(file)}`) logger.error(`${logger.blue(`[${this.id}]`)} 发送文件错误:找不到文件 ${logger.red(file)}`)
return false return false
} }
const files = `${Bot.stdin.data_dir}${Date.now()}-${name}` const files = `${Bot[this.id].data_dir}${Date.now()}-${name}`
logger.info(`${logger.blue(`[stdin]`)} 发送文件:${file}\n文件已保存到:${logger.cyan(files)}`) logger.info(`${logger.blue(`[${this.id}]`)} 发送文件:${file}\n文件已保存到:${logger.cyan(files)}`)
return fs.writeFileSync(files, buffer) return fs.writeFileSync(files, buffer)
} }
@ -94,12 +99,12 @@ export default class stdinAdapter {
message(msg) { message(msg) {
const data = { const data = {
bot: Bot.stdin, bot: Bot[this.id],
self_id: "stdin", self_id: this.id,
user_id: "stdin", user_id: this.id,
post_type: "message", post_type: "message",
message_type: "private", message_type: "private",
sender: { nickname: "标准输入" }, sender: { nickname: this.name },
message: [{ type: "text", text: msg }], message: [{ type: "text", text: msg }],
raw_message: msg, raw_message: msg,
friend: this.pickFriend(), friend: this.pickFriend(),
@ -111,42 +116,38 @@ export default class stdinAdapter {
} }
load() { load() {
Bot.stdin = { Bot[this.id] = {
uin: "stdin", uin: this.id,
nickname: "标准输入", nickname: this.name,
stat: { start_time: Date.now()/1000 }, stat: { start_time: Date.now()/1000 },
version: { impl: "stdin" }, version: { id: this.id, name: this.name },
pickFriend: () => this.pickFriend(), pickFriend: () => this.pickFriend(),
pickUser: () => this.pickFriend(), pickUser: () => this.pickFriend(),
pickGroup: () => this.pickFriend(), pickGroup: () => this.pickFriend(),
pickMember: () => this.pickFriend(), pickMember: () => this.pickFriend(),
fl: new Map().set("stdin", { fl: new Map().set(this.id, {
user_id: "stdin", user_id: this.id,
nickname: "标准输入", nickname: this.name,
}), }),
gl: new Map().set("stdin", { gl: new Map().set(this.id, {
group_id: "stdin", group_id: this.id,
group_name: "标准输入", group_name: this.name,
}), }),
data_dir: `${process.cwd()}/data/stdin/`, data_dir: `${process.cwd()}/data/stdin/`,
} }
if (!fs.existsSync(Bot.stdin.data_dir)) if (!fs.existsSync(Bot[this.id].data_dir))
fs.mkdirSync(Bot.stdin.data_dir) fs.mkdirSync(Bot[this.id].data_dir)
if (Array.isArray(Bot.uin)) { if (!Bot.uin.includes(this.id))
if (!Bot.uin.includes("stdin")) Bot.uin.push(this.id)
Bot.uin.push("stdin")
} else {
Bot.uin = ["stdin"]
}
process.stdin.on("data", data => this.message(data.toString())) process[this.id].on("data", data => this.message(data.toString()))
logger.mark(`${logger.blue(`[stdin]`)} 标准输入 已连接`) logger.mark(`${logger.blue(`[${this.id}]`)} ${this.name}(${this.id}) 已连接`)
Bot.emit(`connect.stdin`, Bot.stdin) Bot.emit(`connect.${this.id}`, Bot[this.id])
Bot.emit(`connect`, Bot.stdin) Bot.emit(`connect`, Bot[this.id])
} }
} })