Files

95 lines
2.7 KiB
JavaScript

const fs = require('fs');
const path = require('path');
/** 清洗 Fandom CDN 缩略图链接,去掉 scale-to-width-down 参数还原原图地址 */
function cleanImageUrl(url) {
return url.replace(/(\/scale-to-width-down\/\d+\?.*)$/, '');
}
/** 从图片 URL 提取文件名并规范化(小写、下划线转短横线) */
function generateImageName(url) {
const fileNameMatch = url.match(/\/([^/]+)\.png/i);
if (fileNameMatch && fileNameMatch[1]) {
// 去除 .、&、(、) 等特殊字符
return fileNameMatch[1].toLowerCase().replace(/_/g, '-').replaceAll(/\.|%26|%28|%29|%e2%80%a2/g, "").replace(/-{2,}/g, '-');
}
return null;
}
/** 对 Wiki 原始文件名应用站点自定义转换,得到最终保存用的基础名 */
function toOutputBaseName(rawName, nameTransform) {
const transformed = nameTransform ? nameTransform(rawName) : rawName;
return transformed;
}
/** 根据 Fandom 站点根地址和页面标题拼接 parse API 请求 URL */
function buildParseApiUrl(baseUrl, wikiTitle) {
const apiBase = baseUrl.replace(/\/$/, '');
const params = new URLSearchParams({
action: 'parse',
page: wikiTitle,
prop: 'text',
format: 'json',
});
return `${apiBase}/api.php?${params.toString()}`;
}
/** 判断图片 URL 是否为懒加载占位图 */
function isPlaceholderImageUrl(url) {
return !url || url.startsWith('data:image/gif');
}
/** 从 img 元素读取图片地址,src 为占位图时自动回退到 data-src */
function resolveImageUrl($img, imageUrlAttr = 'src') {
const primary = $img.attr(imageUrlAttr);
if (!isPlaceholderImageUrl(primary)) {
return primary;
}
if (imageUrlAttr === 'src') {
const fallback = $img.attr('data-src');
if (!isPlaceholderImageUrl(fallback)) {
return fallback;
}
}
return null;
}
/** 延迟指定毫秒,用于控制下载请求间隔 */
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/** 从图片路径提取不含扩展名的文件名,兼容绝对 URL 与相对路径 */
function getFileBaseNameFromUrl(url) {
const normalized = url.split('?')[0].split('#')[0];
const fileName = path.basename(normalized);
return path.basename(fileName, path.extname(fileName));
}
/** 读取本地保存目录中所有 .webp 角色的基础文件名列表 */
function listLocalCharacters(savePath) {
if (!fs.existsSync(savePath)) {
return [];
}
return fs
.readdirSync(savePath)
.filter((file) => file.endsWith('.webp'))
.map((file) => path.basename(file, '.webp'))
.sort();
}
module.exports = {
cleanImageUrl,
generateImageName,
toOutputBaseName,
buildParseApiUrl,
isPlaceholderImageUrl,
resolveImageUrl,
getFileBaseNameFromUrl,
listLocalCharacters,
sleep,
};