Skip to content

Commit

Permalink
refa: migrate form-data
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Feb 16, 2024
1 parent 4e2bac3 commit f60ca8c
Show file tree
Hide file tree
Showing 17 changed files with 27 additions and 117 deletions.
10 changes: 2 additions & 8 deletions 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'

Expand Down Expand Up @@ -63,10 +62,7 @@ export class DingtalkMessageEncoder<C extends Context = Context> 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]
Expand All @@ -77,9 +73,7 @@ export class DingtalkMessageEncoder<C extends Context = Context> 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
}

Expand Down
8 changes: 2 additions & 6 deletions 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'
Expand Down Expand Up @@ -88,13 +87,10 @@ export class DiscordMessageEncoder<C extends Context = Context> 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<string>, addition: Dict) {
Expand Down
2 changes: 0 additions & 2 deletions 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'
Expand Down Expand Up @@ -34,7 +33,6 @@ export class KookBot<C extends Context = Context, T extends KookBot.Config = Koo
if (method === 'GET') {
return (await this.http.get(path, { params: data, headers })).data
} else {
data = data instanceof FormData ? data : JSON.stringify(data)
return (await this.http(method, path, { data, headers })).data
}
}
Expand Down
18 changes: 6 additions & 12 deletions adapters/kook/src/message.ts
@@ -1,8 +1,6 @@
import { Context, h, MessageEncoder, Schema } from '@satorijs/satori'
import FormData from 'form-data'
import { KookBot } from './bot'
import * as Kook from './types'
import internal from 'stream'

export function isDirectChannel(channelId: string) {
return channelId.length > 30
Expand Down Expand Up @@ -54,22 +52,18 @@ export class KookMessageEncoder<C extends Context = Context> 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<internal.Readable>(src, {
const { data, headers } = await this.bot.ctx.http<ArrayBuffer>('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
Expand Down
17 changes: 2 additions & 15 deletions 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'
Expand Down Expand Up @@ -79,16 +74,8 @@ export class LarkMessageEncoder<C extends Context = Context> 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<internal.Readable>(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')
Expand Down
4 changes: 0 additions & 4 deletions 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'

Expand Down Expand Up @@ -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') {
Expand Down
2 changes: 0 additions & 2 deletions adapters/lark/src/types/message/asset.ts
@@ -1,5 +1,3 @@
import FormData from 'form-data'

import { BaseResponse, Internal } from '..'

export interface Asset<T> extends BaseResponse {
Expand Down
11 changes: 4 additions & 7 deletions 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'

Expand All @@ -11,7 +10,7 @@ export const escapeMarkdown = (val: string) =>

export class QQGuildMessageEncoder<C extends Context = Context> extends MessageEncoder<C, QQGuildBot<C>> {
private content: string = ''
private file: Buffer
private file: Blob
private filename: string
fileUrl: string
private passiveId: string
Expand Down Expand Up @@ -52,9 +51,7 @@ export class QQGuildMessageEncoder<C extends Context = Context> extends MessageE
// if (this.fileUrl) {
// form.append('image', this.fileUrl)
// }
r = await this.bot.http.post<QQ.Message>(endpoint, form, {
headers: form.getHeaders(),
})
r = await this.bot.http.post<QQ.Message>(endpoint, form)
} else {
const payload: QQ.Message.ChannelRequest = {
...{
Expand Down Expand Up @@ -147,8 +144,8 @@ export class QQGuildMessageEncoder<C extends Context = Context> 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
}
Expand Down
6 changes: 0 additions & 6 deletions adapters/slack/src/bot.ts
Expand Up @@ -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<C extends Context = Context, T extends SlackBot.Config = SlackBot.Config> extends Bot<C, T> {
Expand All @@ -31,11 +30,6 @@ export class SlackBot<C extends Context = Context, T extends SlackBot.Config = S
if (method === 'GET') {
return await this.http.get(path, { params: data, headers })
} else {
if (!headers['content-type']) {
data = data instanceof FormData ? data : JSON.stringify(data)
const type = data instanceof FormData ? 'multipart/form-data' : 'application/json; charset=utf-8'
headers['content-type'] = type
}
return (await this.http(method, path, { data, headers })).data
}
}
Expand Down
8 changes: 2 additions & 6 deletions adapters/slack/src/message.ts
@@ -1,6 +1,5 @@
import { Context, h, MessageEncoder } from '@satorijs/satori'
import { SlackBot } from './bot'
import FormData from 'form-data'
import { adaptMessage, adaptSentAsset } from './utils'
import { File } from './types'

Expand Down Expand Up @@ -49,17 +48,14 @@ export class SlackMessageEncoder<C extends Context = Context> 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)
Expand Down
6 changes: 1 addition & 5 deletions 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'

Expand All @@ -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
}
Expand Down
10 changes: 1 addition & 9 deletions adapters/telegram/src/types/internal.ts
@@ -1,4 +1,3 @@
import FormData from 'form-data'
import { TelegramBot } from '../bot'

export interface Internal {}
Expand All @@ -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
Expand Down
7 changes: 1 addition & 6 deletions 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'

Expand Down Expand Up @@ -111,10 +110,7 @@ export class WechatOfficialMessageEncoder<C extends Context = Context> 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<{
Expand All @@ -128,7 +124,6 @@ export class WechatOfficialMessageEncoder<C extends Context = Context> extends M
access_token: this.bot.token,
type: uploadType,
},
headers: form.getHeaders(),
})
if (resp.media_id) {
return [resp.media_id, uploadType]
Expand Down
7 changes: 1 addition & 6 deletions 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 */

Expand Down Expand Up @@ -70,10 +69,7 @@ export class WecomMessageEncoder<C extends Context = Context> 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<{
Expand All @@ -87,7 +83,6 @@ export class WecomMessageEncoder<C extends Context = Context> extends MessageEnc
access_token: this.bot.token,
type: uploadType,
},
headers: form.getHeaders(),
})
if (resp.media_id) {
return [resp.media_id, uploadType]
Expand Down
7 changes: 1 addition & 6 deletions 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
Expand Down Expand Up @@ -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)
}
}
5 changes: 1 addition & 4 deletions 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 = [
Expand Down Expand Up @@ -91,9 +90,7 @@ export class WhatsAppMessageEncoder<C extends Context = Context> 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')
Expand Down

0 comments on commit f60ca8c

Please sign in to comment.