From 9a0182feed820277e0e7d70971911f607cf6aeeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=89=E8=8F=9C?= <1659488338@qq.com> Date: Mon, 8 Jul 2024 22:55:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20kritor=20=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/adapters/kritor/src/client.ts | 142 ++++++++++++++++++++----- packages/adapters/kritor/src/index.ts | 6 +- 2 files changed, 118 insertions(+), 30 deletions(-) diff --git a/packages/adapters/kritor/src/client.ts b/packages/adapters/kritor/src/client.ts index 95853bce..ef635df1 100644 --- a/packages/adapters/kritor/src/client.ts +++ b/packages/adapters/kritor/src/client.ts @@ -3,7 +3,7 @@ import * as grpc from '@grpc/grpc-js'; import { loadSync, Long } from '@grpc/proto-loader'; import { kritor, proto } from 'kritor-proto'; import * as path from 'path'; -import { Adapter } from 'zhin'; +import { Adapter, Dict, parseFromTemplate, valueMap } from 'zhin'; export class Client extends EventEmitter { services: Client.Services; @@ -66,18 +66,18 @@ export class Client extends EventEmitter { } public createContact(target_id: string, target_type: 'guild' | 'group' | 'private' | 'temp_from_group' | 'temp') { const [peer, sub_peer] = target_id.split(':'); - return new kritor.common.Contact({ + return { scene: Client.sceneMap[target_type], peer, sub_peer: sub_peer || undefined, - }); + }; } #emitEvent(eventStream: NodeJS.ReadableStream) { eventStream.on('error', e => { this.adapter.logger.error('Event stream error:', e); }); - eventStream.on('data', event => { - console.log(event); + eventStream.on('data', (event: kritor.event.EventStructure) => { + this.emit(event.event!, event.message || event.notice || event.request); }); eventStream.on('end', () => { this.adapter.logger.debug('Event stream end'); @@ -119,7 +119,6 @@ export class Client extends EventEmitter { includeDirs: [proto], longs: String, keepCase: true, - enums: String, defaults: true, oneofs: true, }), @@ -548,16 +547,12 @@ export class Client extends EventEmitter { * @param elements * @param retry_count */ - async sendMessage(contact: kritor.common.Contact, elements: kritor.common.Element[], retry_count = 1) { + async sendMessage(contact: kritor.common.IContact, elements: kritor.common.Element[], retry_count = 1) { return new Promise((resolve, reject) => { - for (let i = 0; i < retry_count; i++) { - this.services.message.sendMessage({ contact, elements }, (err, res) => { - if (!err) { - resolve(res); - return; - } - }); - } + this.services.message.sendMessage({ contact, elements, retry_count }, (err, res) => { + if (err) reject(err); + resolve(res); + }); }); } @@ -568,16 +563,11 @@ export class Client extends EventEmitter { * @param retry_count */ async sendMessageByResId(contact: kritor.common.Contact, res_id: string, retry_count = 1) { - return new Promise((resolve, reject) => { - for (let i = 0; i < retry_count; i++) { - this.services.message.sendMessageByResId({ contact, res_id }, (err, res) => { - if (!err) { - resolve(res); - return; - } - console.error(`sendMessageByResId failed, retrying ${retry_count - i} times...`, err); - }); - } + return new Promise(async (resolve, reject) => { + this.services.message.sendMessageByResId({ contact, res_id, retry_count }, (err, res) => { + if (err) reject(err); + resolve(res); + }); }); } @@ -812,15 +802,24 @@ export namespace Client { web: kritor.web.WebService; }; export function createElementsFromTemplate(template: string): kritor.common.Element[] { - return []; + return parseFromTemplate(template).map(item => { + const { type, data } = item; + return Client.toKritorElement(type, data); + }) as kritor.common.Element[]; } export function eventMessageToString(event: kritor.common.IPushMessageBody) { return (event.elements || []) .map(element => { const { type, ...attrs } = element; - return `<${element.type} ${Object.entries(attrs).map((key, valut) => { - return `${key}='${encodeURIComponent(JSON.stringify(valut))}'`; - })}>`; + const key = Reflect.get(attrs, 'data'); + const data = Reflect.get(attrs, key); + if (type === kritor.common.Element.ElementType.TEXT) return data.text || ''; + return `<${key} ${Object.entries(data) + .filter(([key]) => !key.startsWith('_')) + .map(([key, value]) => { + return `${key}='${encodeURIComponent(JSON.stringify(value))}'`; + }) + .join(' ')}>`; }) .join(''); } @@ -839,4 +838,89 @@ export namespace Client { export function getMessageType(event: kritor.common.IPushMessageBody) { return messageTypeMap[event.contact?.scene!]; } + export const elementTypeMap = { + [kritor.common.Element.ElementType.TEXT]: 'text', + [kritor.common.Element.ElementType.RPS]: 'rps', + [kritor.common.Element.ElementType.DICE]: 'dice', + [kritor.common.Element.ElementType.IMAGE]: 'image', + [kritor.common.Element.ElementType.AT]: 'at', + [kritor.common.Element.ElementType.BASKETBALL]: 'basketball', + [kritor.common.Element.ElementType.BUBBLE_FACE]: 'bubble', + [kritor.common.Element.ElementType.CONTACT]: 'contact', + [kritor.common.Element.ElementType.FACE]: 'face', + [kritor.common.Element.ElementType.FILE]: 'file', + [kritor.common.Element.ElementType.FORWARD]: 'forward', + [kritor.common.Element.ElementType.GIFT]: 'gift', + [kritor.common.Element.ElementType.JSON]: 'json', + [kritor.common.Element.ElementType.LOCATION]: 'location', + [kritor.common.Element.ElementType.KEYBOARD]: 'keyboard', + [kritor.common.Element.ElementType.MARKDOWN]: 'markdown', + [kritor.common.Element.ElementType.POKE]: 'poke', + [kritor.common.Element.ElementType.REPLY]: 'reply', + [kritor.common.Element.ElementType.MUSIC]: 'music', + [kritor.common.Element.ElementType.SHARE]: 'share', + [kritor.common.Element.ElementType.WEATHER]: 'weather', + [kritor.common.Element.ElementType.VOICE]: 'voice', + [kritor.common.Element.ElementType.VIDEO]: 'video', + [kritor.common.Element.ElementType.XML]: 'xml', + [kritor.common.Element.ElementType.MARKET_FACE]: 'market_face', + }; + type ElementTypeMap = typeof elementTypeMap; + export type ElementType = ElementTypeMap[keyof ElementTypeMap]; + export function toKritorElement(type: ElementType, data: Dict) { + switch (type) { + case 'text': + return { text: data }; + case 'rps': + return { rps: data }; + case 'dice': + return { dice: data }; + case 'image': + return { image: data }; + case 'at': + return { at: data }; + case 'basketball': + return { basketball: data }; + case 'bubble': + return { bubble: data }; + case 'contact': + return { contact: data }; + case 'face': + return { face: data }; + case 'file': + return { file: data }; + case 'forward': + return { forward: data }; + case 'gift': + return { gift: data }; + case 'json': + return { json: data }; + case 'location': + return { location: data }; + case 'keyboard': + return { keyboard: data }; + case 'markdown': + return { markdown: data }; + case 'poke': + return { poke: data }; + case 'reply': + return { reply: data }; + case 'music': + return { music: data }; + case 'share': + return { share: data }; + case 'weather': + return { weather: data }; + case 'voice': + return { voice: data }; + case 'video': + return { video: data }; + case 'xml': + return { xml: data }; + case 'market_face': + return { market_face: data }; + default: + throw new Error(`Unsupported element type: ${type}`); + } + } } diff --git a/packages/adapters/kritor/src/index.ts b/packages/adapters/kritor/src/index.ts index c812d9ac..984b6169 100644 --- a/packages/adapters/kritor/src/index.ts +++ b/packages/adapters/kritor/src/index.ts @@ -18,12 +18,15 @@ adapter.define('sendMsg', async (bot_id, target_id, target_type, message, source const bot = adapter.pick(bot_id); const contact = bot.createContact(target_id, target_type as any); await bot.sendMessage(contact, Client.createElementsFromTemplate(message)); + bot.logger.info(`send [${target_type} ${target_id}]:${decodeURIComponent(message)}`); }); const messageHandler = (bot: Adapter.Bot, event: kritor.common.IPushMessageBody) => { const message = Message.fromEvent(adapter, bot, event); message.raw_message = Client.eventMessageToString(event); message.message_type = Client.getMessageType(event) as Message.Type; - message.from_id = [event.contact?.peer, event.contact?.sub_peer].filter(Boolean).join(':'); + message.from_id = Array.from(new Set([event.contact?.peer, event.contact?.sub_peer])) + .filter(Boolean) + .join(':'); const master = adapter.botConfig(bot)?.master; const admins = adapter.botConfig(bot)?.admins; message.sender = { @@ -34,6 +37,7 @@ const messageHandler = (bot: Adapter.Bot, event: kritor.common.IPushMess admins && admins.includes(event.sender?.uid || '') && 'admins', ].filter(Boolean) as string[], }; + bot.logger.info(`recv [${message.message_type} ${message.from_id}]: ${message.raw_message}`); adapter.app!.emit('message', adapter, bot, message); }; const startBots = (configs: App.BotConfig<'kritor'>[]) => {