fix: 修复newspic类型图片上传和news类型封面兜底逻辑
- uploadImagesInHtml 函数添加 articleType 参数支持 - 为 newspic 类型正文图片额外调用 material 接口收集 media_id - 返回 firstImageSource 用于 news 类型封面兜底逻辑 - 恢复 news 类型没有显式封面时使用第一张正文图作为封面的逻辑
This commit is contained in:
parent
e79a42fd94
commit
747977416d
|
|
@ -175,17 +175,19 @@ async function uploadImagesInHtml(
|
||||||
accessToken: string,
|
accessToken: string,
|
||||||
baseDir: string,
|
baseDir: string,
|
||||||
contentImages: ImageInfo[] = [],
|
contentImages: ImageInfo[] = [],
|
||||||
): Promise<{ html: string; firstImageUrl: string; allMediaIds: string[] }> {
|
articleType: ArticleType = "news",
|
||||||
|
): Promise<{ html: string; firstImageUrl: string; firstImageSource: string; imageMediaIds: string[] }> {
|
||||||
const imgRegex = /<img[^>]*\ssrc=["']([^"']+)["'][^>]*>/gi;
|
const imgRegex = /<img[^>]*\ssrc=["']([^"']+)["'][^>]*>/gi;
|
||||||
const matches = [...html.matchAll(imgRegex)];
|
const matches = [...html.matchAll(imgRegex)];
|
||||||
|
|
||||||
if (matches.length === 0 && contentImages.length === 0) {
|
if (matches.length === 0 && contentImages.length === 0) {
|
||||||
return { html, firstImageUrl: "", allMediaIds: [] };
|
return { html, firstImageUrl: "", firstImageSource: "", imageMediaIds: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
let firstImageUrl = "";
|
let firstImageUrl = "";
|
||||||
|
let firstImageSource = "";
|
||||||
let updatedHtml = html;
|
let updatedHtml = html;
|
||||||
const allMediaIds: string[] = [];
|
const imageMediaIds: string[] = [];
|
||||||
const uploadedBySource = new Map<string, UploadResponse>();
|
const uploadedBySource = new Map<string, UploadResponse>();
|
||||||
|
|
||||||
for (const match of matches) {
|
for (const match of matches) {
|
||||||
|
|
@ -206,7 +208,7 @@ async function uploadImagesInHtml(
|
||||||
try {
|
try {
|
||||||
let resp = uploadedBySource.get(imagePath);
|
let resp = uploadedBySource.get(imagePath);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
// 正文图片使用 media/uploadimg 接口
|
// 正文图片使用 media/uploadimg 接口获取 URL
|
||||||
resp = await uploadImage(imagePath, accessToken, baseDir, "body");
|
resp = await uploadImage(imagePath, accessToken, baseDir, "body");
|
||||||
uploadedBySource.set(imagePath, resp);
|
uploadedBySource.set(imagePath, resp);
|
||||||
}
|
}
|
||||||
|
|
@ -217,6 +219,21 @@ async function uploadImagesInHtml(
|
||||||
if (!firstImageUrl) {
|
if (!firstImageUrl) {
|
||||||
firstImageUrl = resp.url;
|
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) {
|
} catch (err) {
|
||||||
console.error(`[wechat-api] Failed to upload ${imagePath}:`, err);
|
console.error(`[wechat-api] Failed to upload ${imagePath}:`, err);
|
||||||
}
|
}
|
||||||
|
|
@ -231,7 +248,7 @@ async function uploadImagesInHtml(
|
||||||
try {
|
try {
|
||||||
let resp = uploadedBySource.get(imagePath);
|
let resp = uploadedBySource.get(imagePath);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
// 正文图片使用 media/uploadimg 接口
|
// 正文图片使用 media/uploadimg 接口获取 URL
|
||||||
resp = await uploadImage(imagePath, accessToken, baseDir, "body");
|
resp = await uploadImage(imagePath, accessToken, baseDir, "body");
|
||||||
uploadedBySource.set(imagePath, resp);
|
uploadedBySource.set(imagePath, resp);
|
||||||
}
|
}
|
||||||
|
|
@ -241,12 +258,27 @@ async function uploadImagesInHtml(
|
||||||
if (!firstImageUrl) {
|
if (!firstImageUrl) {
|
||||||
firstImageUrl = resp.url;
|
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) {
|
} catch (err) {
|
||||||
console.error(`[wechat-api] Failed to upload placeholder ${image.placeholder}:`, 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(
|
async function publishToDraft(
|
||||||
|
|
@ -609,11 +641,12 @@ async function main(): Promise<void> {
|
||||||
const accessToken = await fetchAccessToken(creds.appId, creds.appSecret);
|
const accessToken = await fetchAccessToken(creds.appId, creds.appSecret);
|
||||||
|
|
||||||
console.error("[wechat-api] Uploading body images...");
|
console.error("[wechat-api] Uploading body images...");
|
||||||
const { html: processedHtml, firstImageUrl, allMediaIds } = await uploadImagesInHtml(
|
const { html: processedHtml, firstImageUrl, firstImageSource, imageMediaIds } = await uploadImagesInHtml(
|
||||||
htmlContent,
|
htmlContent,
|
||||||
accessToken,
|
accessToken,
|
||||||
baseDir,
|
baseDir,
|
||||||
contentImages,
|
contentImages,
|
||||||
|
args.articleType,
|
||||||
);
|
);
|
||||||
htmlContent = processedHtml;
|
htmlContent = processedHtml;
|
||||||
|
|
||||||
|
|
@ -633,13 +666,10 @@ async function main(): Promise<void> {
|
||||||
const coverResp = await uploadImage(coverPath, accessToken, baseDir, "material");
|
const coverResp = await uploadImage(coverPath, accessToken, baseDir, "material");
|
||||||
thumbMediaId = coverResp.media_id;
|
thumbMediaId = coverResp.media_id;
|
||||||
console.error(`[wechat-api] Cover uploaded successfully, media_id: ${thumbMediaId}`);
|
console.error(`[wechat-api] Cover uploaded successfully, media_id: ${thumbMediaId}`);
|
||||||
} else if (firstImageUrl && args.articleType === "news") {
|
} else if (firstImageSource && args.articleType === "news") {
|
||||||
// news 类型需要 thumb_media_id,正文图片的 URL 无法使用
|
// news 类型没有封面时,使用第一张正文图的 media_id 作为封面(兜底逻辑)
|
||||||
console.error(`[wechat-api] Warning: No cover image provided for news article.`);
|
thumbMediaId = firstImageSource;
|
||||||
console.error(`[wechat-api] The first body image URL is: ${firstImageUrl}`);
|
console.error(`[wechat-api] Using first body image as cover (fallback), media_id: ${thumbMediaId}`);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.articleType === "news" && !thumbMediaId) {
|
if (args.articleType === "news" && !thumbMediaId) {
|
||||||
|
|
@ -647,7 +677,7 @@ async function main(): Promise<void> {
|
||||||
process.exit(1);
|
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.");
|
console.error("Error: newspic requires at least one image in content.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
@ -660,7 +690,7 @@ async function main(): Promise<void> {
|
||||||
content: htmlContent,
|
content: htmlContent,
|
||||||
thumbMediaId,
|
thumbMediaId,
|
||||||
articleType: args.articleType,
|
articleType: args.articleType,
|
||||||
imageMediaIds: args.articleType === "newspic" ? allMediaIds : undefined,
|
imageMediaIds: args.articleType === "newspic" ? imageMediaIds : undefined,
|
||||||
needOpenComment: resolved.need_open_comment,
|
needOpenComment: resolved.need_open_comment,
|
||||||
onlyFansCanComment: resolved.only_fans_can_comment,
|
onlyFansCanComment: resolved.only_fans_can_comment,
|
||||||
}, accessToken);
|
}, accessToken);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue