


























@@ -1,10 +1,6 @@
11import { StickerFormatType, type APIAttachment, type APIStickerItem } from "discord-api-types/v10";
22import { getFileExtension } from "openclaw/plugin-sdk/media-mime";
3-import {
4-fetchRemoteMedia,
5-saveMediaBuffer,
6-type FetchLike,
7-} from "openclaw/plugin-sdk/media-runtime";
3+import { saveRemoteMedia, type FetchLike } from "openclaw/plugin-sdk/media-runtime";
84import { buildMediaPayload } from "openclaw/plugin-sdk/reply-payload";
95import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
106import type { SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
@@ -215,19 +211,23 @@ async function fetchDiscordMedia(params: {
215211readIdleTimeoutMs?: number;
216212totalTimeoutMs?: number;
217213abortSignal?: AbortSignal;
214+fallbackContentType?: string;
215+originalFilename?: string;
218216}) {
219217const timeoutAbortController = params.totalTimeoutMs ? new AbortController() : undefined;
220218const signal = mergeAbortSignals([params.abortSignal, timeoutAbortController?.signal]);
221219let timedOut = false;
222220let timeoutHandle: ReturnType<typeof setTimeout> | null = null;
223221224-const fetchPromise = fetchRemoteMedia({
222+const savePromise = saveRemoteMedia({
225223url: params.url,
226224filePathHint: params.filePathHint,
227225maxBytes: params.maxBytes,
228226fetchImpl: params.fetchImpl,
229227ssrfPolicy: params.ssrfPolicy,
230228readIdleTimeoutMs: params.readIdleTimeoutMs,
229+fallbackContentType: params.fallbackContentType,
230+originalFilename: params.originalFilename,
231231 ...(signal ? { requestInit: { signal } } : {}),
232232}).catch((error) => {
233233if (timedOut) {
@@ -238,7 +238,7 @@ async function fetchDiscordMedia(params: {
238238239239try {
240240if (!params.totalTimeoutMs) {
241-return await fetchPromise;
241+return await savePromise;
242242}
243243const timeoutPromise = new Promise<never>((_, reject) => {
244244timeoutHandle = setTimeout(() => {
@@ -248,7 +248,7 @@ async function fetchDiscordMedia(params: {
248248}, params.totalTimeoutMs);
249249timeoutHandle.unref?.();
250250});
251-return await Promise.race([fetchPromise, timeoutPromise]);
251+return await Promise.race([savePromise, timeoutPromise]);
252252} finally {
253253if (timeoutHandle) {
254254clearTimeout(timeoutHandle);
@@ -280,7 +280,7 @@ async function appendResolvedMediaFromAttachments(params: {
280280continue;
281281}
282282try {
283-const fetched = await fetchDiscordMedia({
283+const saved = await fetchDiscordMedia({
284284url: attachmentUrl,
285285filePathHint: attachment.filename ?? attachmentUrl,
286286maxBytes: params.maxBytes,
@@ -289,14 +289,9 @@ async function appendResolvedMediaFromAttachments(params: {
289289readIdleTimeoutMs: params.readIdleTimeoutMs,
290290totalTimeoutMs: params.totalTimeoutMs,
291291abortSignal: params.abortSignal,
292+fallbackContentType: attachment.content_type,
293+originalFilename: attachment.filename,
292294});
293-const saved = await saveMediaBuffer(
294-fetched.buffer,
295-fetched.contentType ?? attachment.content_type,
296-"inbound",
297-params.maxBytes,
298-attachment.filename,
299-);
300295params.out.push({
301296path: saved.path,
302297contentType: saved.contentType,
@@ -388,7 +383,7 @@ async function appendResolvedMediaFromStickers(params: {
388383let lastError: unknown;
389384for (const candidate of candidates) {
390385try {
391-const fetched = await fetchDiscordMedia({
386+const saved = await fetchDiscordMedia({
392387url: candidate.url,
393388filePathHint: candidate.fileName,
394389maxBytes: params.maxBytes,
@@ -397,14 +392,9 @@ async function appendResolvedMediaFromStickers(params: {
397392readIdleTimeoutMs: params.readIdleTimeoutMs,
398393totalTimeoutMs: params.totalTimeoutMs,
399394abortSignal: params.abortSignal,
395+fallbackContentType: inferStickerContentType(sticker),
396+originalFilename: candidate.fileName,
400397});
401-const saved = await saveMediaBuffer(
402-fetched.buffer,
403-fetched.contentType,
404-"inbound",
405-params.maxBytes,
406-candidate.fileName,
407-);
408398params.out.push({
409399path: saved.path,
410400contentType: saved.contentType,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。