全项目扫描修复: Docker数据卷修复+安全requireAdmin+12页SEO+API白名单+脚本超时+常量提取+假数据删除
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
// 直接调用 bot stats 逻辑,不走 HTTP
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
|
||||
import "dotenv/config";
|
||||
|
||||
const base = process.env.DATABASE_URL.replace("mysql://", "mariadb://");
|
||||
const sep = base.includes("?") ? "&" : "?";
|
||||
const connectionString = `${base}${sep}connection_limit=5&pool_timeout=10`;
|
||||
const adapter = new PrismaMariaDb(connectionString);
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
|
||||
async function main() {
|
||||
const days = 14;
|
||||
const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
||||
const sinceDate = new Date(since.getFullYear(), since.getMonth(), since.getDate());
|
||||
|
||||
const botUsers = await prisma.user.findMany({
|
||||
where: { isBot: true },
|
||||
select: { id: true, name: true, email: true, points: true },
|
||||
});
|
||||
const botConfigs = await prisma.botConfig.findMany({
|
||||
select: { id: true, userId: true, primaryForums: true },
|
||||
});
|
||||
const configByUserId = new Map(botConfigs.map((c) => [c.userId, c]));
|
||||
|
||||
const dailyStats = await prisma.botDailyStat.groupBy({
|
||||
by: ["botId"],
|
||||
where: { date: { gte: sinceDate } },
|
||||
_sum: {
|
||||
topicCreated: true,
|
||||
replySent: true,
|
||||
repliesReceived: true,
|
||||
likesReceived: true,
|
||||
humanInteractions: true,
|
||||
},
|
||||
});
|
||||
const statMap = new Map(
|
||||
dailyStats.map((s) => [
|
||||
s.botId,
|
||||
{
|
||||
topicCreated: s._sum.topicCreated || 0,
|
||||
replySent: s._sum.replySent || 0,
|
||||
likesReceived: s._sum.likesReceived || 0,
|
||||
humanInteractions: s._sum.humanInteractions || 0,
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
const memCount = await prisma.botMemory.count();
|
||||
console.log("--- Bot Stats Preview ---");
|
||||
console.log("Total bots:", botUsers.length);
|
||||
console.log("Total configs:", botConfigs.length);
|
||||
console.log("BotDailyStat records:", dailyStats.length);
|
||||
console.log("BotMemory records:", memCount);
|
||||
console.log("Bots with stats:", statMap.size);
|
||||
|
||||
// Top 5 by health score
|
||||
const top = botUsers
|
||||
.map((u) => {
|
||||
const cfg = configByUserId.get(u.id);
|
||||
const d = statMap.get(cfg?.id) || { topicCreated: 0, replySent: 0, likesReceived: 0, humanInteractions: 0 };
|
||||
return {
|
||||
name: u.name,
|
||||
health: d.topicCreated * 3 + d.replySent + d.likesReceived * 2 + d.humanInteractions * 5,
|
||||
...d,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => b.health - a.health)
|
||||
.slice(0, 5);
|
||||
|
||||
console.log("\n--- Top 5 ---");
|
||||
for (const t of top) {
|
||||
console.log(`${t.name.padEnd(20)} health=${String(t.health).padStart(4)} 话题=${t.topicCreated} 回复=${t.replySent} 赞=${t.likesReceived} 真人=${t.humanInteractions}`);
|
||||
}
|
||||
|
||||
// Trends
|
||||
const trendRaw = await prisma.botDailyStat.groupBy({
|
||||
by: ["date"],
|
||||
where: { date: { gte: sinceDate } },
|
||||
_sum: { topicCreated: true, replySent: true, likesReceived: true, humanInteractions: true },
|
||||
orderBy: { date: "asc" },
|
||||
});
|
||||
console.log("\n--- Trend (近14天) ---");
|
||||
for (const t of trendRaw) {
|
||||
console.log(`${t.date.toISOString().split("T")[0]} 话题=${t._sum.topicCreated} 回复=${t._sum.replySent} 赞=${t._sum.likesReceived}`);
|
||||
}
|
||||
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user