From 01461f826c214161c458b2cf02ddd3d491438967 Mon Sep 17 00:00:00 2001 From: Shigma Date: Mon, 28 Oct 2024 18:14:27 +0800 Subject: [PATCH] feat(lark): support interaction/command event --- adapters/lark/src/types/event.ts | 21 ++++++------ adapters/lark/src/types/message/index.ts | 41 +++++++++++++++++++++--- adapters/lark/src/utils.ts | 35 ++++++++++++++++++-- yakumo.yml | 11 +++++-- 4 files changed, 88 insertions(+), 20 deletions(-) diff --git a/adapters/lark/src/types/event.ts b/adapters/lark/src/types/event.ts index bcbdb962..c1ea1cbb 100644 --- a/adapters/lark/src/types/event.ts +++ b/adapters/lark/src/types/event.ts @@ -1,6 +1,6 @@ -export interface EventHeader { +export interface EventHeader { event_id: string - event_type: T + event_type: K create_time: string token: string app_id: string @@ -12,11 +12,12 @@ export type EventName = keyof Events // In fact, this is the 2.0 version of the event sent by Lark. // And only the 2.0 version has the `schema` field. -export type EventSkeleton> = { - schema: '2.0' - type: T - header: Header - event: Event -} - -export type AllEvents = Events[EventName] +export type EventPayload = { + [K in keyof Events]: { + schema: '2.0' + // special added field for TypeScript + type: K + header: EventHeader + event: Events[K] + } +}[keyof Events] diff --git a/adapters/lark/src/types/message/index.ts b/adapters/lark/src/types/message/index.ts index 98f7ef77..75224b15 100644 --- a/adapters/lark/src/types/message/index.ts +++ b/adapters/lark/src/types/message/index.ts @@ -25,7 +25,7 @@ declare module '../event' { * Receive message event. * @see https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/events/receive */ - 'im.message.receive_v1': EventSkeleton<'im.message.receive_v1', { + 'im.message.receive_v1': { sender: { sender_id: Lark.UserIds sender_type?: string @@ -47,18 +47,51 @@ declare module '../event' { tenant_key: string }[] } - }> + } /** * Message read event. * @see https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/events/message_read */ - 'im.message.message_read_v1': EventSkeleton<'im.message.message_read_v1', { + 'im.message.message_read_v1': { reader: { reader_id: Lark.UserIds read_time: string tenant_key: string } message_id_list: string[] - }> + } + /** + * Message card callback event. + * @see https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-callback-communication + */ + 'card.action.trigger': { + operator: { + tenant_key: string + user_id: string + union_id: string + open_id: string + } + token: string + action: { + value: any + tag: string + timezone?: string + name?: string + form_value?: any + input_value?: string + option?: string + options?: string[] + checked?: boolean + } + host: string + /** 卡片分发类型,固定取值为 url_preview,表示链接预览卡片。仅链接预览卡片有此字段。 */ + delivery_type?: 'url_preview' + context: { + url?: string + preview_token?: string + open_message_id: string + open_chat_id: string + } + } } } diff --git a/adapters/lark/src/utils.ts b/adapters/lark/src/utils.ts index 412ce21b..03dead25 100644 --- a/adapters/lark/src/utils.ts +++ b/adapters/lark/src/utils.ts @@ -1,7 +1,7 @@ import crypto from 'crypto' import { Context, h, Session, trimSlash, Universal } from '@satorijs/core' import { FeishuBot, LarkBot } from './bot' -import { AllEvents, Events, GetImChatResponse, Lark, MessageContentType, MessageType } from './types' +import { EventPayload, Events, GetImChatResponse, Lark, MessageContentType, MessageType } from './types' export type Sender = | { @@ -22,7 +22,7 @@ export function adaptSender(sender: Sender, session: Session): Session { return session } -export async function adaptMessage(bot: FeishuBot, data: Events['im.message.receive_v1']['event'], session: Session, details = true): Promise { +export async function adaptMessage(bot: FeishuBot, data: Events['im.message.receive_v1'], session: Session, details = true): Promise { const json = JSON.parse(data.message.content) as MessageContentType const assetEndpoint = trimSlash(bot.config.selfUrl ?? bot.ctx.server.config.selfUrl) + bot.config.path + '/assets' const content: (string | h)[] = [] @@ -71,7 +71,7 @@ export async function adaptMessage(bot: FeishuBot, data: Events['im.message.rece return session } -export async function adaptSession(bot: FeishuBot, body: AllEvents) { +export async function adaptSession(bot: FeishuBot, body: EventPayload) { const session = bot.session() session.setInternal('lark', body) @@ -84,6 +84,35 @@ export async function adaptSession(bot: FeishuBot, body: A adaptSender(body.event.sender, session) await adaptMessage(bot, body.event, session) break + case 'card.action.trigger': + if (body.event.action.value?._satori_type === 'command') { + session.type = 'interaction/command' + let content = body.event.action.value.content + const args = [], options = Object.create(null) + for (const [key, value] of Object.entries(body.event.action.form_value ?? {})) { + if (+key * 0 === 0) { + args[+key] = value + } else { + options[key] = value + } + } + for (let i = 0; i < args.length; ++i) { + if (i in args) { + content += ` ${args[i]}` + } else { + content += ` ''` + } + } + for (const [key, value] of Object.entries(options)) { + content += ` --${key} ${value}` + } + session.content = content + session.messageId = body.event.context.open_message_id + session.channelId = body.event.context.open_chat_id + session.guildId = body.event.context.open_chat_id + session.userId = body.event.operator.open_id + } + break } return session } diff --git a/yakumo.yml b/yakumo.yml index c81c6cc0..96724ca8 100644 --- a/yakumo.yml +++ b/yakumo.yml @@ -1,4 +1,5 @@ -- name: yakumo +- id: zzgvxg + name: yakumo config: pipeline: build: @@ -6,5 +7,9 @@ - esbuild clean: - tsc --clean -- name: yakumo-esbuild -- name: yakumo-tsc +- id: 67eben + name: yakumo-esbuild +- id: fqmym8 + name: yakumo-tsc +- id: qrzdog + name: yakumo/run