feat: Implement a generic user timers system with a scheduler to manage cooldowns, effects, and access.

This commit is contained in:
syntaxbullet
2025-12-13 14:18:46 +01:00
parent b33738aee3
commit d34e872133
6 changed files with 194 additions and 30 deletions

View File

@@ -1,4 +1,4 @@
import { users, cooldowns } from "@/db/schema";
import { users, userTimers } from "@/db/schema";
import { eq, sql, and } from "drizzle-orm";
import { DrizzleClient } from "@/lib/DrizzleClient";
import { GameConfig } from "@/config/game";
@@ -58,15 +58,16 @@ export const levelingService = {
processChatXp: async (id: string, tx?: any) => {
const execute = async (txFn: any) => {
// check if an xp cooldown is in place
const cooldown = await txFn.query.cooldowns.findFirst({
const cooldown = await txFn.query.userTimers.findFirst({
where: and(
eq(cooldowns.userId, BigInt(id)),
eq(cooldowns.actionKey, 'xp')
eq(userTimers.userId, BigInt(id)),
eq(userTimers.type, 'COOLDOWN'),
eq(userTimers.key, 'chat_xp')
),
});
const now = new Date();
if (cooldown && cooldown.readyAt > now) {
if (cooldown && cooldown.expiresAt > now) {
return { awarded: false, reason: 'cooldown' };
}
@@ -79,15 +80,16 @@ export const levelingService = {
// Update/Set Cooldown
const nextReadyAt = new Date(now.getTime() + GameConfig.leveling.chat.cooldownMs);
await txFn.insert(cooldowns)
await txFn.insert(userTimers)
.values({
userId: BigInt(id),
actionKey: 'xp',
readyAt: nextReadyAt,
type: 'COOLDOWN',
key: 'chat_xp',
expiresAt: nextReadyAt,
})
.onConflictDoUpdate({
target: [cooldowns.userId, cooldowns.actionKey],
set: { readyAt: nextReadyAt },
target: [userTimers.userId, userTimers.type, userTimers.key],
set: { expiresAt: nextReadyAt },
});
return { awarded: true, amount, ...result };