From f32984dcd88a7a36272d2d2adafb327445b94d28 Mon Sep 17 00:00:00 2001 From: Shigma Date: Mon, 8 Jan 2024 23:12:19 +0800 Subject: [PATCH 1/4] fix(satori): fix incorrect impl about resource elements --- adapters/dingtalk/src/message.ts | 13 +++++++------ adapters/discord/src/bot.ts | 2 +- adapters/discord/src/message.ts | 10 +++++----- adapters/discord/src/utils.ts | 16 ++++++++-------- adapters/kook/src/message.ts | 13 +++++++------ adapters/kook/src/utils.ts | 2 +- adapters/lark/src/message.ts | 11 ++++++----- adapters/line/src/message.ts | 18 +++++++++--------- adapters/mail/src/message.ts | 10 ++++------ adapters/mail/src/utils.ts | 2 +- adapters/matrix/src/message.ts | 6 +++--- adapters/matrix/src/utils.ts | 4 ++-- adapters/qq/package.json | 2 +- adapters/qq/src/message.ts | 19 ++++++++----------- adapters/slack/src/message.ts | 4 ++-- adapters/telegram/src/bot.ts | 8 ++++---- adapters/telegram/src/message.ts | 6 +++--- adapters/telegram/src/utils.ts | 6 +++--- adapters/wechat-official/src/message.ts | 7 ++++--- adapters/wecom/src/message.ts | 7 ++++--- adapters/whatsapp/src/message.ts | 8 +++----- adapters/zulip/src/message.ts | 4 ++-- 22 files changed, 88 insertions(+), 90 deletions(-) diff --git a/adapters/dingtalk/src/message.ts b/adapters/dingtalk/src/message.ts index a2ab9adf..84bbc079 100644 --- a/adapters/dingtalk/src/message.ts +++ b/adapters/dingtalk/src/message.ts @@ -61,7 +61,7 @@ export class DingtalkMessageEncoder extends Message // https://open.dingtalk.com/document/orgapp/upload-media-files?spm=ding_open_doc.document.0.0.3b166172ERBuHw async uploadMedia(attrs: Dict) { - const { data, mime } = await this.bot.ctx.http.file(attrs.url, attrs) + const { data, mime } = await this.bot.ctx.http.file(attrs.src || attrs.url, attrs) const form = new FormData() // https://github.com/form-data/form-data/issues/468 const value = process.env.KOISHI_ENV === 'browser' @@ -89,20 +89,21 @@ export class DingtalkMessageEncoder extends Message const { type, attrs, children } = element if (type === 'text') { this.buffer += escape(attrs.content) - } else if (type === 'image' && attrs.url) { + } else if ((type === 'img' || type === 'image') && (attrs.src || attrs.url)) { + const src = attrs.src || attrs.url // await this.flush() // await this.sendMessage('sampleImageMsg', { - // photoURL: attrs.url + // photoURL: src, // }) - if (await this.bot.http.isPrivate(attrs.url)) { + if (await this.bot.http.isPrivate(src)) { const temp = this.bot.ctx.get('server.temp') if (!temp) { return this.bot.logger.warn('missing temporary file service, cannot send assets with private url') } - const entry: Entry | undefined = await temp.create(attrs.url) + const entry: Entry | undefined = await temp.create(src) this.buffer += `![${attrs.alt ?? ''}](${entry.url})` } else { - this.buffer += `![${attrs.alt ?? ''}](${attrs.url})` + this.buffer += `![${attrs.alt ?? ''}](${src})` } } else if (type === 'message') { await this.flush() diff --git a/adapters/discord/src/bot.ts b/adapters/discord/src/bot.ts index 0d983366..f5d0a498 100644 --- a/adapters/discord/src/bot.ts +++ b/adapters/discord/src/bot.ts @@ -71,7 +71,7 @@ export class DiscordBot extends Bot v.type === 'image') + const image = elements.find(v => v.type === 'img' || v.type === 'image') if (image) { throw new Error("You can't include embed object(s) while editing message.") } diff --git a/adapters/discord/src/message.ts b/adapters/discord/src/message.ts index 4522cc6b..969a670d 100644 --- a/adapters/discord/src/message.ts +++ b/adapters/discord/src/message.ts @@ -86,7 +86,7 @@ export class DiscordMessageEncoder extends MessageE } async sendEmbed(attrs: Dict, payload: Dict) { - const { filename, data, mime } = await this.bot.ctx.http.file(attrs.url, attrs) + const { filename, data, mime } = await this.bot.ctx.http.file(attrs.src || attrs.url, attrs) const form = new FormData() // https://github.com/form-data/form-data/issues/468 const value = process.env.KOISHI_ENV === 'browser' @@ -109,10 +109,10 @@ export class DiscordMessageEncoder extends MessageE if (addition.content) { await this.post(addition) } - return this.post({ ...addition, content: attrs.url }) + return this.post({ ...addition, content: attrs.src || attrs.url }) } - if (await this.bot.http.isPrivate(attrs.url)) { + if (await this.bot.http.isPrivate(attrs.src || attrs.url)) { return await this.sendEmbed(attrs, addition) } @@ -124,7 +124,7 @@ export class DiscordMessageEncoder extends MessageE } // auto mode - if (await this.checkMediaType(attrs.url, type)) { + if (await this.checkMediaType(attrs.src || attrs.url, type)) { return sendDirect() } else { return this.sendEmbed(attrs, addition) @@ -285,7 +285,7 @@ export class DiscordMessageEncoder extends MessageE } else { this.buffer += `<${attrs.animated ? 'a' : ''}:${attrs.name}:${attrs.id}>` } - } else if ((type === 'image' || type === 'video') && attrs.url) { + } else if ((type === 'img' || type === 'image' || type === 'video') && (attrs.src || attrs.url)) { if (this.mode === 'figure') { this.figure = element } else { diff --git a/adapters/discord/src/utils.ts b/adapters/discord/src/utils.ts index 5142291b..cb7f10d0 100644 --- a/adapters/discord/src/utils.ts +++ b/adapters/discord/src/utils.ts @@ -92,26 +92,26 @@ export async function decodeMessage( if (!/\s$/.test(message.content)) message.content += ' ' message.content += data.attachments.map(v => { if (v.height && v.width && v.content_type?.startsWith('image/')) { - return h('image', { - url: v.url, + return h('img', { + src: v.url, proxy_url: v.proxy_url, file: v.filename, }) } else if (v.height && v.width && v.content_type?.startsWith('video/')) { return h('video', { - url: v.url, + src: v.url, proxy_url: v.proxy_url, file: v.filename, }) } else if (v.content_type?.startsWith('audio/')) { return h('record', { - url: v.url, + src: v.url, proxy_url: v.proxy_url, file: v.filename, }) } else { return h('file', { - url: v.url, + src: v.url, proxy_url: v.proxy_url, file: v.filename, }) @@ -122,13 +122,13 @@ export async function decodeMessage( // not using embed types // https://discord.com/developers/docs/resources/channel#embed-object-embed-types if (embed.image) { - message.content += h('image', { url: embed.image.url, proxy_url: embed.image.proxy_url }) + message.content += h('img', { src: embed.image.url, proxy_url: embed.image.proxy_url }) } if (embed.thumbnail) { - message.content += h('image', { url: embed.thumbnail.url, proxy_url: embed.thumbnail.proxy_url }) + message.content += h('img', { src: embed.thumbnail.url, proxy_url: embed.thumbnail.proxy_url }) } if (embed.video) { - message.content += h('video', { url: embed.video.url, proxy_url: embed.video.proxy_url }) + message.content += h('video', { src: embed.video.url, proxy_url: embed.video.proxy_url }) } } message.elements = h.parse(message.content) diff --git a/adapters/kook/src/message.ts b/adapters/kook/src/message.ts index 7449ec3f..e0b1fad9 100644 --- a/adapters/kook/src/message.ts +++ b/adapters/kook/src/message.ts @@ -48,16 +48,17 @@ export class KookMessageEncoder extends MessageEnco } private async transformUrl({ type, attrs }: h) { - if (await this.bot.http.isPrivate(attrs.url)) { + const src = attrs.src || attrs.url + if (await this.bot.http.isPrivate(src)) { const payload = new FormData() - const result = await this.bot.ctx.http.file(attrs.url, attrs) + const result = await this.bot.ctx.http.file(src, attrs) payload.append('file', Buffer.from(result.data), { filename: attrs.file || result.filename, }) const { url } = await this.bot.request('POST', '/asset/create', payload, payload.getHeaders()) return url - } else if (!attrs.url.includes('kookapp.cn')) { - const res = await this.bot.ctx.http.get(attrs.url, { + } else if (!src.includes('kookapp.cn')) { + const res = await this.bot.ctx.http.get(src, { headers: { accept: type + '/*' }, responseType: 'stream', timeout: +attrs.timeout || undefined, @@ -69,7 +70,7 @@ export class KookMessageEncoder extends MessageEnco const { url } = await this.bot.request('POST', '/asset/create', payload, payload.getHeaders()) return url } else { - return attrs.url + return src } } @@ -163,7 +164,7 @@ export class KookMessageEncoder extends MessageEnco src: await this.transformUrl(element), title: attrs.title, }) - } else if (type === 'image' || type === 'kook:image') { + } else if (type === 'img' || type === 'image' || type === 'kook:image') { this.flushText() this.cardBuffer.modules.push({ type: 'container', diff --git a/adapters/kook/src/utils.ts b/adapters/kook/src/utils.ts index f533f2ed..4804f376 100644 --- a/adapters/kook/src/utils.ts +++ b/adapters/kook/src/utils.ts @@ -64,7 +64,7 @@ function adaptMessageMeta( .replace(/#channel:(\d+);/, (_, id) => h.sharp(id).toString()) message.elements = h.parse(message.content) } else if (base.type === Kook.Type.image) { - const element = h('image', { url: base.content, file: data.attachments?.name }) + const element = h('img', { src: base.content, file: data.attachments?.name }) message.elements = [element] message.content = element.toString() } else if (base.type === Kook.Type.card) { diff --git a/adapters/lark/src/message.ts b/adapters/lark/src/message.ts index 284bad27..4d749678 100644 --- a/adapters/lark/src/message.ts +++ b/adapters/lark/src/message.ts @@ -75,10 +75,10 @@ export class LarkMessageEncoder extends MessageEnco this.richText = undefined } - async sendFile(type: 'image' | 'video' | 'audio' | 'file', url: string): Promise { + async sendFile(type: 'img' | 'image' | 'video' | 'audio' | 'file', url: string): Promise { const payload = new FormData() - const assetKey = type === 'image' ? 'image' : 'file' + const assetKey = type === 'img' || type === 'image' ? 'image' : 'file' const [schema, file] = url.split('://') const filename = schema === 'base64' ? 'unknown' : new URL(url).pathname.split('/').pop() if (schema === 'file') { @@ -90,7 +90,7 @@ export class LarkMessageEncoder extends MessageEnco payload.append(assetKey, resp) } - if (type === 'image') { + if (type === 'img' || type === 'image') { payload.append('image_type', 'message') const { data } = await this.bot.internal.uploadImage(payload) return { @@ -162,13 +162,14 @@ export class LarkMessageEncoder extends MessageEnco await this.flush() this.quote = attrs.id break + case 'img': case 'image': case 'video': case 'audio': case 'file': - if (attrs.url) { + if (attrs.src || attrs.url) { await this.flush() - this.addition = await this.sendFile(type, attrs.url) + this.addition = await this.sendFile(type, attrs.src || attrs.url) } break case 'figure': // FIXME: treat as message element for now diff --git a/adapters/line/src/message.ts b/adapters/line/src/message.ts index 8e7cc442..dce5d286 100644 --- a/adapters/line/src/message.ts +++ b/adapters/line/src/message.ts @@ -93,28 +93,28 @@ export class LineMessageEncoder extends MessageEnco if (!this.buffer.endsWith('\n')) this.buffer += '\n' await this.render(children) if (!this.buffer.endsWith('\n')) this.buffer += '\n' - } else if (type === 'image' && attrs.url) { + } else if ((type === 'img' || type === 'image') && (attrs.src || attrs.url)) { await this.insertBlock() this.blocks.push({ type: 'image', - originalContentUrl: attrs.url, - previewImageUrl: attrs.url, + originalContentUrl: attrs.src || attrs.url, + previewImageUrl: attrs.src || attrs.url, }) - } else if (type === 'video' && attrs.url) { + } else if (type === 'video' && (attrs.src || attrs.url)) { await this.insertBlock() this.blocks.push({ type: 'video', - originalContentUrl: attrs.url, - previewImageUrl: attrs.url, + originalContentUrl: attrs.src || attrs.url, + previewImageUrl: attrs.src || attrs.url, }) - } else if (type === 'audio' && attrs.url) { + } else if (type === 'audio' && (attrs.src || attrs.url)) { await this.insertBlock() this.blocks.push({ type: 'audio', - originalContentUrl: attrs.url, + originalContentUrl: attrs.src || attrs.url, duration: 1145, }) - } else if (type === 'face' && attrs.id) { + } else if (type === 'face') { if (attrs.id.startsWith('s')) { // https://developers.line.biz/en/reference/messaging-api/#sticker-message await this.insertBlock() diff --git a/adapters/mail/src/message.ts b/adapters/mail/src/message.ts index c0b96471..0ffe2c40 100644 --- a/adapters/mail/src/message.ts +++ b/adapters/mail/src/message.ts @@ -55,13 +55,11 @@ export class MailMessageEncoder extends MessageEnco } } else if (type === 'sharp' && attrs.id) { this.buffer += ` #${attrs.id} ` - } else if (['image', 'audio', 'video', 'file'].includes(type) && attrs.url) { - let url: string - if (attrs.url.match(/^https?:/)) { - url = attrs.url - } else { + } else if (['image', 'audio', 'video', 'file'].includes(type) && (attrs.src || attrs.url)) { + let url: string = attrs.src || attrs.url + if (!url.match(/^https?:/)) { const cid = randomId() - const { filename, mime, data } = await this.bot.ctx.http.file(attrs.url) + const { filename, mime, data } = await this.bot.ctx.http.file(url) this.attachments.push({ cid, filename, diff --git a/adapters/mail/src/utils.ts b/adapters/mail/src/utils.ts index 5c55ca75..86d69b02 100644 --- a/adapters/mail/src/utils.ts +++ b/adapters/mail/src/utils.ts @@ -84,7 +84,7 @@ export async function adaptMessage( break } if (src.match(/^(data|https?):/)) { - content += `` + content += `` break } break diff --git a/adapters/matrix/src/message.ts b/adapters/matrix/src/message.ts index 9a7818e2..6079219a 100644 --- a/adapters/matrix/src/message.ts +++ b/adapters/matrix/src/message.ts @@ -81,10 +81,10 @@ export class MatrixMessageEncoder extends MessageEn } } else if (type === 'sharp' && attrs.id) { this.buffer += ` #${attrs.id} ` - } else if ((type === 'image' || type === 'video' || type === 'record' || type === 'file') && attrs.url) { + } else if ((type === 'image' || type === 'img' || type === 'video' || type === 'record' || type === 'file') && (attrs.src || attrs.url)) { await this.flush() - const matrixType = type === 'record' ? 'audio' : type - await this.sendMedia(attrs.url, matrixType) + const matrixType = type === 'record' ? 'audio' : type === 'img' ? 'image' : type + await this.sendMedia(attrs.src || attrs.url, matrixType) } else if (type === 'quote') { this.reply = await this.bot.getMessage(this.channelId, attrs.id) } else if (type === 'message') { diff --git a/adapters/matrix/src/utils.ts b/adapters/matrix/src/utils.ts index 31f3dde8..aa5ac2ad 100644 --- a/adapters/matrix/src/utils.ts +++ b/adapters/matrix/src/utils.ts @@ -32,9 +32,9 @@ export async function adaptMessage( case 'm.file': case 'm.audio': case 'm.video': { - const url = bot.internal.getAssetUrl((content as any).url) + const src = bot.internal.getAssetUrl((content as any).url) const type = content.msgtype.substring(2) - message.content = segment(type === 'audio' ? 'record' : type, { url }).toString() + message.content = segment(type === 'audio' ? 'record' : type === 'image' ? 'img' : type, { src }).toString() break } default: diff --git a/adapters/qq/package.json b/adapters/qq/package.json index 4069fd18..3c9d3948 100644 --- a/adapters/qq/package.json +++ b/adapters/qq/package.json @@ -1,7 +1,7 @@ { "name": "@satorijs/adapter-qq", "description": "QQ Adapter for Satorijs", - "version": "4.2.5", + "version": "4.2.7", "main": "lib/index.js", "typings": "lib/index.d.ts", "files": [ diff --git a/adapters/qq/src/message.ts b/adapters/qq/src/message.ts index f921b2d8..ec33a90c 100644 --- a/adapters/qq/src/message.ts +++ b/adapters/qq/src/message.ts @@ -17,7 +17,6 @@ export class QQGuildMessageEncoder extends MessageE private passiveId: string reference: string private retry = false - private resource: Dict // 先文后图 async flush() { if (!this.content.trim().length && !this.file && !this.fileUrl) { @@ -110,7 +109,6 @@ export class QQGuildMessageEncoder extends MessageE this.file = null this.filename = null this.fileUrl = null - this.resource = null this.retry = false } @@ -134,11 +132,10 @@ export class QQGuildMessageEncoder extends MessageE } async resolveFile(attrs: Dict, download = false) { - if (attrs) this.resource = attrs - if (!download && !await this.bot.ctx.http.isPrivate(this.resource.url)) { - return this.fileUrl = this.resource.url + if (!download && !await this.bot.ctx.http.isPrivate(attrs.src || attrs.url)) { + return this.fileUrl = attrs.src || attrs.url } - const { data, filename } = await this.bot.ctx.http.file(this.resource.url, this.resource) + const { data, filename } = await this.bot.ctx.http.file(attrs.src || attrs.url, attrs) this.file = Buffer.from(data) this.filename = filename this.fileUrl = null @@ -169,7 +166,7 @@ export class QQGuildMessageEncoder extends MessageE await this.flush() } else if (type === 'passive') { this.passiveId = attrs.id - } else if (type === 'image' && attrs.url) { + } else if ((type === 'img' || type === 'image') && (attrs.src || attrs.url)) { await this.flush() await this.resolveFile(attrs) await this.flush() @@ -287,7 +284,7 @@ export class QQMessageEncoder extends MessageEncode } async sendFile(type: string, attrs: Dict) { - let url = attrs.url, entry: Entry | undefined + let url = attrs.src || attrs.url, entry: Entry | undefined if (await this.bot.ctx.http.isPrivate(url)) { const temp = this.bot.ctx.get('server.temp') if (!temp) { @@ -298,7 +295,7 @@ export class QQMessageEncoder extends MessageEncode } await this.flush() let file_type = 0 - if (type === 'image') file_type = 1 + if (type === 'img' || type === 'image') file_type = 1 else if (type === 'video') file_type = 2 else return const data: QQ.Message.File.Request = { @@ -371,11 +368,11 @@ export class QQMessageEncoder extends MessageEncode } else if (type === 'passive') { this.passiveId = attrs.id this.passiveSeq = Number(attrs.seq) - } else if (type === 'image' && attrs.url) { + } else if ((type === 'img' || type === 'image') && (attrs.src || attrs.url)) { await this.flush() const data = await this.sendFile(type, attrs) if (data) this.attachedFile = data - } else if (type === 'video' && attrs.url) { + } else if (type === 'video' && (attrs.src || attrs.url)) { await this.flush() const data = await this.sendFile(type, attrs) if (data) this.attachedFile = data diff --git a/adapters/slack/src/message.ts b/adapters/slack/src/message.ts index 6238f67d..9c988311 100644 --- a/adapters/slack/src/message.ts +++ b/adapters/slack/src/message.ts @@ -47,7 +47,7 @@ export class SlackMessageEncoder extends MessageEnc async sendAsset(element: h) { if (this.buffer.length) await this.flush() const { attrs } = element - const { filename, data, mime } = await this.bot.ctx.http.file(attrs.url, attrs) + const { filename, data, mime } = await this.bot.ctx.http.file(attrs.src || attrs.url, attrs) const form = new FormData() // https://github.com/form-data/form-data/issues/468 const value = process.env.KOISHI_ENV === 'browser' @@ -72,7 +72,7 @@ export class SlackMessageEncoder extends MessageEnc const { type, attrs, children } = element if (type === 'text') { this.buffer += escape(attrs.content) - } else if (type === 'image' && attrs.url) { + } else if ((type === 'img' || type === 'image') && (attrs.src || attrs.url)) { await this.sendAsset(element) } else if (type === 'sharp' && attrs.id) { this.buffer += `<#${attrs.id}>` diff --git a/adapters/telegram/src/bot.ts b/adapters/telegram/src/bot.ts index 3ee414e2..977ede8b 100644 --- a/adapters/telegram/src/bot.ts +++ b/adapters/telegram/src/bot.ts @@ -161,14 +161,14 @@ export class TelegramBot { let method: AssetMethod - const { filename, data, mime } = await bot.ctx.http.file(element.attrs.url, element.attrs) - if (element.type === 'image') { + const { filename, data, mime } = await bot.ctx.http.file(element.attrs.src || element.attrs.url, element.attrs) + if (element.type === 'img' || element.type === 'image') { method = mime === 'image/gif' ? 'sendAnimation' : 'sendPhoto' } else if (element.type === 'file') { method = 'sendDocument' @@ -145,7 +145,7 @@ export class TelegramMessageEncoder extends Message if (attrs.id) { this.payload.caption += `@${attrs.name || attrs.id}` } - } else if (['image', 'audio', 'video', 'file'].includes(type)) { + } else if (['img', 'image', 'audio', 'video', 'file'].includes(type)) { if (this.mode === 'default') { await this.flush() } diff --git a/adapters/telegram/src/utils.ts b/adapters/telegram/src/utils.ts index 25aa277c..4c1d26ec 100644 --- a/adapters/telegram/src/utils.ts +++ b/adapters/telegram/src/utils.ts @@ -171,7 +171,7 @@ export async function decodeMessage( segments.push(h('location', { lat: data.location.latitude, lon: data.location.longitude })) } else if (data.photo) { const photo = data.photo.sort((s1, s2) => s2.file_size - s1.file_size)[0] - segments.push(h('image', await bot.$getFileFromId(photo.file_id))) + segments.push(h('img', await bot.$getFileFromId(photo.file_id))) } else if (data.sticker) { // TODO: Convert tgs to gif // https://github.com/ed-asriyan/tgs-to-gif @@ -181,7 +181,7 @@ export async function decodeMessage( if (file.file_path.endsWith('.tgs')) { throw new Error('tgs is not supported now') } - segments.push(h('image', await bot.$getFileFromPath(file.file_path))) + segments.push(h('img', await bot.$getFileFromPath(file.file_path))) } catch (e) { bot.logger.warn('get file error', e) segments.push(h('text', { content: `[${data.sticker.set_name || 'sticker'} ${data.sticker.emoji || ''}]` })) @@ -189,7 +189,7 @@ export async function decodeMessage( } else if (data.voice) { await addResource('audio', data.voice) } else if (data.animation) { - await addResource('image', data.animation) + await addResource('img', data.animation) } else if (data.video) { await addResource('video', data.video) } else if (data.document) { diff --git a/adapters/wechat-official/src/message.ts b/adapters/wechat-official/src/message.ts index cd70a3f7..3daa4f29 100644 --- a/adapters/wechat-official/src/message.ts +++ b/adapters/wechat-official/src/message.ts @@ -61,9 +61,10 @@ export class WechatOfficialMessageEncoder extends M } async flushMedia(element: h) { - if (!['audio', 'video', 'image'].includes(element.type)) return + if (!['audio', 'video', 'image', 'img'].includes(element.type)) return let type = element.type if (type === 'audio') type = 'voice' + if (type === 'img') type = 'image' const [media] = await this.uploadMedia(element) if (this.options.session.wechatOfficialResolve && !this.bot.config.customerService) { @@ -109,7 +110,7 @@ export class WechatOfficialMessageEncoder extends M const uploadType = type === 'audio' ? 'voice' : type const form = new FormData() - const { filename, data, mime } = await this.bot.ctx.http.file(attrs.url, attrs) + const { filename, data, mime } = await this.bot.ctx.http.file(attrs.src || attrs.url, attrs) const value = process.env.KOISHI_ENV === 'browser' ? new Blob([data], { type: mime }) : Buffer.from(data) @@ -144,7 +145,7 @@ export class WechatOfficialMessageEncoder extends M if (!this.buffer.endsWith('\n')) this.buffer += '\n' await this.render(children) if (!this.buffer.endsWith('\n')) this.buffer += '\n' - } else if (type === 'image' || type === 'audio' || type === 'video') { + } else if (type === 'img' || type === 'image' || type === 'audio' || type === 'video') { await this.flushMedia(element) } else if (type === 'message') { await this.flush() diff --git a/adapters/wecom/src/message.ts b/adapters/wecom/src/message.ts index e8843f9c..0f1074ef 100644 --- a/adapters/wecom/src/message.ts +++ b/adapters/wecom/src/message.ts @@ -39,9 +39,10 @@ export class WecomMessageEncoder extends MessageEnc } async flushMedia(element: h) { - if (!['audio', 'video', 'image', 'file'].includes(element.type)) return + if (!['audio', 'video', 'image', 'file', 'img'].includes(element.type)) return let type = element.type if (type === 'audio') type = 'voice' + if (type === 'img') type = 'image' const [media] = await this.uploadMedia(element) await this.sendByCustom({ @@ -68,7 +69,7 @@ export class WecomMessageEncoder extends MessageEnc const uploadType = type === 'audio' ? 'voice' : type const form = new FormData() - const { filename, data, mime } = await this.bot.ctx.http.file(attrs.url, attrs) + const { filename, data, mime } = await this.bot.ctx.http.file(attrs.src || attrs.url, attrs) const value = process.env.KOISHI_ENV === 'browser' ? new Blob([data], { type: mime }) : Buffer.from(data) @@ -104,7 +105,7 @@ export class WecomMessageEncoder extends MessageEnc if (!this.buffer.endsWith('\n')) this.buffer += '\n' await this.render(children) if (!this.buffer.endsWith('\n')) this.buffer += '\n' - } else if (type === 'image' || type === 'audio' || type === 'video' || type === 'file') { + } else if (type === 'img' || type === 'image' || type === 'audio' || type === 'video' || type === 'file') { await this.flushMedia(element) } else if (type === 'a' && attrs.href) { await this.render(children) diff --git a/adapters/whatsapp/src/message.ts b/adapters/whatsapp/src/message.ts index 89b73bef..76b6f084 100644 --- a/adapters/whatsapp/src/message.ts +++ b/adapters/whatsapp/src/message.ts @@ -83,7 +83,7 @@ export class WhatsAppMessageEncoder extends Message // https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#upload-media async uploadMedia(attrs: Dict) { - const { filename, data, mime } = await this.bot.ctx.http.file(attrs.url, attrs) + const { filename, data, mime } = await this.bot.ctx.http.file(attrs.src || attrs.url, attrs) if (!SUPPORTED_MEDIA.includes(mime)) { this.bot.ctx.logger('whatsapp').warn(`Unsupported media type: ${mime}`) @@ -114,13 +114,11 @@ export class WhatsAppMessageEncoder extends Message const { type, attrs, children } = element if (type === 'text') { this.buffer += attrs.content - } else if (( - type === 'image' || type === 'audio' || type === 'video' - ) && attrs.url) { + } else if ((type === 'image' || type === 'img' || type === 'audio' || type === 'video') && (attrs.src || attrs.url)) { // https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#supported-media-types const id = await this.uploadMedia(attrs) if (!id) return - await this.sendMessage(type, { id }) + await this.sendMessage(type === 'img' ? 'image' : type, { id }) } else if (type === 'file') { const id = await this.uploadMedia(attrs) if (!id) return diff --git a/adapters/zulip/src/message.ts b/adapters/zulip/src/message.ts index c0bffff5..65299964 100644 --- a/adapters/zulip/src/message.ts +++ b/adapters/zulip/src/message.ts @@ -42,7 +42,7 @@ export class ZulipMessageEncoder extends MessageEnc async uploadMedia(element: h) { const { attrs } = element - const { filename, data, mime } = await this.bot.ctx.http.file(attrs.url, attrs) + const { filename, data, mime } = await this.bot.ctx.http.file(attrs.src || attrs.url, attrs) const form = new FormData() // https://github.com/form-data/form-data/issues/468 const value = process.env.KOISHI_ENV === 'browser' @@ -82,7 +82,7 @@ export class ZulipMessageEncoder extends MessageEnc this.buffer += `[` await this.render(children) this.buffer += `](${encodeURI(attrs.href)})` - } else if (['audio', 'video', 'file', 'image'].includes(type)) { + } else if (['audio', 'video', 'file', 'image', 'img'].includes(type)) { const [uri, filename] = await this.uploadMedia(element) this.buffer += `[${filename}](${encodeURI(uri)})\n` } else if (type === 'quote') { From cf0ea1197523a659ec91dc4baee122ebbfa0c3ed Mon Sep 17 00:00:00 2001 From: Shigma Date: Mon, 8 Jan 2024 23:23:03 +0800 Subject: [PATCH 2/4] fix(satori): replace url with src in h shorthands --- packages/element/src/index.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/element/src/index.ts b/packages/element/src/index.ts index e2e02a7f..7c1f1289 100644 --- a/packages/element/src/index.ts +++ b/packages/element/src/index.ts @@ -469,20 +469,20 @@ namespace Element { export let warn: (message: string) => void = () => {} function createAssetFactory(type: string): Factory<[data: string] | [data: Buffer | ArrayBuffer, type: string]> { - return (url, ...args) => { + return (src, ...args) => { let prefix = 'base64://' if (typeof args[0] === 'string') { prefix = `data:${args.shift()};base64,` } - if (is('Buffer', url)) { - url = prefix + url.toString('base64') - } else if (is('ArrayBuffer', url)) { - url = prefix + arrayBufferToBase64(url) + if (is('Buffer', src)) { + src = prefix + src.toString('base64') + } else if (is('ArrayBuffer', src)) { + src = prefix + arrayBufferToBase64(src) } - if (url.startsWith('base64://')) { + if (src.startsWith('base64://')) { warn(`protocol "base64:" is deprecated and will be removed in the future, please use "data:" instead`) } - return Element(type, { ...args[0] as {}, url }) + return Element(type, { ...args[0] as {}, src }) } } @@ -490,7 +490,8 @@ namespace Element { export const at = createFactory<[id: any]>('at', 'id') export const sharp = createFactory<[id: any]>('sharp', 'id') export const quote = createFactory<[id: any]>('quote', 'id') - export const image = createAssetFactory('image') + export const image = createAssetFactory('img') + export const img = createAssetFactory('img') export const video = createAssetFactory('video') export const audio = createAssetFactory('audio') export const file = createAssetFactory('file') From af499b65da2622858a0832e333eb77bef0c9d844 Mon Sep 17 00:00:00 2001 From: Shigma Date: Mon, 8 Jan 2024 23:43:43 +0800 Subject: [PATCH 3/4] feat(kook): support attrs.poster --- adapters/kook/src/message.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/adapters/kook/src/message.ts b/adapters/kook/src/message.ts index e0b1fad9..1fc191a3 100644 --- a/adapters/kook/src/message.ts +++ b/adapters/kook/src/message.ts @@ -163,6 +163,7 @@ export class KookMessageEncoder extends MessageEnco type: (type.startsWith('kook:') ? type.slice(5) : type) as never, src: await this.transformUrl(element), title: attrs.title, + cover: attrs.poster, }) } else if (type === 'img' || type === 'image' || type === 'kook:image') { this.flushText() From 49d3887144f990b5afcc0911c2556cfcac3d6f1f Mon Sep 17 00:00:00 2001 From: Shigma Date: Mon, 8 Jan 2024 23:44:00 +0800 Subject: [PATCH 4/4] feat(line): support attrs.poster and attrs.duration --- adapters/line/src/message.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adapters/line/src/message.ts b/adapters/line/src/message.ts index dce5d286..92b18f70 100644 --- a/adapters/line/src/message.ts +++ b/adapters/line/src/message.ts @@ -98,21 +98,21 @@ export class LineMessageEncoder extends MessageEnco this.blocks.push({ type: 'image', originalContentUrl: attrs.src || attrs.url, - previewImageUrl: attrs.src || attrs.url, + previewImageUrl: attrs.poster, }) } else if (type === 'video' && (attrs.src || attrs.url)) { await this.insertBlock() this.blocks.push({ type: 'video', originalContentUrl: attrs.src || attrs.url, - previewImageUrl: attrs.src || attrs.url, + previewImageUrl: attrs.poster, }) } else if (type === 'audio' && (attrs.src || attrs.url)) { await this.insertBlock() this.blocks.push({ type: 'audio', originalContentUrl: attrs.src || attrs.url, - duration: 1145, + duration: attrs.duration, }) } else if (type === 'face') { if (attrs.id.startsWith('s')) {