95 lines
3.1 KiB
JavaScript
95 lines
3.1 KiB
JavaScript
// 直接调用 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);
|
|
});
|