diff --git a/package.json b/package.json index 5f73102..19ede40 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "koishi-plugin-adapter-red", "description": "Red Protocol Adapter for Koishi", - "version": "3.0.3", + "version": "3.1.0", "main": "lib/index.js", "typings": "lib/index.d.ts", "files": [ @@ -31,12 +31,12 @@ "url": "https://github.com/idanran" }, "peerDependencies": { - "koishi": "^4.17.0" + "koishi": "^4.17.3" }, "devDependencies": { "@koishijs/plugin-server": "^3.1.8", "koishi-plugin-ffmpeg": "^1.1.0", - "koishi-plugin-silk": "^1.1.0" + "koishi-plugin-silk": "^1.1.2" }, "koishi": { "description": { diff --git a/src/assets.ts b/src/assets.ts index 5b0d210..c04f6ed 100644 --- a/src/assets.ts +++ b/src/assets.ts @@ -1,6 +1,8 @@ import { Context, sanitize, trimSlash, Quester, Dict } from 'koishi' import { RedBot } from './bot' import { Message } from './types' +import { Readable } from 'node:stream' +import { ReadableStream } from 'node:stream/web' import { } from '@koishijs/plugin-server' export class RedAssets { @@ -23,14 +25,6 @@ export class RedAssets { })).toString('base64url') return `${this.selfUrl}${this.path}/${payload}` } - get(payload: Dict) { - return this.bot.internal.getFile({ - msgId: payload.msgId, - chatType: payload.chatType, - peerUid: payload.peerUid, - elementId: payload.elementId, - }) - } private get selfUrl() { if (this.config.selfUrl) { return trimSlash(this.config.selfUrl) @@ -44,7 +38,7 @@ export class RedAssets { ctx.body = '200 OK' ctx.status = 200 }) - this.bot.ctx.server.get(this.path + '/:data', async (ctx) => { + this.bot.ctx.server.get(this.path + '/:data', async (ctx, next) => { const data = ctx.params['data'] let payload: Dict if (data.endsWith('=')) { @@ -53,34 +47,38 @@ export class RedAssets { payload = JSON.parse(Buffer.from(data, 'base64url').toString()) } const mime = payload.mime - let response: Quester.Response + let file: Quester.Response try { - response = await this.get(payload) + file = await this.bot.internal.getFileStream({ + msgId: payload.msgId, + chatType: payload.chatType, + peerUid: payload.peerUid, + elementId: payload.elementId, + }) } catch (err) { if (!Quester.Error.is(err)) { throw err } if (mime.includes('image')) { try { - response = await this.bot.ctx.http(`https://gchat.qpic.cn/gchatpic_new/0/0-0-${payload.md5.toUpperCase()}/0`, { + file = await this.bot.ctx.http(`https://gchat.qpic.cn/gchatpic_new/0/0-0-${payload.md5.toUpperCase()}/0`, { method: 'GET', - responseType: 'arraybuffer' + responseType: 'stream' }) } catch { } } - response ||= err.response + file ||= err.response } - const { headers } = response - const contentType = headers.get('content-type') - - ctx.status = response.status + ctx.status = file.status + const contentType = file.headers.get('content-type') if (contentType) { ctx.type = contentType - } else if (response.status === 200) { + } else if (file.status === 200) { ctx.type = mime } - ctx.body = Buffer.from(response.data) + ctx.body = Readable.fromWeb(file.data) + return next() }) } } \ No newline at end of file diff --git a/src/internal.ts b/src/internal.ts index 513573d..f69779b 100644 --- a/src/internal.ts +++ b/src/internal.ts @@ -45,13 +45,21 @@ export class Internal { } getFile(data: Red.MessageFetchRichMediaPayload) { - return this.http('/api/message/fetchRichMedia', { + return this.http('/api/message/fetchRichMedia', { method: 'POST', data, responseType: 'arraybuffer' }) } + getFileStream(data: Red.MessageFetchRichMediaPayload) { + return this.http('/api/message/fetchRichMedia', { + method: 'POST', + data, + responseType: 'stream' + }) + } + muteGroup(data: Red.GroupMuteEveryonePayload) { return this.http.post('/api/group/muteEveryone', data) } diff --git a/src/utils.ts b/src/utils.ts index 0e7c5ca..74be0be 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -98,7 +98,7 @@ export async function decodeMessage( let url: string if (originImageUrl?.startsWith('/gchatpic_new')) { url = `https://c2cpicdw.qpic.cn${originImageUrl}` - } else if (originImageUrl?.startsWith('/download')) { + } else if (originImageUrl?.startsWith('/download') && originImageUrl.includes('rkey=')) { url = `https://multimedia.nt.qq.com.cn${originImageUrl}` } url ||= bot.redAssets.set(data, v.elementId, mime, md5HexStr)