From 1109cd5e9822afda1d22c539363b8c27429b197e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E6=A3=AE?= Date: Sat, 23 Dec 2023 14:32:02 +0800 Subject: [PATCH] =?UTF-8?q?style:=20=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/wechaty-file.ts | 26 ++-- examples/wechaty.ts | 14 +- .../src/dingtalk/sayer.ts | 8 +- .../src/dingtalk/schemas/contact.ts | 2 +- .../src/puppet-dingtalk.ts | 143 ++++++++---------- 5 files changed, 93 insertions(+), 100 deletions(-) diff --git a/examples/wechaty-file.ts b/examples/wechaty-file.ts index fb9ad5a..8c5a1e3 100644 --- a/examples/wechaty-file.ts +++ b/examples/wechaty-file.ts @@ -1,35 +1,33 @@ -import os from 'node:os' -import path from 'node:path'; import { unlinkSync } from 'node:fs'; - +import os from 'node:os'; +import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { PuppetDingTalk } from '@zhengxs/wechaty-puppet-dingtalk'; import { FileBox } from 'file-box'; +import { getAudioDurationInSeconds } from 'get-audio-duration'; import { WechatyBuilder } from 'wechaty'; -import { getAudioDurationInSeconds } from 'get-audio-duration' - const __dirname = path.dirname(fileURLToPath(import.meta.url)); const puppet = new PuppetDingTalk({ clientId: process.env.DINGTALK_CLIENT_ID, clientSecret: process.env.DINGTALK_CLIENT_SECRET, async getAudioDurationInSeconds(fileBox) { - const saveTo = path.resolve(os.tmpdir(), fileBox.name) + const saveTo = path.resolve(os.tmpdir(), fileBox.name); - await fileBox.toFile(saveTo) + await fileBox.toFile(saveTo); try { - return await getAudioDurationInSeconds(saveTo) + return await getAudioDurationInSeconds(saveTo); } finally { - unlinkSync(saveTo) + unlinkSync(saveTo); } }, -}) +}); const bot = WechatyBuilder.build({ - puppet + puppet, }); bot.on('message', async msg => { @@ -41,9 +39,9 @@ bot.on('message', async msg => { case MessageTypes.Video: case MessageTypes.Image: { const fileBox = await msg.toFileBox(); - const saveTo = path.resolve(__dirname, 'data', fileBox.name) + const saveTo = path.resolve(__dirname, 'data', fileBox.name); - await fileBox.toFile(saveTo) + await fileBox.toFile(saveTo); await msg.say(`File saved to: ${saveTo}`); break; @@ -51,7 +49,7 @@ bot.on('message', async msg => { case MessageTypes.Text: { if (msg.text() === 'ding') { - await msg.say('dong') + await msg.say('dong'); } await msg.say(FileBox.fromUrl('https://downsc.chinaz.net/Files/DownLoad/sound1/202311/y2300.mp3')); diff --git a/examples/wechaty.ts b/examples/wechaty.ts index d8cc2b4..038e58d 100644 --- a/examples/wechaty.ts +++ b/examples/wechaty.ts @@ -1,18 +1,16 @@ - import path from 'node:path'; import { PuppetDingTalk } from '@zhengxs/wechaty-puppet-dingtalk'; import { FileBox } from 'file-box'; import { WechatyBuilder } from 'wechaty'; - const puppet = new PuppetDingTalk({ clientId: process.env.DINGTALK_CLIENT_ID, clientSecret: process.env.DINGTALK_CLIENT_SECRET, -}) +}); const bot = WechatyBuilder.build({ - puppet + puppet, }); bot.on('message', async msg => { @@ -24,17 +22,17 @@ bot.on('message', async msg => { case MessageTypes.Video: case MessageTypes.Image: { const fileBox = await msg.toFileBox(); - const saveTo = path.resolve(__dirname, 'data', fileBox.name) + const saveTo = path.resolve(__dirname, 'data', fileBox.name); - await fileBox.toFile(saveTo) + await fileBox.toFile(saveTo); await msg.say(`File saved to: ${saveTo}`); break; } case MessageTypes.Text: { if (msg.text() === 'ding') { - await msg.say('dong') - break + await msg.say('dong'); + break; } await msg.say(FileBox.fromUrl('https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png')); diff --git a/packages/wechaty-puppet-dingtalk/src/dingtalk/sayer.ts b/packages/wechaty-puppet-dingtalk/src/dingtalk/sayer.ts index f99c5ee..72ac54a 100644 --- a/packages/wechaty-puppet-dingtalk/src/dingtalk/sayer.ts +++ b/packages/wechaty-puppet-dingtalk/src/dingtalk/sayer.ts @@ -1,4 +1,10 @@ -import { type MarkdownMessagePayload, type MessagePayload, MessageType, type Sayable, type TextMessagePayload } from './payloads'; +import { + type MarkdownMessagePayload, + type MessagePayload, + MessageType, + type Sayable, + type TextMessagePayload, +} from './payloads'; import { Sender } from './sender'; export class SayableSayer extends Sender { diff --git a/packages/wechaty-puppet-dingtalk/src/dingtalk/schemas/contact.ts b/packages/wechaty-puppet-dingtalk/src/dingtalk/schemas/contact.ts index 76ec766..ca1e2b4 100644 --- a/packages/wechaty-puppet-dingtalk/src/dingtalk/schemas/contact.ts +++ b/packages/wechaty-puppet-dingtalk/src/dingtalk/schemas/contact.ts @@ -34,7 +34,7 @@ export interface DTContactRawPayload { /** * 用户类型 */ - type: DTContactType + type: DTContactType; /** * Webhook 地址 diff --git a/packages/wechaty-puppet-dingtalk/src/puppet-dingtalk.ts b/packages/wechaty-puppet-dingtalk/src/puppet-dingtalk.ts index f66af30..606725d 100644 --- a/packages/wechaty-puppet-dingtalk/src/puppet-dingtalk.ts +++ b/packages/wechaty-puppet-dingtalk/src/puppet-dingtalk.ts @@ -1,31 +1,31 @@ import { extname } from 'node:path'; +import QuickLRU from '@alloc/quick-lru'; import { Dingtalk } from '@zhengxs/dingtalk'; import { AuthCredential } from '@zhengxs/dingtalk-auth'; import { type HubConnection, HubConnectionBuilder } from '@zhengxs/dingtalk-event-hubs'; import { toFile } from '@zhengxs/http'; import { FileBox, type FileBoxInterface } from 'file-box'; import { GError } from 'gerror'; -import Keyv from 'keyv' +import Keyv from 'keyv'; import * as PUPPET from 'wechaty-puppet'; import { log } from 'wechaty-puppet'; -import QuickLRU from '@alloc/quick-lru' import { - type DTMediaMessageRawPayload, - type Sayable, - SayableSayer, - DTContactType, - type DTSessionWebhookRawPayload, type DTContactRawPayload, dtContactToWechaty, - dtRoomMemberToWechaty, + DTContactType, + type DTMediaMessageRawPayload, type DTMessageRawPayload, dtMessageToWechaty, DTMessageType, + dtRoomMemberToWechaty, type DTRoomRawPayload, dtRoomToWechaty, + type DTSessionWebhookRawPayload, type MessagePayload, + type Sayable, + SayableSayer, } from './dingtalk'; const AttachmentExtRE = /\.(doc|docx|xls|xlsx|ppt|pptx|zip|pdf|rar)$/i; @@ -70,7 +70,7 @@ const ImageExtRE = /\.(jpg|jpeg|png|gif|bmp|webp)$/i; * }) * ``` */ -export type GetMediaDurationInSeconds = (fileBox: FileBoxInterface) => Promise +export type GetMediaDurationInSeconds = (fileBox: FileBoxInterface) => Promise; export interface PuppetDingTalkOptions extends PUPPET.PuppetOptions { /** @@ -94,19 +94,19 @@ export interface PuppetDingTalkOptions extends PUPPET.PuppetOptions { /** * 群数据缓存 */ - roomsStore?: Keyv + roomsStore?: Keyv; /** * 联系人数据缓存 */ - contactsStore?: Keyv + contactsStore?: Keyv; /** * 消息数据缓存 */ - messagesStore?: Keyv + messagesStore?: Keyv; /** * 会话 Webhook 数据缓存 */ - sessionWebhooksStore?: Keyv + sessionWebhooksStore?: Keyv; /** * 登出后是否清理缓存 * @@ -119,14 +119,14 @@ export interface PuppetDingTalkOptions extends PUPPET.PuppetOptions { * * @returns 以秒为单位的视频时长 */ - getVideoDurationInSeconds?: GetMediaDurationInSeconds + getVideoDurationInSeconds?: GetMediaDurationInSeconds; /** * 获取视频时长 * * @returns 以秒为单位的视频时长 */ - getAudioDurationInSeconds?: GetMediaDurationInSeconds + getAudioDurationInSeconds?: GetMediaDurationInSeconds; } export class PuppetDingTalk extends PUPPET.Puppet { @@ -134,15 +134,15 @@ export class PuppetDingTalk extends PUPPET.Puppet { protected _dkCredential: AuthCredential; protected _dkConnection?: HubConnection; - protected _roomsStore: Keyv - protected _contactsStore: Keyv - protected _messagesStore: Keyv - protected _sessionWebhooksStore: Keyv + protected _roomsStore: Keyv; + protected _contactsStore: Keyv; + protected _messagesStore: Keyv; + protected _sessionWebhooksStore: Keyv; - protected _clearCacheAfterLogout: boolean + protected _clearCacheAfterLogout: boolean; - protected _getVideoDurationInSeconds: GetMediaDurationInSeconds - protected _getAudioDurationInSeconds: GetMediaDurationInSeconds + protected _getVideoDurationInSeconds: GetMediaDurationInSeconds; + protected _getAudioDurationInSeconds: GetMediaDurationInSeconds; constructor(options: PuppetDingTalkOptions = {}) { const { @@ -176,14 +176,14 @@ export class PuppetDingTalk extends PUPPET.Puppet { this._dkCredential = credential; this._dkClient = new Dingtalk({ credential }); - this._getAudioDurationInSeconds = getAudioDurationInSeconds || this.unstable_defaultGetAudioDurationInSeconds - this._getVideoDurationInSeconds = getVideoDurationInSeconds || this.unstable_defaultGetVideoDurationInSeconds + this._getAudioDurationInSeconds = getAudioDurationInSeconds || this.unstable_defaultGetAudioDurationInSeconds; + this._getVideoDurationInSeconds = getVideoDurationInSeconds || this.unstable_defaultGetVideoDurationInSeconds; - this._contactsStore = contactsStore - this._roomsStore = roomsStore - this._messagesStore = messagesStore - this._sessionWebhooksStore = sessionWebhooksStore - this._clearCacheAfterLogout = clearCacheAfterLogout + this._contactsStore = contactsStore; + this._roomsStore = roomsStore; + this._messagesStore = messagesStore; + this._sessionWebhooksStore = sessionWebhooksStore; + this._clearCacheAfterLogout = clearCacheAfterLogout; } override async roomRawPayload(roomId: string): Promise { @@ -195,11 +195,11 @@ export class PuppetDingTalk extends PUPPET.Puppet { if (!rawPayload) { throw new GError({ code: 5, - message: `PuppetDingTalk: Room ${roomId} not found` + message: `PuppetDingTalk: Room ${roomId} not found`, }); } - return rawPayload + return rawPayload; } override async roomRawPayloadParser(rawPayload: DTRoomRawPayload): Promise { @@ -224,11 +224,11 @@ export class PuppetDingTalk extends PUPPET.Puppet { if (!rawPayload) { throw new GError({ code: 5, - message: `PuppetDingTalk: Contacts ${contactId} not found in Room(${roomId})` + message: `PuppetDingTalk: Contacts ${contactId} not found in Room(${roomId})`, }); } - return rawPayload + return rawPayload; } override async roomMemberRawPayloadParser(rawPayload: DTContactRawPayload): Promise { @@ -244,11 +244,11 @@ export class PuppetDingTalk extends PUPPET.Puppet { if (!rawPayload) { throw new GError({ code: 5, - message: `PuppetDingTalk: Contacts ${contactId} not found` + message: `PuppetDingTalk: Contacts ${contactId} not found`, }); } - return rawPayload + return rawPayload; } override async contactRawPayloadParser(rawPayload: DTContactRawPayload): Promise { @@ -264,11 +264,11 @@ export class PuppetDingTalk extends PUPPET.Puppet { if (!rawPayload) { throw new GError({ code: 5, - message: `PuppetDingTalk: Message ${messageId} not found` + message: `PuppetDingTalk: Message ${messageId} not found`, }); } - return rawPayload + return rawPayload; } override async messageRawPayloadParser(rawPayload: DTMessageRawPayload): Promise { @@ -332,10 +332,7 @@ export class PuppetDingTalk extends PUPPET.Puppet { } case AudioExtRE.test(ext): { - const [ - fileObj, - duration, - ] = await Promise.all([ + const [fileObj, duration] = await Promise.all([ files.create({ type: 'voice', media: await toFile(fileBox.toStream(), fileBox.name), @@ -351,7 +348,7 @@ export class PuppetDingTalk extends PUPPET.Puppet { }, }); - break + break; } case VideoExtRE.test(ext): { @@ -361,7 +358,7 @@ export class PuppetDingTalk extends PUPPET.Puppet { case ImageExtRE.test(ext): { // hack 强制获取私有的 remoteUrl 属性 // @ts-expect-error - const remoteUrl = fileBox.remoteUrl + const remoteUrl = fileBox.remoteUrl; if (remoteUrl) { await this.unstable__say(conversationId, { msgtype: 'image', @@ -369,13 +366,13 @@ export class PuppetDingTalk extends PUPPET.Puppet { picURL: remoteUrl, }, }); - break + break; } throw new GError({ code: 12, - message: '暂不支持以本地文件的方式上传图片' - }) + message: '暂不支持以本地文件的方式上传图片', + }); } default: @@ -420,14 +417,7 @@ export class PuppetDingTalk extends PUPPET.Puppet { connection.on('message', async event => { const payload: DTMessageRawPayload = JSON.parse(event.data); - const { - msgId, - senderId, - chatbotUserId, - conversationId, - sessionWebhook, - sessionWebhookExpiredTime, - } = payload + const { msgId, senderId, chatbotUserId, conversationId, sessionWebhook, sessionWebhookExpiredTime } = payload; const sessionWebhookPayload: DTSessionWebhookRawPayload = { msgId, @@ -436,7 +426,7 @@ export class PuppetDingTalk extends PUPPET.Puppet { conversationId, sessionWebhook, sessionWebhookExpiredTime, - } + }; const storeQueue = [ messagesStore.set(msgId, payload), @@ -464,7 +454,7 @@ export class PuppetDingTalk extends PUPPET.Puppet { // Note: wechaty 的消息发送不传递消息ID回来,只给联系人ID 和 群ID // 为了快速找到 sessionWebhook,以联系人ID 和 群 ID 各写一次 sessionWebhooksStore.set(senderId, sessionWebhookPayload, sessionWebhookExpiredTime), - ] + ]; if (payload.conversationType === '2') { const roomPayload: DTRoomRawPayload = { @@ -474,7 +464,7 @@ export class PuppetDingTalk extends PUPPET.Puppet { adminIdList: [], sessionWebhook, sessionWebhookExpiredTime, - } + }; if (payload.isAdmin) { roomPayload.adminIdList.push(senderId); @@ -483,12 +473,12 @@ export class PuppetDingTalk extends PUPPET.Puppet { storeQueue.push( roomsStore.set(conversationId, roomPayload), // Note: 理由同上 - sessionWebhooksStore.set(conversationId, sessionWebhookPayload, sessionWebhookExpiredTime) + sessionWebhooksStore.set(conversationId, sessionWebhookPayload, sessionWebhookExpiredTime), ); } // Note: 存储机器人用户信息后,再触发登录事件 - await Promise.all(storeQueue) + await Promise.all(storeQueue); // Note: 未登录,就触发登录事件 if (!this.isLoggedIn) { @@ -507,14 +497,14 @@ export class PuppetDingTalk extends PUPPET.Puppet { connection.on('connected', waitStable); connection.on('disconnected', () => { - if (!this.isLoggedIn) return + if (!this.isLoggedIn) return; // 清理缓存 if (this._clearCacheAfterLogout) { - this._contactsStore.clear() - this._roomsStore.clear() - this._messagesStore.clear() - this._sessionWebhooksStore.clear() + this._contactsStore.clear(); + this._roomsStore.clear(); + this._messagesStore.clear(); + this._sessionWebhooksStore.clear(); } this.logout(); @@ -538,20 +528,21 @@ export class PuppetDingTalk extends PUPPET.Puppet { } } - private async unstable__say(conversationId: string, sayable: Sayable, mentionIdList?: true | string[]): Promise { - const rawPayload = await this._sessionWebhooksStore.get(conversationId) + private async unstable__say( + conversationId: string, + sayable: Sayable, + mentionIdList?: true | string[], + ): Promise { + const rawPayload = await this._sessionWebhooksStore.get(conversationId); if (!rawPayload) { this.emit('error', { data: GError.stringify(`Webhook ${conversationId} does not exist or has expired`), - }) - return + }); + return; } - const sender = new SayableSayer( - rawPayload.sessionWebhook, - rawPayload.sessionWebhookExpiredTime, - ) + const sender = new SayableSayer(rawPayload.sessionWebhook, rawPayload.sessionWebhookExpiredTime); // @ts-expect-error await sender.say(sayable, mentionIdList); @@ -569,10 +560,10 @@ export class PuppetDingTalk extends PUPPET.Puppet { } protected unstable_defaultGetAudioDurationInSeconds: GetMediaDurationInSeconds = function (_fileBox) { - return Promise.resolve(1) - } + return Promise.resolve(1); + }; protected unstable_defaultGetVideoDurationInSeconds: GetMediaDurationInSeconds = function (_fileBox) { - return Promise.resolve(1) - } + return Promise.resolve(1); + }; }