diff --git a/adapters/dingtalk/src/message.ts b/adapters/dingtalk/src/message.ts index 6d940b09..dd90ec87 100644 --- a/adapters/dingtalk/src/message.ts +++ b/adapters/dingtalk/src/message.ts @@ -1,6 +1,5 @@ import { Context, Dict, h, MessageEncoder } from '@satorijs/satori' import { DingtalkBot } from './bot' -import FormData from 'form-data' import { SendMessageData } from './types' import { Entry } from '@satorijs/server-temp' @@ -63,10 +62,7 @@ export class DingtalkMessageEncoder extends Message async uploadMedia(attrs: Dict) { 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' - ? new Blob([data], { type: mime }) - : Buffer.from(data) + const value = new Blob([data], { type: mime }) let type: string if (mime.startsWith('image/') || mime.startsWith('video/')) { type = mime.split('/')[0] @@ -77,9 +73,7 @@ export class DingtalkMessageEncoder extends Message } form.append('type', type) form.append('media', value) - const { media_id } = await this.bot.oldHttp.post('/media/upload', form, { - headers: form.getHeaders(), - }) + const { media_id } = await this.bot.oldHttp.post('/media/upload', form) return media_id } diff --git a/adapters/discord/src/message.ts b/adapters/discord/src/message.ts index bf751812..c66a1d6c 100644 --- a/adapters/discord/src/message.ts +++ b/adapters/discord/src/message.ts @@ -1,5 +1,4 @@ import { Context, Dict, h, MessageEncoder, Quester, Schema, Universal } from '@satorijs/satori' -import FormData from 'form-data' import { DiscordBot } from './bot' import { ActionRow, Button, ButtonStyles, Channel, ComponentType, Message } from './types' import { decodeMessage, sanitize } from './utils' @@ -88,13 +87,10 @@ export class DiscordMessageEncoder extends MessageE async sendEmbed(attrs: Dict, payload: Dict) { 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' - ? new Blob([data], { type: mime }) - : Buffer.from(data) + const value = new Blob([data], { type: mime }) form.append('file', value, attrs.file || filename) form.append('payload_json', JSON.stringify(payload)) - return this.post(form, form.getHeaders()) + return this.post(form) } async sendAsset(type: string, attrs: Dict, addition: Dict) { diff --git a/adapters/kook/src/bot.ts b/adapters/kook/src/bot.ts index 177bb43d..48806551 100644 --- a/adapters/kook/src/bot.ts +++ b/adapters/kook/src/bot.ts @@ -1,7 +1,6 @@ import { Bot, Context, Fragment, h, Quester, Schema, Universal } from '@satorijs/satori' import { adaptGroup, adaptMessage, adaptUser, decodeGuildMember, decodeRole, encodeRole } from './utils' import * as Kook from './types' -import FormData from 'form-data' import { WsClient } from './ws' import { HttpServer } from './http' import { isDirectChannel, KookMessageEncoder } from './message' @@ -34,7 +33,6 @@ export class KookBot 30 @@ -54,22 +52,18 @@ export class KookMessageEncoder extends MessageEnco if (await this.bot.http.isLocal(src)) { const payload = new FormData() 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()) + payload.append('file', new Blob([result.data], { type: result.mime }), attrs.file || result.filename) + const { url } = await this.bot.request('POST', '/asset/create', payload) return url } else if (!src.includes('kookapp.cn')) { - const res = await this.bot.ctx.http.get(src, { + const { data, headers } = await this.bot.ctx.http('GET', src, { headers: { accept: type + '/*' }, - responseType: 'stream', + responseType: 'arraybuffer', timeout: +attrs.timeout || undefined, }) const payload = new FormData() - payload.append('file', res, { - filename: 'file', - }) - const { url } = await this.bot.request('POST', '/asset/create', payload, payload.getHeaders()) + payload.append('file', new Blob([data], { type: headers.get('Content-Type') }), 'file') + const { url } = await this.bot.request('POST', '/asset/create', payload) return url } else { return src diff --git a/adapters/lark/src/message.ts b/adapters/lark/src/message.ts index 4d749678..7a0e49aa 100644 --- a/adapters/lark/src/message.ts +++ b/adapters/lark/src/message.ts @@ -1,9 +1,4 @@ -import { createReadStream } from 'fs' -import internal from 'stream' - import { Context, h, MessageEncoder, Quester } from '@satorijs/satori' -import FormData from 'form-data' - import { LarkBot } from './bot' import { BaseResponse, Message, MessageContent, MessageType } from './types' import { extractIdType } from './utils' @@ -79,16 +74,8 @@ export class LarkMessageEncoder extends MessageEnco const payload = new FormData() 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') { - payload.append(assetKey, createReadStream(file)) - } else if (schema === 'base64') { - payload.append(assetKey, Buffer.from(file, 'base64')) - } else { - const resp = await this.bot.assetsQuester.get(url, { responseType: 'stream' }) - payload.append(assetKey, resp) - } + const { filename, mime, data } = await this.bot.assetsQuester.file(url) + payload.append(assetKey, new Blob([data], { type: mime }), filename) if (type === 'img' || type === 'image') { payload.append('image_type', 'message') diff --git a/adapters/lark/src/types/internal.ts b/adapters/lark/src/types/internal.ts index ee9af685..69fbcd77 100644 --- a/adapters/lark/src/types/internal.ts +++ b/adapters/lark/src/types/internal.ts @@ -1,4 +1,3 @@ -import FormData from 'form-data' import { Dict, makeArray, Quester } from '@satorijs/satori' import { LarkBot } from '../bot' @@ -42,9 +41,6 @@ export class Internal { if (method === 'GET' || method === 'DELETE') { config.params = args[0] } else { - if (method === 'POST' && args[0] instanceof FormData) { - config.headers = args[0].getHeaders() - } config.data = args[0] } } else if (args.length === 2 && method !== 'GET' && method !== 'DELETE') { diff --git a/adapters/lark/src/types/message/asset.ts b/adapters/lark/src/types/message/asset.ts index 76428027..f792b585 100644 --- a/adapters/lark/src/types/message/asset.ts +++ b/adapters/lark/src/types/message/asset.ts @@ -1,5 +1,3 @@ -import FormData from 'form-data' - import { BaseResponse, Internal } from '..' export interface Asset extends BaseResponse { diff --git a/adapters/qq/src/message.ts b/adapters/qq/src/message.ts index fb573797..54f3721e 100644 --- a/adapters/qq/src/message.ts +++ b/adapters/qq/src/message.ts @@ -1,7 +1,6 @@ import * as QQ from './types' import { Context, Dict, h, MessageEncoder, Quester } from '@satorijs/satori' import { QQBot } from './bot' -import FormData from 'form-data' import { QQGuildBot } from './bot/guild' import { Entry } from '@satorijs/server-temp' @@ -11,7 +10,7 @@ export const escapeMarkdown = (val: string) => export class QQGuildMessageEncoder extends MessageEncoder> { private content: string = '' - private file: Buffer + private file: Blob private filename: string fileUrl: string private passiveId: string @@ -52,9 +51,7 @@ export class QQGuildMessageEncoder extends MessageE // if (this.fileUrl) { // form.append('image', this.fileUrl) // } - r = await this.bot.http.post(endpoint, form, { - headers: form.getHeaders(), - }) + r = await this.bot.http.post(endpoint, form) } else { const payload: QQ.Message.ChannelRequest = { ...{ @@ -147,8 +144,8 @@ export class QQGuildMessageEncoder extends MessageE if (!download && !await this.bot.ctx.http.isLocal(attrs.src || attrs.url)) { return this.fileUrl = attrs.src || attrs.url } - const { data, filename } = await this.bot.ctx.http.file(this.fileUrl || attrs.src || attrs.url, attrs) - this.file = Buffer.from(data) + const { data, filename, mime } = await this.bot.ctx.http.file(this.fileUrl || attrs.src || attrs.url, attrs) + this.file = new Blob([data], { type: mime }) this.filename = filename this.fileUrl = null } diff --git a/adapters/slack/src/bot.ts b/adapters/slack/src/bot.ts index 32117d76..70569a38 100644 --- a/adapters/slack/src/bot.ts +++ b/adapters/slack/src/bot.ts @@ -4,7 +4,6 @@ import { HttpServer } from './http' import { adaptMessage, decodeChannel, decodeGuild, decodeGuildMember, decodeUser } from './utils' import { SlackMessageEncoder } from './message' import { GenericMessageEvent, SlackChannel, SlackTeam, SlackUser } from './types' -import FormData from 'form-data' import { Internal, Token } from './types/internal' export class SlackBot extends Bot { @@ -31,11 +30,6 @@ export class SlackBot extends MessageEnc const { attrs } = element 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' - ? new Blob([data], { type: mime }) - : Buffer.from(data) + const value = new Blob([data], { type: mime }) form.append('file', value, attrs.file || filename) form.append('channels', this.channelId) if (this.thread_ts) form.append('thread_ts', this.thread_ts) const sent = await this.bot.request<{ ok: boolean file: File - }>('POST', '/files.upload', form, form.getHeaders()) + }>('POST', '/files.upload', form) if (sent.ok) { const session = this.bot.session() adaptSentAsset(sent.file, session) diff --git a/adapters/telegram/src/message.ts b/adapters/telegram/src/message.ts index 41be6ff3..87dc6da4 100644 --- a/adapters/telegram/src/message.ts +++ b/adapters/telegram/src/message.ts @@ -1,5 +1,4 @@ import { Context, Dict, h, MessageEncoder } from '@satorijs/satori' -import FormData from 'form-data' import { TelegramBot } from './bot' import * as Telegram from './utils' @@ -19,10 +18,7 @@ async function appendAsset(bot: TelegramBot, form: FormData, element: h): Promis } else if (element.type === 'audio') { method = element.attrs.type === 'voice' ? 'sendVoice' : 'sendAudio' } - // https://github.com/form-data/form-data/issues/468 - const value = process.env.KOISHI_ENV === 'browser' - ? new Blob([data], { type: mime }) - : Buffer.from(data) + const value = new Blob([data], { type: mime }) form.append(method.slice(4).toLowerCase(), value, filename) return method } diff --git a/adapters/telegram/src/types/internal.ts b/adapters/telegram/src/types/internal.ts index 440a2613..d3592bdf 100644 --- a/adapters/telegram/src/types/internal.ts +++ b/adapters/telegram/src/types/internal.ts @@ -1,4 +1,3 @@ -import FormData from 'form-data' import { TelegramBot } from '../bot' export interface Internal {} @@ -10,14 +9,7 @@ export class Internal { Internal.prototype[method] = async function (this: Internal, data = {}) { this.bot.logger.debug('[request] %s %o', method, data) try { - let response: any - if (data instanceof FormData) { - response = await this.bot.http.post('/' + method, data, { - headers: data.getHeaders(), - }) - } else { - response = await this.bot.http.post('/' + method, data) - } + const response = await this.bot.http.post('/' + method, data) this.bot.logger.debug('[response] %o', response) const { ok, result } = response if (ok) return result diff --git a/adapters/wechat-official/src/message.ts b/adapters/wechat-official/src/message.ts index 3daa4f29..81bc5d74 100644 --- a/adapters/wechat-official/src/message.ts +++ b/adapters/wechat-official/src/message.ts @@ -1,6 +1,5 @@ import { Context, h, MessageEncoder } from '@satorijs/satori' import { WechatOfficialBot } from './bot' -import FormData from 'form-data' import xml2js from 'xml2js' import { SendMessage } from './types' @@ -111,10 +110,7 @@ export class WechatOfficialMessageEncoder extends M const form = new FormData() 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) - + const value = new Blob([data], { type: mime }) form.append('media', value, attrs.file || filename) const resp = await this.bot.http.post<{ @@ -128,7 +124,6 @@ export class WechatOfficialMessageEncoder extends M access_token: this.bot.token, type: uploadType, }, - headers: form.getHeaders(), }) if (resp.media_id) { return [resp.media_id, uploadType] diff --git a/adapters/wecom/src/message.ts b/adapters/wecom/src/message.ts index 0f1074ef..355259b2 100644 --- a/adapters/wecom/src/message.ts +++ b/adapters/wecom/src/message.ts @@ -1,6 +1,5 @@ import { Context, h, MessageEncoder } from '@satorijs/satori' import { WecomBot } from './bot' -import FormData from 'form-data' /** https://developer.work.weixin.qq.com/document/path/90236#%E6%94%AF%E6%8C%81%E7%9A%84markdown%E8%AF%AD%E6%B3%95 */ @@ -70,10 +69,7 @@ export class WecomMessageEncoder extends MessageEnc const form = new FormData() 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) - + const value = new Blob([data], { type: mime }) form.append('media', value, attrs.file || filename) const resp = await this.bot.http.post<{ @@ -87,7 +83,6 @@ export class WecomMessageEncoder extends MessageEnc access_token: this.bot.token, type: uploadType, }, - headers: form.getHeaders(), }) if (resp.media_id) { return [resp.media_id, uploadType] diff --git a/adapters/whatsapp/src/internal.ts b/adapters/whatsapp/src/internal.ts index d6d5bc06..62a5fd09 100644 --- a/adapters/whatsapp/src/internal.ts +++ b/adapters/whatsapp/src/internal.ts @@ -1,6 +1,5 @@ import { Quester } from '@satorijs/satori' import { SendMessage } from './types' -import FormData from 'form-data' interface PhoneNumber { verified_name: string @@ -45,10 +44,6 @@ export class Internal { } uploadMedia(selfId: string, form: FormData) { - return this.http.post<{ - id: string - }>(`/${selfId}/media`, form, { - headers: form.getHeaders(), - }) + return this.http.post<{ id: string }>(`/${selfId}/media`, form) } } diff --git a/adapters/whatsapp/src/message.ts b/adapters/whatsapp/src/message.ts index 76b6f084..47a25230 100644 --- a/adapters/whatsapp/src/message.ts +++ b/adapters/whatsapp/src/message.ts @@ -1,6 +1,5 @@ import { Context, Dict, h, MessageEncoder } from '@satorijs/satori' import { WhatsAppBot } from './bot' -import FormData from 'form-data' import { Button, SendMessage } from './types' const SUPPORTED_MEDIA = [ @@ -91,9 +90,7 @@ export class WhatsAppMessageEncoder extends Message } const form = new FormData() - const value = process.env.KOISHI_ENV === 'browser' - ? new Blob([data], { type: mime }) - : Buffer.from(data) + const value = new Blob([data], { type: mime }) form.append('file', value, attrs.file || filename) form.append('type', mime) form.append('messaging_product', 'whatsapp') diff --git a/adapters/zulip/src/message.ts b/adapters/zulip/src/message.ts index 29c66515..528b4765 100644 --- a/adapters/zulip/src/message.ts +++ b/adapters/zulip/src/message.ts @@ -1,6 +1,5 @@ import { Context, h, MessageEncoder } from '@satorijs/satori' import { ZulipBot } from './bot' -import FormData from 'form-data' import { by_stream_topic_url, encodeHashComponent } from './utils' export const escape = (val: string) => @@ -26,9 +25,7 @@ export class ZulipMessageEncoder extends MessageEnc form.append('content', this.buffer) if (!this.session.isDirect) form.append('topic', this.session.channelId) - const { id } = await this.bot.http.post('/messages', form, { - headers: form.getHeaders(), - }) + const { id } = await this.bot.http.post('/messages', form) const session = this.bot.session() session.content = this.buffer session.messageId = id.toString() @@ -44,16 +41,9 @@ export class ZulipMessageEncoder extends MessageEnc const { attrs } = element 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' - ? new Blob([data], { type: mime }) - : Buffer.from(data) + const value = new Blob([data], { type: mime }) form.append('file', value, attrs.file || filename) - const response = await this.bot.http.post<{ - uri: string - }>('/user_uploads', form, { - headers: form.getHeaders(), - }) + const response = await this.bot.http.post<{ uri: string }>('/user_uploads', form) return [response.uri, filename] }