feat: 首次推送到Gitea - 完整项目代码 + 安全加固 + 知识库

This commit is contained in:
ZhuiGuangAI Dev
2026-10-02 18:52:49 +08:00
parent b44601bb66
commit 8205ae709c
1185 changed files with 49841 additions and 12802 deletions
+90
View File
@@ -0,0 +1,90 @@
// 每月1号运行:给活跃用户发放断签保护卡
// Grant freeze cards to active users on the 1st of each month
import { PrismaClient } from "@prisma/client";
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
import "dotenv/config";
const base = (process.env.DATABASE_URL || "mysql://localhost:3306/zhuiguang_ai?charset=utf8mb4").replace("mysql://", "mariadb://");
const sep = base.includes("?") ? "&" : "?";
const connectionString = `${base}${sep}connection_limit=5&pool_timeout=15`;
const adapter = new PrismaMariaDb(connectionString);
const prisma = new PrismaClient({ adapter });
function getCurrentMonth() {
const d = new Date();
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`;
}
async function main() {
const currentMonth = getCurrentMonth();
console.log(`[grant-freeze-cards] 开始发放 ${currentMonth} 月断签保护卡...`);
// 活跃判定:近 30 天有 签到 / 发帖 / 回复 任一即可(真人用户)。
// 原实现只统计签到(forumCheckIn 常为空),导致断签卡永远发不出。
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const [checkinIds, topicIds, postIds] = await Promise.all([
prisma.forumCheckIn.findMany({
where: { checkInDate: { gte: thirtyDaysAgo } },
distinct: ["userId"],
select: { userId: true },
}),
prisma.forumTopic.findMany({
where: { createdAt: { gte: thirtyDaysAgo }, user: { isBot: false } },
distinct: ["userId"],
select: { userId: true },
}),
prisma.forumPost.findMany({
where: { createdAt: { gte: thirtyDaysAgo }, user: { isBot: false } },
distinct: ["userId"],
select: { userId: true },
}),
]);
const activeUserIds = [...new Set([...checkinIds, ...topicIds, ...postIds].map((r) => r.userId))];
console.log(`[grant-freeze-cards] 找到 ${activeUserIds.length} 位近30天活跃用户`);
let granted = 0;
let skipped = 0;
let newUsers = 0;
for (const userId of activeUserIds) {
const key = `streak_freeze_${userId}`;
const existing = await prisma.systemConfig.findUnique({ where: { key } });
if (existing) {
const data = existing.value;
if (data.lastGrantedMonth === currentMonth) {
skipped++;
continue; // Already granted this month
}
// Grant 2 cards, cap at 2
data.freezeCards = Math.min((data.freezeCards || 0) + 2, 2);
data.lastGrantedMonth = currentMonth;
await prisma.systemConfig.update({
where: { key },
data: { value: data },
});
granted++;
} else {
// New user: grant initial 2 cards
await prisma.systemConfig.create({
data: {
key,
value: { freezeCards: 2, lastGrantedMonth: currentMonth },
},
});
newUsers++;
}
}
console.log(`[grant-freeze-cards] 完成: 发放 ${granted} 人, 新用户 ${newUsers} 人, 跳过 ${skipped} 人 (本月已发放) `);
await prisma.$disconnect();
}
main().catch(async (e) => {
console.error("[grant-freeze-cards] 执行失败:", e.message);
if (prisma) await prisma.$disconnect();
process.exit(1);
});