From 747977416d984d4e23fcdd01a62af5ec4060cc6b 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 13:57:59 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dnewspic=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=9B=BE=E7=89=87=E4=B8=8A=E4=BC=A0=E5=92=8Cnews?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=B0=81=E9=9D=A2=E5=85=9C=E5=BA=95=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - uploadImagesInHtml 函数添加 articleType 参数支持 - 为 newspic 类型正文图片额外调用 material 接口收集 media_id - 返回 firstImageSource 用于 news 类型封面兜底逻辑 - 恢复 news 类型没有显式封面时使用第一张正文图作为封面的逻辑 --- .../scripts/wechat-api.ts | 62 ++++++++++++++----- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/skills/baoyu-post-to-wechat/scripts/wechat-api.ts b/skills/baoyu-post-to-wechat/scripts/wechat-api.ts index 4802736..7266460 100644 --- a/skills/baoyu-post-to-wechat/scripts/wechat-api.ts +++ b/skills/baoyu-post-to-wechat/scripts/wechat-api.ts @@ -175,17 +175,19 @@ async function uploadImagesInHtml( accessToken: string, baseDir: string, contentImages: ImageInfo[] = [], -): Promise<{ html: string; firstImageUrl: string; allMediaIds: string[] }> { + articleType: ArticleType = "news", +): Promise<{ html: string; firstImageUrl: string; firstImageSource: string; imageMediaIds: string[] }> { const imgRegex = /]*\ssrc=["']([^"']+)["'][^>]*>/gi; const matches = [...html.matchAll(imgRegex)]; if (matches.length === 0 && contentImages.length === 0) { - return { html, firstImageUrl: "", allMediaIds: [] }; + return { html, firstImageUrl: "", firstImageSource: "", imageMediaIds: [] }; } let firstImageUrl = ""; + let firstImageSource = ""; let updatedHtml = html; - const allMediaIds: string[] = []; + const imageMediaIds: string[] = []; const uploadedBySource = new Map(); for (const match of matches) { @@ -206,7 +208,7 @@ async function uploadImagesInHtml( try { let resp = uploadedBySource.get(imagePath); if (!resp) { - // 正文图片使用 media/uploadimg 接口 + // 正文图片使用 media/uploadimg 接口获取 URL resp = await uploadImage(imagePath, accessToken, baseDir, "body"); uploadedBySource.set(imagePath, resp); } @@ -217,6 +219,21 @@ async function uploadImagesInHtml( if (!firstImageUrl) { firstImageUrl = resp.url; } + + // 如果是 newspic 类型,额外调用 material 接口收集 media_id + if (articleType === "newspic") { + let materialResp = uploadedBySource.get(`${imagePath}:material`); + if (!materialResp) { + materialResp = await uploadImage(imagePath, accessToken, baseDir, "material"); + uploadedBySource.set(`${imagePath}:material`, materialResp); + } + if (materialResp.media_id) { + imageMediaIds.push(materialResp.media_id); + if (!firstImageSource) { + firstImageSource = materialResp.media_id; + } + } + } } catch (err) { console.error(`[wechat-api] Failed to upload ${imagePath}:`, err); } @@ -231,7 +248,7 @@ async function uploadImagesInHtml( try { let resp = uploadedBySource.get(imagePath); if (!resp) { - // 正文图片使用 media/uploadimg 接口 + // 正文图片使用 media/uploadimg 接口获取 URL resp = await uploadImage(imagePath, accessToken, baseDir, "body"); uploadedBySource.set(imagePath, resp); } @@ -241,12 +258,27 @@ async function uploadImagesInHtml( if (!firstImageUrl) { firstImageUrl = resp.url; } + + // 如果是 newspic 类型,额外调用 material 接口收集 media_id + if (articleType === "newspic") { + let materialResp = uploadedBySource.get(`${imagePath}:material`); + if (!materialResp) { + materialResp = await uploadImage(imagePath, accessToken, baseDir, "material"); + uploadedBySource.set(`${imagePath}:material`, materialResp); + } + if (materialResp.media_id) { + imageMediaIds.push(materialResp.media_id); + if (!firstImageSource) { + firstImageSource = materialResp.media_id; + } + } + } } catch (err) { console.error(`[wechat-api] Failed to upload placeholder ${image.placeholder}:`, err); } } - return { html: updatedHtml, firstImageUrl, allMediaIds }; + return { html: updatedHtml, firstImageUrl, firstImageSource, imageMediaIds }; } async function publishToDraft( @@ -609,11 +641,12 @@ async function main(): Promise { const accessToken = await fetchAccessToken(creds.appId, creds.appSecret); console.error("[wechat-api] Uploading body images..."); - const { html: processedHtml, firstImageUrl, allMediaIds } = await uploadImagesInHtml( + const { html: processedHtml, firstImageUrl, firstImageSource, imageMediaIds } = await uploadImagesInHtml( htmlContent, accessToken, baseDir, contentImages, + args.articleType, ); htmlContent = processedHtml; @@ -633,13 +666,10 @@ async function main(): Promise { const coverResp = await uploadImage(coverPath, accessToken, baseDir, "material"); thumbMediaId = coverResp.media_id; console.error(`[wechat-api] Cover uploaded successfully, media_id: ${thumbMediaId}`); - } else if (firstImageUrl && args.articleType === "news") { - // news 类型需要 thumb_media_id,正文图片的 URL 无法使用 - console.error(`[wechat-api] Warning: No cover image provided for news article.`); - console.error(`[wechat-api] The first body image URL is: ${firstImageUrl}`); - console.error(`[wechat-api] However, news articles require thumb_media_id (not URL).`); - console.error(`[wechat-api] Please provide --cover parameter or set coverImage in frontmatter.`); - process.exit(1); + } else if (firstImageSource && args.articleType === "news") { + // news 类型没有封面时,使用第一张正文图的 media_id 作为封面(兜底逻辑) + thumbMediaId = firstImageSource; + console.error(`[wechat-api] Using first body image as cover (fallback), media_id: ${thumbMediaId}`); } if (args.articleType === "news" && !thumbMediaId) { @@ -647,7 +677,7 @@ async function main(): Promise { process.exit(1); } - if (args.articleType === "newspic" && allMediaIds.length === 0) { + if (args.articleType === "newspic" && imageMediaIds.length === 0) { console.error("Error: newspic requires at least one image in content."); process.exit(1); } @@ -660,7 +690,7 @@ async function main(): Promise { content: htmlContent, thumbMediaId, articleType: args.articleType, - imageMediaIds: args.articleType === "newspic" ? allMediaIds : undefined, + imageMediaIds: args.articleType === "newspic" ? imageMediaIds : undefined, needOpenComment: resolved.need_open_comment, onlyFansCanComment: resolved.only_fans_can_comment, }, accessToken);