From 79c289ca928f62c9a9728487a529eca92650a926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=AA=E4=B8=8D=E8=83=BD=E5=81=9C?= Date: Fri, 20 Mar 2026 18:18:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A4=84=E7=90=86WebP=E7=AD=89=E4=B8=8D?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=9A=84=E6=A0=BC=E5=BC=8F=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=9B=9E=E9=80=80=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加WebP、BMP、TIFF等格式到不支持列表 - 对于需要回退到material接口的情况,同时调用两个接口获取URL和media_id - 提取uploadToWechat函数避免代码重复 --- .../scripts/wechat-api.ts | 81 +++++++++++++------ 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/skills/baoyu-post-to-wechat/scripts/wechat-api.ts b/skills/baoyu-post-to-wechat/scripts/wechat-api.ts index 154bf66..9aa3372 100644 --- a/skills/baoyu-post-to-wechat/scripts/wechat-api.ts +++ b/skills/baoyu-post-to-wechat/scripts/wechat-api.ts @@ -75,7 +75,7 @@ async function fetchAccessToken(appId: string, appSecret: string): Promise BODY_IMG_MAX_SIZE; - if (uploadType === "body" && isGifOrLarge) { - console.error(`[wechat-api] Image ${filename} is GIF or larger than 1MB, using material API instead`); - uploadType = "material"; + // 检查是否需要回退到 material 接口 + const isUnsupportedFormat = BODY_IMG_UNSUPPORTED_FORMATS.includes(fileExt); + const isTooLarge = fileSize > BODY_IMG_MAX_SIZE; + const needFallback = uploadType === "body" && (isUnsupportedFormat || isTooLarge); + + // 记录警告信息 + if (needFallback) { + const reason = isUnsupportedFormat ? `unsupported format (${fileExt})` : `too large (${(fileSize / 1024 / 1024).toFixed(2)}MB)`; + console.error(`[wechat-api] Image ${filename} is ${reason}, using material API for both URL and media_id`); } + // 如果需要回退到 material 接口,为了获取正文图片 URL,需要同时调用两个接口 + let bodyUrl = ""; + if (needFallback) { + // 先调用 material 接口获取 media_id(也返回 url) + const materialResult = await uploadToWechat(fileBuffer, filename, contentType, accessToken, "material"); + // 再调用 body 接口获取可以在正文中使用的 URL + const bodyResult = await uploadToWechat(fileBuffer, filename, contentType, accessToken, "body"); + bodyUrl = bodyResult.url || materialResult.url; + + if (materialResult.url?.startsWith("http://")) { + materialResult.url = materialResult.url.replace(/^http:\/\//i, "https://"); + } + return { + url: bodyUrl, + media_id: materialResult.media_id, + } as UploadResponse; + } + + // 正常情况:直接使用选定的接口上传 + const result = await uploadToWechat(fileBuffer, filename, contentType, accessToken, uploadType); + + // media/uploadimg 接口只返回 URL,material/add_material 返回 media_id + if (uploadType === "body") { + if (result.url?.startsWith("http://")) { + result.url = result.url.replace(/^http:\/\//i, "https://"); + } + return { + url: result.url, + media_id: "", + } as UploadResponse; + } else { + if (result.url?.startsWith("http://")) { + result.url = result.url.replace(/^http:\/\//i, "https://"); + } + return result; + } +} + +// 实际的微信上传函数 +async function uploadToWechat( + fileBuffer: Buffer, + filename: string, + contentType: string, + accessToken: string, + uploadType: "body" | "material" +): Promise { const boundary = `----WebKitFormBoundary${Date.now().toString(16)}`; const header = [ `--${boundary}`, @@ -151,7 +201,6 @@ async function uploadImage( const footerBuffer = Buffer.from(footer, "utf-8"); const body = Buffer.concat([headerBuffer, fileBuffer, footerBuffer]); - // 根据上传类型选择不同的接口 const uploadUrl = uploadType === "body" ? UPLOAD_BODY_IMG_URL : UPLOAD_MATERIAL_URL; const url = `${uploadUrl}?type=image&access_token=${accessToken}`; const res = await fetch(url, { @@ -167,23 +216,7 @@ async function uploadImage( throw new Error(`Upload failed ${data.errcode}: ${data.errmsg}`); } - // media/uploadimg 接口只返回 URL,material/add_material 返回 media_id - if (uploadType === "body") { - // 正文图片上传,返回 URL - if (data.url?.startsWith("http://")) { - data.url = data.url.replace(/^http:\/\//i, "https://"); - } - return { - url: data.url, - media_id: "", - } as UploadResponse; - } else { - // 封面图片上传,返回 media_id - if (data.url?.startsWith("http://")) { - data.url = data.url.replace(/^http:\/\//i, "https://"); - } - return data; - } + return data; } async function uploadImagesInHtml(