From 72ae91988806fa434161777ef5b48af31b9b2860 Mon Sep 17 00:00:00 2001 From: Dragon-Fish Date: Tue, 16 Jan 2024 15:58:39 +0800 Subject: [PATCH] feat: + MinecraftConnect --- src/index.ts | 6 +- src/modules/MinecraftConnect.ts | 35 +++++++ src/plugins/adapter-minecraft.ts | 91 +++++++++++++++++-- .../index.html" | 4 +- .../index.ts" | 4 +- 5 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 src/modules/MinecraftConnect.ts diff --git a/src/index.ts b/src/index.ts index f95f494..98ffeb0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -81,7 +81,8 @@ import * as PluginSwitch from 'koishi-plugin-switch' import { HTMLService } from '$utils/RenderHTML' -import { AdapterMinecraft } from './plugins/adapter-minecraft' +import { MinecraftConnect } from './modules/MinecraftConnect' +import { MinecraftBot } from './plugins/adapter-minecraft' const PROD = process.env.NODE_ENV === 'production' @@ -171,7 +172,7 @@ app.plugin(function PluginCollectionAdapters(ctx) { // Minecraft if (env.MINECRAFT_TOKEN) { - ctx.plugin(AdapterMinecraft, { + ctx.plugin(MinecraftBot, { host: env.MINECRAFT_HOST, port: Number(env.MINECRAFT_PORT), protocol: env.MINECRAFT_PROTOCOL as 'ws' | 'wss', @@ -367,6 +368,7 @@ app.plugin(function PluginCollectionInternal(ctx) { ctx.plugin(PluginReboot) ctx.plugin(PluginSensitiveFilter) ctx.plugin(PluginSpawn, { shell: 'pwsh' }) + ctx.plugin(MinecraftConnect) }) /** 启动应用程序 */ diff --git a/src/modules/MinecraftConnect.ts b/src/modules/MinecraftConnect.ts new file mode 100644 index 0000000..011e290 --- /dev/null +++ b/src/modules/MinecraftConnect.ts @@ -0,0 +1,35 @@ +import { Context } from 'koishi' + +import { MinecraftBot } from '@/plugins/adapter-minecraft' + +import BasePlugin from '~/_boilerplate' + +export class MinecraftConnect extends BasePlugin { + constructor( + public ctx: Context, + options + ) { + super(ctx, options, 'mc-connect') + + const QQ_GROUP = process.env.CHANNEL_QQ_NGNL_MINECRAFT + + const qqBot = ctx.bots.find((bot) => + ['onebot', 'red'].includes(bot.platform) + ) + const qqCtx = ctx.channel(QQ_GROUP, process.env.CHANNEL_QQ_SANDBOX) + const mcBot = ctx.bots.find( + (bot) => bot.platform === 'minecraft' + ) as MinecraftBot + const mcCtx = ctx.platform('minecraft') + + mcCtx.on('message', (session) => { + qqBot.sendMessage( + QQ_GROUP, + `[MC] ${session.username}:\n${session.content}` + ) + }) + qqCtx.on('message', (session) => { + mcBot.sendMessageAs(session.username, session.content) + }) + } +} diff --git a/src/plugins/adapter-minecraft.ts b/src/plugins/adapter-minecraft.ts index fba6e1f..f2b72f9 100644 --- a/src/plugins/adapter-minecraft.ts +++ b/src/plugins/adapter-minecraft.ts @@ -1,4 +1,6 @@ -import { Adapter, Bot, Context, Logger, Session } from 'koishi' +import { Adapter, Bot, Context, Fragment, Logger, h } from 'koishi' + +import { SendOptions } from '@satorijs/protocol' export interface Config extends Adapter.WsClientConfig { host: string @@ -16,6 +18,7 @@ export class MinecraftBot extends Bot { protocol: 'ws', token: '', } + public ws?: ReturnType constructor( public ctx: C, @@ -24,6 +27,7 @@ export class MinecraftBot extends Bot { config = { ...MinecraftBot.defaultConfig, ...config } super(ctx, config) this.platform = 'minecraft' + this.ctx.root.plugin(AdapterMinecraft, this) } get serverURL() { @@ -33,6 +37,57 @@ export class MinecraftBot extends Bot { url.protocol = this.config.protocol return url } + + async sendMessage( + channelId: string, + content: Fragment, + guildId?: string, + options?: SendOptions & { + sendAs?: string + } + ): Promise { + this.ws.send( + JSON.stringify({ + Name: options.sendAs || this.ctx.root.config.name || 'koishi', + Content: this.stringifyContent(content), + }) + ) + return [] + } + + async sendMessageAs(username: string, content: Fragment) { + return this.sendMessage('0', content, undefined, { + sendAs: username, + }) + } + + stringifyContent(content: Fragment) { + const elements = h.parse(content.toString()) + console.log('[[stringifyContent]] income:', content, elements) + return elements + .map((el) => { + console.log('[[stringifyContent]] map:', el) + if (el.type === 'text') return el + switch (el.type) { + default: + return el + case 'at': + return h.text(`@${el.attrs.name || el.attrs.id}`) + case 'img': + case 'image': + return h.text('[图片]') + case 'video': + return h.text('[视频]') + case 'audio': + return h.text('[音频]') + case 'file': + return h.text('[文件]') + case 'face': + return h.text('[表情]') + } + }) + .join('') + } } export class AdapterMinecraft extends Adapter.WsClient< @@ -40,19 +95,41 @@ export class AdapterMinecraft extends Adapter.WsClient< MinecraftBot > { protected async prepare() { - return this.ctx.http.ws(this.bot.serverURL.href, { + const ws = this.ctx.http.ws(this.bot.serverURL.href, { headers: { authorization: `Bot ${this.bot.config.token}`, }, }) + this.bot.ws = ws + return ws } protected accept(): void { this.bot.online() - this.socket.addEventListener('message', (raw: any) => { - const data = JSON.parse(raw.toString()) - logger.info('[recieved]', raw, data) - - // if (!this.bot.) return + // this.bot.sendMessage('0', 'SILI is online') + this.socket.addEventListener('message', (msg: any) => { + const data: { + Name: string + Content: string + } = typeof msg.data === 'string' ? JSON.parse(msg.data) : msg.data + logger.info('[message]', data) + const user = { + id: 'MC:' + data.Name, + name: data.Name, + } + const channel = { + id: '0', + type: 0, + } + const session = this.bot.session({ + type: 'message', + user, + channel, + message: { + user, + }, + }) + session.content = data.Content + this.bot.dispatch(session) }) } } diff --git "a/src/plugins/sticker/\350\224\232\350\223\235\346\241\243\346\241\210/index.html" "b/src/plugins/sticker/\350\224\232\350\223\235\346\241\243\346\241\210/index.html" index b014c54..5e470c3 100644 --- "a/src/plugins/sticker/\350\224\232\350\223\235\346\241\243\346\241\210/index.html" +++ "b/src/plugins/sticker/\350\224\232\350\223\235\346\241\243\346\241\210/index.html" @@ -6,11 +6,11 @@ Document diff --git "a/src/plugins/sticker/\350\224\232\350\223\235\346\241\243\346\241\210/index.ts" "b/src/plugins/sticker/\350\224\232\350\223\235\346\241\243\346\241\210/index.ts" index 8e52a04..8824f10 100644 --- "a/src/plugins/sticker/\350\224\232\350\223\235\346\241\243\346\241\210/index.ts" +++ "b/src/plugins/sticker/\350\224\232\350\223\235\346\241\243\346\241\210/index.ts" @@ -57,9 +57,9 @@ export default class 蔚蓝档案 extends BaseSticker { url.searchParams.set('rightText', rightText) await page.goto(url.toString(), { waitUntil: 'load', - timeout: 8 * 1000, + timeout: 15 * 1000, }) - await page.waitForNetworkIdle({ timeout: 5 * 1000 }) + await page.waitForNetworkIdle({ timeout: 10 * 1000 }) const logo = await page.$('#logo') const buffer = await logo?.screenshot({ type: 'jpeg' }) return h.image(buffer, 'image/jpeg')