Files
zhuiguang-ai/scripts/_forum-clear.cjs
T

71 lines
3.1 KiB
JavaScript

// 论坛内容 备份+清空 工具(在 app 容器内运行)
// 用法: node _forum-clear.mjs dump <out.json> | node _forum-clear.mjs clear
const fs = require("fs");
const { PrismaMariaDb } = require("@prisma/adapter-mariadb");
const { PrismaClient } = require("@prisma/client");
const env = fs.readFileSync("/app/.env", "utf8");
const m = env.match(/^DATABASE_URL=(.+)$/m);
let base = m[1].trim().replace(/^["']|["']$/g, "");
if (base.includes("?")) base = base.split("?")[0];
const p = new PrismaClient({ adapter: new PrismaMariaDb(base + "?connection_limit=5&pool_timeout=30") });
const MODE = process.argv[2];
async function dump(outPath) {
const [categories, topics, posts, topicLikes, postLikes, tags, topicTags, bookmarks, reports, subscriptions, moderationLogs] =
await Promise.all([
p.forumCategory.findMany(),
p.forumTopic.findMany(),
p.forumPost.findMany(),
p.forumTopicLike.findMany(),
p.forumPostLike.findMany(),
p.forumTag.findMany(),
p.forumTopicTag.findMany(),
p.forumTopicBookmark.findMany(),
p.forumReport.findMany(),
p.forumTopicSubscription.findMany(),
p.forumModerationLog.findMany(),
]);
const data = { categories, topics, posts, topicLikes, postLikes, tags, topicTags, bookmarks, reports, subscriptions, moderationLogs };
fs.writeFileSync(outPath, JSON.stringify(data));
console.log(`DUMP_OK topics=${topics.length} posts=${posts.length} likes=${topicLikes.length + postLikes.length} tags=${tags.length} -> ${outPath} (${(fs.statSync(outPath).size / 1024 / 1024).toFixed(2)}MB)`);
}
async function clearData() {
const del = async (name, fn) => {
try {
const r = await fn();
console.log(`cleared ${name}: ${r.count ?? r} rows`);
return r.count ?? r;
} catch (e) {
console.log(`clear ${name} skipped: ${e.message.slice(0, 80)}`);
return 0;
}
};
await del("forum_topic_subscriptions", () => p.forumTopicSubscription.deleteMany());
await del("forum_reports", () => p.forumReport.deleteMany());
await del("forum_moderation_logs", () => p.forumModerationLog.deleteMany());
await del("forum_topic_bookmarks", () => p.forumTopicBookmark.deleteMany());
await del("forum_topic_tags", () => p.forumTopicTag.deleteMany());
await del("forum_post_likes", () => p.forumPostLike.deleteMany());
await del("forum_topic_likes", () => p.forumTopicLike.deleteMany());
await del("forum_posts", () => p.forumPost.deleteMany());
await del("forum_topics", () => p.forumTopic.deleteMany());
await del("forum_tags", () => p.forumTag.deleteMany());
const upd = await p.forumCategory.updateMany({ data: { topicCount: 0 } });
console.log(`reset forum_categories.topic_count: ${upd.count}`);
const [tc, pc] = await Promise.all([p.forumTopic.count(), p.forumPost.count()]);
console.log(`FINAL topics=${tc} posts=${pc}`);
}
(async () => {
if (MODE === "dump") {
await dump(process.argv[3] || "/tmp/forum-dump.json");
} else if (MODE === "clear") {
await clearData();
} else {
console.error("usage: dump <out> | clear");
process.exit(1);
}
})().catch((e) => { console.error("ERR:", e.message); process.exit(1); }).finally(() => p.$disconnect());