From 547640bbfd6b49860dbf73a1fc03781fcccfeb95 Mon Sep 17 00:00:00 2001 From: DrSmoothl <1787882683@qq.com> Date: Tue, 30 Jun 2026 01:24:00 +0800 Subject: [PATCH] fix(onebot): route oversized videos to the file path up front (#145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A video larger than MAX_VIDEO_SIZE (~100 MB, QQ's video-resource cap) uploads "successfully" — the server accepts the Highway bytes — but the receiver sees 视频已过期 because no valid video resource is ever produced. The existing large-video → file fallback only fired from the send catch block, i.e. when the upload threw. An oversized upload doesn't throw, so the fallback never triggered. Add a proactive split before the send: any video whose source size is known to exceed MAX_VIDEO_SIZE is re-routed to the file pipeline up front (mirrored for private and group sends). Smaller videos (verified up to ~49 MB) are unaffected and still send as videos. This pairs with the c2c-file fix (f8caa92): the re-routed video now rides the now-working offline-file path and downloads correctly. --- .../onebot/src/modules/message-actions.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/onebot/src/modules/message-actions.ts b/packages/onebot/src/modules/message-actions.ts index e2d4da1c..1fa44697 100644 --- a/packages/onebot/src/modules/message-actions.ts +++ b/packages/onebot/src/modules/message-actions.ts @@ -583,6 +583,19 @@ export async function sendPrivateMessage( let allFileElements = elements.filter(e => e.type === 'file'); let nonFileElements = elements.filter(e => e.type !== 'file'); + // [#145] A video above QQ's ~100 MB video-resource cap (MAX_VIDEO_SIZE) + // uploads "successfully" but renders as 视频已过期 on the receiver — the + // server accepts the bytes yet never produces a valid video resource. The + // on-error fallback below can't catch it (the oversized upload doesn't + // throw), so route known-oversized videos to the file path up front. + { + const pre = splitVideoFileFallback(nonFileElements, false); + if (pre.fileEls.length > 0) { + allFileElements = [...allFileElements, ...pre.fileEls]; + nonFileElements = pre.remaining; + } + } + let lastReceipt: Awaited> | undefined; if (nonFileElements.length > 0) { try { @@ -690,6 +703,16 @@ export async function sendGroupMessage( let allFileElements = elements.filter(e => e.type === 'file'); let nonFileElements = elements.filter(e => e.type !== 'file'); + // [#145] Route known-oversized videos (> MAX_VIDEO_SIZE) to the file path + // up front — they upload as a video without error but render expired. + { + const pre = splitVideoFileFallback(nonFileElements, false); + if (pre.fileEls.length > 0) { + allFileElements = [...allFileElements, ...pre.fileEls]; + nonFileElements = pre.remaining; + } + } + let lastReceipt: Awaited> | undefined; if (nonFileElements.length > 0) { try {