新增 GSUIDCore、微信 适配器,细节优化
This commit is contained in:
parent
c47e5a6519
commit
81d59035be
|
@ -1,5 +1,6 @@
|
||||||
# 3.1.0
|
# 3.1.0
|
||||||
|
|
||||||
|
* 支持协议端:GSUIDCore、微信
|
||||||
* 重构CK与UID管理逻辑
|
* 重构CK与UID管理逻辑
|
||||||
* 支持多UID绑定,可绑定多个UID并进行切换
|
* 支持多UID绑定,可绑定多个UID并进行切换
|
||||||
* 支持原神与星铁UID共存,可针对查询命令分配对应UID
|
* 支持原神与星铁UID共存,可针对查询命令分配对应UID
|
||||||
|
|
18
README.md
18
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# TRSS-Yunzai
|
# TRSS-Yunzai
|
||||||
|
|
||||||
Yunzai 应用端,支持多账号,支持协议端:go-cqhttp、ComWeChat、ICQQ、QQ频道、KOOK、Telegram、Discord
|
Yunzai 应用端,支持多账号,支持协议端:go-cqhttp、ComWeChat、GSUIDCore、ICQQ、QQ频道、微信、KOOK、Telegram、Discord
|
||||||
|
|
||||||
[](https://github.com/TimeRainStarSky/Yunzai)
|
[](https://github.com/TimeRainStarSky/Yunzai)
|
||||||
[](../../stargazers)
|
[](../../stargazers)
|
||||||
|
@ -110,6 +110,16 @@ websocket_url = ["ws://localhost:2536/ComWeChat"]
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details><summary>GSUIDCore</summary>
|
||||||
|
|
||||||
|
下载运行 [GenshinUID 插件](http://docs.gsuid.gbots.work/#/AdapterList),GSUIDCore 连接地址 修改为:
|
||||||
|
|
||||||
|
```
|
||||||
|
ws://localhost:2536/GSUIDCore
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
<details><summary>ICQQ</summary>
|
<details><summary>ICQQ</summary>
|
||||||
|
|
||||||
[TRSS-Yunzai ICQQ Plugin](../../../Yunzai-ICQQ-Plugin)
|
[TRSS-Yunzai ICQQ Plugin](../../../Yunzai-ICQQ-Plugin)
|
||||||
|
@ -122,6 +132,12 @@ websocket_url = ["ws://localhost:2536/ComWeChat"]
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details><summary>微信</summary>
|
||||||
|
|
||||||
|
[TRSS-Yunzai WeChat Plugin](../../../Yunzai-WeChat-Plugin)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
<details><summary>KOOK</summary>
|
<details><summary>KOOK</summary>
|
||||||
|
|
||||||
[TRSS-Yunzai KOOK Plugin](../../../Yunzai-KOOK-Plugin)
|
[TRSS-Yunzai KOOK Plugin](../../../Yunzai-KOOK-Plugin)
|
||||||
|
|
22
lib/bot.js
22
lib/bot.js
|
@ -23,21 +23,16 @@ export default class Yunzai extends EventEmitter {
|
||||||
this.emit("online", this)
|
this.emit("online", this)
|
||||||
}
|
}
|
||||||
|
|
||||||
serverRequest(req) {
|
serverLoad() {
|
||||||
|
this.server.all("*", req => {
|
||||||
logger.info(`${logger.blue(`[${req.ip}]`)} HTTP ${req.method} 请求:${req.url} ${JSON.stringify(req.rawHeaders)}`)
|
logger.info(`${logger.blue(`[${req.ip}]`)} HTTP ${req.method} 请求:${req.url} ${JSON.stringify(req.rawHeaders)}`)
|
||||||
req.res.redirect("https://github.com/TimeRainStarSky/Yunzai")
|
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 = http.createServer(this.server)
|
||||||
|
|
||||||
this.server.on("upgrade", (req, socket, head) => {
|
this.server.on("upgrade", (req, socket, head) => {
|
||||||
for (const i of Object.keys(this.wss))
|
const wss = this.wss[req.url.split("/")[1]]
|
||||||
if (req.url == `/${i}`)
|
if (wss) wss.handleUpgrade(req, socket, head, conn => wss.emit("connection", conn, req))
|
||||||
return this.wss[i].handleUpgrade(req, socket, head, conn =>
|
|
||||||
this.wss[i].emit("connection", conn, req))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this.server.listen(cfg.bot.port, () => {
|
this.server.listen(cfg.bot.port, () => {
|
||||||
|
@ -197,4 +192,11 @@ export default class Yunzai extends EventEmitter {
|
||||||
msg.replace = () => msg
|
msg.replace = () => msg
|
||||||
return { type: "node", data: 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
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -11,16 +11,15 @@ process.env.TZ = 'Asia/Shanghai'
|
||||||
|
|
||||||
/** 捕获未处理的Promise错误 */
|
/** 捕获未处理的Promise错误 */
|
||||||
process.on('unhandledRejection', (error, promise) => {
|
process.on('unhandledRejection', (error, promise) => {
|
||||||
let err = error
|
|
||||||
if (logger) {
|
if (logger) {
|
||||||
logger.error(err)
|
logger.error(error)
|
||||||
} else {
|
} else {
|
||||||
console.log(err)
|
console.log(error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 退出事件 */
|
/** 退出事件 */
|
||||||
process.on('exit', async (code) => {
|
process.on('exit', async code => {
|
||||||
if (typeof redis != 'undefined' && typeof test == 'undefined')
|
if (typeof redis != 'undefined' && typeof test == 'undefined')
|
||||||
await redis.save()
|
await redis.save()
|
||||||
logger.mark(logger.magenta('TRSS-Yunzai 已停止运行'))
|
logger.mark(logger.magenta('TRSS-Yunzai 已停止运行'))
|
||||||
|
@ -29,7 +28,7 @@ process.on('exit', async (code) => {
|
||||||
await checkInit()
|
await checkInit()
|
||||||
|
|
||||||
/** 初始化事件 */
|
/** 初始化事件 */
|
||||||
async function checkInit () {
|
async function checkInit() {
|
||||||
/** 日志设置 */
|
/** 日志设置 */
|
||||||
setLog()
|
setLog()
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ Bot.adapter.push(new class stdinAdapter {
|
||||||
return Buffer.from(await (await fetch(file)).arrayBuffer())
|
return Buffer.from(await (await fetch(file)).arrayBuffer())
|
||||||
else if (fs.existsSync(file))
|
else if (fs.existsSync(file))
|
||||||
return Buffer.from(fs.readFileSync(file))
|
return Buffer.from(fs.readFileSync(file))
|
||||||
else
|
|
||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +68,7 @@ Bot.adapter.push(new class stdinAdapter {
|
||||||
case "at":
|
case "at":
|
||||||
break
|
break
|
||||||
case "node":
|
case "node":
|
||||||
this.sendForwardMsg(i.data)
|
Bot.sendForwardMsg(msg => this.sendMsg(msg), i.data)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
i = JSON.stringify(i)
|
i = JSON.stringify(i)
|
||||||
|
@ -85,13 +84,6 @@ Bot.adapter.push(new class stdinAdapter {
|
||||||
logger.info(`${logger.blue(`[${this.id}]`)} 撤回消息:${message_id}`)
|
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)) {
|
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)) {
|
||||||
|
@ -109,7 +101,7 @@ Bot.adapter.push(new class stdinAdapter {
|
||||||
sendMsg: msg => this.sendMsg(msg),
|
sendMsg: msg => this.sendMsg(msg),
|
||||||
recallMsg: message_id => this.recallMsg(message_id),
|
recallMsg: message_id => this.recallMsg(message_id),
|
||||||
makeForwardMsg: Bot.makeForwardMsg,
|
makeForwardMsg: Bot.makeForwardMsg,
|
||||||
sendForwardMsg: msg => this.sendForwardMsg(msg),
|
sendForwardMsg: msg => Bot.sendForwardMsg(msg => this.sendMsg(msg), msg),
|
||||||
sendFile: (file, name) => this.sendFile(file, name),
|
sendFile: (file, name) => this.sendFile(file, name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,8 +132,8 @@ Bot.adapter.push(new class stdinAdapter {
|
||||||
version: { id: this.id, name: this.name },
|
version: { id: this.id, name: this.name },
|
||||||
pickFriend: () => this.pickFriend(),
|
pickFriend: () => this.pickFriend(),
|
||||||
pickUser: () => this.pickFriend(),
|
pickUser: () => this.pickFriend(),
|
||||||
pickGroup: () => this.pickFriend(),
|
|
||||||
pickMember: () => this.pickFriend(),
|
pickMember: () => this.pickFriend(),
|
||||||
|
pickGroup: () => this.pickFriend(),
|
||||||
|
|
||||||
fl: new Map().set(this.id, {
|
fl: new Map().set(this.id, {
|
||||||
user_id: this.id,
|
user_id: this.id,
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
"yaml": "^2.3.1"
|
"yaml": "^2.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.43.0",
|
"eslint": "^8.44.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.1",
|
"eslint-plugin-n": "^16.0.1",
|
||||||
|
|
|
@ -7,6 +7,7 @@ Bot.adapter.push(new class ComWeChatAdapter {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.id = "WeChat"
|
this.id = "WeChat"
|
||||||
this.name = "ComWeChat"
|
this.name = "ComWeChat"
|
||||||
|
this.path = this.name
|
||||||
}
|
}
|
||||||
|
|
||||||
toStr(data) {
|
toStr(data) {
|
||||||
|
@ -21,6 +22,7 @@ Bot.adapter.push(new class ComWeChatAdapter {
|
||||||
else
|
else
|
||||||
return JSON.stringify(data)
|
return JSON.stringify(data)
|
||||||
}
|
}
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
makeLog(msg) {
|
makeLog(msg) {
|
||||||
|
@ -37,8 +39,23 @@ Bot.adapter.push(new class ComWeChatAdapter {
|
||||||
resolve({ ...data, ...data.data })))
|
resolve({ ...data, ...data.data })))
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadFile(data, file, name = randomUUID()) {
|
async fileName(file) {
|
||||||
const opts = { name }
|
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?:\/\//)) {
|
if (file.match(/^https?:\/\//)) {
|
||||||
opts.type = "url"
|
opts.type = "url"
|
||||||
|
@ -54,6 +71,7 @@ Bot.adapter.push(new class ComWeChatAdapter {
|
||||||
opts.path = file
|
opts.path = file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info(`${logger.blue(`[${data.self_id}]`)} 上传文件:${this.makeLog(opts)}`)
|
||||||
return data.sendApi("upload_file", 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 }}
|
i = { type: i.type, data: { ...i, type: undefined }}
|
||||||
if (i.data.file)
|
if (i.data.file)
|
||||||
i.data = { file_id: (await this.uploadFile(data, i.data.file)).file_id }
|
i.data = { file_id: (await this.uploadFile(data, i.data.file)).file_id }
|
||||||
|
|
||||||
switch (i.type) {
|
switch (i.type) {
|
||||||
|
case "text":
|
||||||
|
break
|
||||||
|
case "image":
|
||||||
|
break
|
||||||
|
case "record":
|
||||||
|
i.type = "file"
|
||||||
|
break
|
||||||
|
case "video":
|
||||||
|
i.type = "file"
|
||||||
|
break
|
||||||
case "at":
|
case "at":
|
||||||
if (i.data.qq == "all")
|
if (i.data.qq == "all")
|
||||||
msgs.push({ type: "mention_all", data: {}})
|
i = { type: "mention_all", data: {}}
|
||||||
else
|
else
|
||||||
msgs.push({ type: "mention", data: { user_id: i.data.qq }})
|
i = { type: "mention", data: { user_id: i.data.qq }}
|
||||||
break
|
break
|
||||||
case "reply":
|
case "reply":
|
||||||
|
i = { type: "text", data: { text: `回复:${i.data.id}\n` }}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
msgs.push(i)
|
i = { type: "text", data: { text: JSON.stringify(i) }}
|
||||||
}
|
}
|
||||||
|
msgs.push(i)
|
||||||
}
|
}
|
||||||
return msgs
|
return msgs
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendFriendMsg(data, msg) {
|
async sendFriendMsg(data, msg) {
|
||||||
if (msg?.type == "node")
|
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", {
|
return data.sendApi("send_message", {
|
||||||
detail_type: "private",
|
detail_type: "private",
|
||||||
user_id: data.user_id,
|
user_id: data.user_id,
|
||||||
message: await this.makeMsg(data, msg),
|
message,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendGroupMsg(data, msg) {
|
async sendGroupMsg(data, msg) {
|
||||||
if (msg?.type == "node")
|
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", {
|
return data.sendApi("send_message", {
|
||||||
detail_type: "group",
|
detail_type: "group",
|
||||||
group_id: data.group_id,
|
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) {
|
async getFriendArray(data) {
|
||||||
const array = []
|
const array = []
|
||||||
for (const i of (await data.sendApi("get_friend_list")).data)
|
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})`)
|
logger.info(`${logger.blue(`[${data.self_id}]`)} 发送文件:${name}(${file})`)
|
||||||
return send(segment.custom("file", {
|
return send(segment.custom("file", {
|
||||||
file_id: (await this.uploadFile(data, file, name)).file_id
|
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),
|
sendMsg: msg => this.sendFriendMsg(i, msg),
|
||||||
recallMsg: () => false,
|
recallMsg: () => false,
|
||||||
makeForwardMsg: Bot.makeForwardMsg,
|
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),
|
sendFile: (file, name) => this.sendFile(i, msg => this.sendFriendMsg(i, msg), file, name),
|
||||||
getInfo: () => this.getFriendInfo(i),
|
getInfo: () => this.getFriendInfo(i),
|
||||||
getAvatarUrl: async () => (await this.getFriendInfo(i))["wx.avatar"],
|
getAvatarUrl: async () => (await this.getFriendInfo(i))["wx.avatar"],
|
||||||
|
@ -247,7 +273,7 @@ Bot.adapter.push(new class ComWeChatAdapter {
|
||||||
sendMsg: msg => this.sendGroupMsg(i, msg),
|
sendMsg: msg => this.sendGroupMsg(i, msg),
|
||||||
recallMsg: () => false,
|
recallMsg: () => false,
|
||||||
makeForwardMsg: Bot.makeForwardMsg,
|
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),
|
sendFile: (file, name) => this.sendFile(i, msg => this.sendGroupMsg(i, msg), file, name),
|
||||||
getInfo: () => this.getGroupInfo(i),
|
getInfo: () => this.getGroupInfo(i),
|
||||||
getAvatarUrl: async () => (await this.getGroupInfo(i))["wx.avatar"],
|
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
|
data.self_id = bot.self.user_id
|
||||||
|
|
||||||
Bot[data.self_id] = {
|
Bot[data.self_id] = {
|
||||||
|
adapter: this,
|
||||||
sendApi: data.sendApi,
|
sendApi: data.sendApi,
|
||||||
stat: { ...data.status, start_time: data.time },
|
stat: { ...data.status, start_time: data.time },
|
||||||
|
|
||||||
|
pickUser: user_id => this.pickFriend(data, user_id),
|
||||||
pickFriend: user_id => this.pickFriend(data, user_id),
|
pickFriend: user_id => this.pickFriend(data, user_id),
|
||||||
|
|
||||||
getFriendArray: () => this.getFriendArray(data),
|
getFriendArray: () => this.getFriendArray(data),
|
||||||
|
@ -279,7 +307,6 @@ Bot.adapter.push(new class ComWeChatAdapter {
|
||||||
getGroupList: () => this.getGroupList(data),
|
getGroupList: () => this.getGroupList(data),
|
||||||
getGroupMap: () => this.getGroupMap(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].info = (await data.sendApi("get_self_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
|
||||||
|
@ -411,8 +438,8 @@ Bot.adapter.push(new class ComWeChatAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
Bot.wss[this.name] = new WebSocketServer({ noServer: true })
|
Bot.wss[this.path] = new WebSocketServer({ noServer: true })
|
||||||
Bot.wss[this.name].on("connection", ws => {
|
Bot.wss[this.path].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))
|
||||||
})
|
})
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
})
|
|
@ -6,6 +6,7 @@ Bot.adapter.push(new class gocqhttpAdapter {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.id = "QQ"
|
this.id = "QQ"
|
||||||
this.name = "go-cqhttp"
|
this.name = "go-cqhttp"
|
||||||
|
this.path = this.name
|
||||||
}
|
}
|
||||||
|
|
||||||
toStr(data) {
|
toStr(data) {
|
||||||
|
@ -20,6 +21,7 @@ Bot.adapter.push(new class gocqhttpAdapter {
|
||||||
else
|
else
|
||||||
return JSON.stringify(data)
|
return JSON.stringify(data)
|
||||||
}
|
}
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
makeLog(msg) {
|
makeLog(msg) {
|
||||||
|
@ -525,6 +527,7 @@ Bot.adapter.push(new class gocqhttpAdapter {
|
||||||
|
|
||||||
async connect(data) {
|
async connect(data) {
|
||||||
Bot[data.self_id] = {
|
Bot[data.self_id] = {
|
||||||
|
adapter: this,
|
||||||
sendApi: data.sendApi,
|
sendApi: data.sendApi,
|
||||||
stat: { start_time: data.time },
|
stat: { start_time: data.time },
|
||||||
|
|
||||||
|
@ -532,6 +535,7 @@ Bot.adapter.push(new class gocqhttpAdapter {
|
||||||
recallMsg: message_id => this.recallMsg(data, message_id),
|
recallMsg: message_id => this.recallMsg(data, message_id),
|
||||||
getForwardMsg: message_id => this.getForwardMsg(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),
|
pickFriend: user_id => this.pickFriend(data, user_id),
|
||||||
|
|
||||||
getFriendArray: () => this.getFriendArray(data),
|
getFriendArray: () => this.getFriendArray(data),
|
||||||
|
@ -545,7 +549,6 @@ Bot.adapter.push(new class gocqhttpAdapter {
|
||||||
getGroupList: () => this.getGroupList(data),
|
getGroupList: () => this.getGroupList(data),
|
||||||
getGroupMap: () => this.getGroupMap(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].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
|
||||||
|
@ -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 = (await data.sendApi("get_version_info")).data
|
||||||
Bot[data.self_id].version = {
|
Bot[data.self_id].version = {
|
||||||
...Bot[data.self_id].version,
|
...Bot[data.self_id].version,
|
||||||
impl: Bot[data.self_id].version.app_name,
|
id: this.id,
|
||||||
version: Bot[data.self_id].version.app_version,
|
name: this.name,
|
||||||
onebot_version: Bot[data.self_id].version.protocol_version,
|
|
||||||
}
|
}
|
||||||
Bot[data.self_id].status = Bot[data.self_id].version.protocol_name
|
Bot[data.self_id].status = Bot[data.self_id].version.protocol_name
|
||||||
|
|
||||||
|
@ -829,8 +831,8 @@ Bot.adapter.push(new class gocqhttpAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
Bot.wss[this.name] = new WebSocketServer({ noServer: true })
|
Bot.wss[this.path] = new WebSocketServer({ noServer: true })
|
||||||
Bot.wss[this.name].on("connection", ws => {
|
Bot.wss[this.path].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))
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,6 +16,7 @@ const list = {
|
||||||
"Telegram-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-Telegram-Plugin",
|
"Telegram-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-Telegram-Plugin",
|
||||||
"Discord-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-Discord-Plugin",
|
"Discord-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-Discord-Plugin",
|
||||||
"QQGuild-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-QQGuild-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",
|
"ICQQ-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-ICQQ-Plugin",
|
||||||
"KOOK-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-KOOK-Plugin",
|
"KOOK-Plugin" :"https://gitee.com/TimeRainStarSky/Yunzai-KOOK-Plugin",
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue