全项目扫描修复: Docker数据卷修复+安全requireAdmin+12页SEO+API白名单+脚本超时+常量提取+假数据删除

This commit is contained in:
ZhuiGuangAI Dev
2026-06-12 17:27:47 +08:00
parent 464924aea0
commit 4c325c8699
454 changed files with 33647 additions and 980 deletions
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env node
// scripts/bot-avatar-generate.mjs
// 数字人头像批量预生成 + 落盘 + 回写 User.avatarUrl
//
// 用法:
// node scripts/bot-avatar-generate.mjs # 生成所有 bot 头像
// node scripts/bot-avatar-generate.mjs --bot=laochen # 只生成单个 bot
// node scripts/bot-avatar-generate.mjs --force # 强制重新生成(已存在也覆盖)
// node scripts/bot-avatar-generate.mjs --use-lunaris-only # 只用 Lunaris,不生成 SVG(当前 Lunaris 全是 default,不推荐)
// node scripts/bot-avatar-generate.mjs --no-update-db # 只落盘,不写 User.avatarUrl
// node scripts/bot-avatar-generate.mjs --dry-run # 试运行,不落盘不写库
import { disconnect, generateForAll } from "./lib/bot-avatar-generator.mjs";
function parseArgs() {
const args = process.argv.slice(2);
const out = { force: false, useLunarisOnly: false, updateDb: true, dryRun: false, bot: null, delay: 200 };
for (const a of args) {
if (a === "--force") out.force = true;
else if (a === "--use-lunaris-only") out.useLunarisOnly = true;
else if (a === "--no-update-db") out.updateDb = false;
else if (a === "--dry-run") out.dryRun = true;
else if (a.startsWith("--bot=")) out.bot = a.slice(6);
else if (a.startsWith("--delay=")) out.delay = parseInt(a.slice(8), 10);
else if (a === "--help" || a === "-h") {
console.log("用法: node scripts/bot-avatar-generate.mjs [选项]");
console.log(" --bot=<key> 只生成指定 bot");
console.log(" --force 覆盖已存在的头像");
console.log(" --use-lunaris-only 禁用 SVG 兜底(当前不推荐)");
console.log(" --no-update-db 只落盘不写 User.avatarUrl");
console.log(" --dry-run 试运行,不落盘不写库");
console.log(" --delay=<ms> bot 间隔延迟(默认 200ms)");
process.exit(0);
}
}
return out;
}
function ts() {
return new Date().toISOString().replace("T", " ").slice(0, 19);
}
async function main() {
const args = parseArgs();
console.log(`${ts()} 数字人头像批量预生成开始`);
console.log(
` bot=${args.bot || "all"} force=${args.force} lunarisOnly=${args.useLunarisOnly} updateDb=${args.updateDb} dryRun=${args.dryRun} delay=${args.delay}ms`
);
if (!process.env.DATABASE_URL) {
throw new Error("DATABASE_URL 未配置");
}
const startTime = Date.now();
const { summary, results } = await generateForAll({
force: args.force,
botKey: args.bot,
useLunarisOnly: args.useLunarisOnly,
delayMs: args.dryRun ? 0 : args.delay,
});
const duration = Date.now() - startTime;
console.log("");
console.log(`${ts()} 完成: total=${summary.total} ok=${summary.ok} failed=${summary.failed} (${duration}ms)`);
console.log(`${ts()} 落盘位置: public/bot-avatars/{key}.svg + public/bot-avatars/lunaris/{key}.jpg`);
console.log(`${ts()} 清单: public/bot-avatars/manifest.json`);
if (summary.failed > 0) {
console.log("");
console.log("失败列表:");
for (const r of results) {
if (r.error) console.log(` - ${r.key}: ${r.error}`);
}
}
await disconnect();
process.exit(summary.failed > 0 ? 1 : 0);
}
main().catch(async (err) => {
console.error(`${ts()} ❌ 致命错误: ${err.message}`);
console.error(err.stack);
await disconnect().catch(() => {});
process.exit(1);
});