Add events module with dashboard UI, scheduling, signups, and settings updates; extend env/readme.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Collection, Message } from 'discord.js';
|
||||
import { logger } from '../utils/logger.js';
|
||||
import { settings } from '../config/state.js';
|
||||
import { logger } from '../utils/logger';
|
||||
import { settingsStore } from '../config/state';
|
||||
import { prisma } from '../database';
|
||||
|
||||
interface LevelData {
|
||||
xp: number;
|
||||
@@ -8,32 +9,53 @@ interface LevelData {
|
||||
}
|
||||
|
||||
export class LevelService {
|
||||
private data = new Collection<string, LevelData>();
|
||||
private cache = new Collection<string, LevelData>();
|
||||
private cooldown = new Set<string>();
|
||||
|
||||
handleMessage(message: Message) {
|
||||
if (!message.guild || message.author.bot) return;
|
||||
const guildConfig = settings.get(message.guild.id);
|
||||
if (!guildConfig?.levelingEnabled) return;
|
||||
private key(guildId: string, userId: string) {
|
||||
return `${guildId}:${userId}`;
|
||||
}
|
||||
|
||||
const key = `${message.guild.id}:${message.author.id}`;
|
||||
async handleMessage(message: Message) {
|
||||
if (!message.guild || message.author.bot) return;
|
||||
const guildConfig = settingsStore.get(message.guild.id);
|
||||
if (guildConfig?.levelingEnabled !== true) return;
|
||||
|
||||
const key = this.key(message.guild.id, message.author.id);
|
||||
if (this.cooldown.has(key)) return;
|
||||
this.cooldown.add(key);
|
||||
setTimeout(() => this.cooldown.delete(key), 60_000);
|
||||
|
||||
const entry = this.data.get(key) ?? { xp: 0, level: 0 };
|
||||
entry.xp += 10;
|
||||
const entry = await this.loadLevel(message.guild.id, message.author.id);
|
||||
const xpGain = 10;
|
||||
entry.xp += xpGain;
|
||||
const nextLevel = Math.floor(0.2 * Math.sqrt(entry.xp));
|
||||
if (nextLevel > entry.level) {
|
||||
entry.level = nextLevel;
|
||||
message.channel.send({ content: `${message.author} hat Level ${entry.level} erreicht!` }).catch(() => undefined);
|
||||
logger.info(`Level up: ${message.author.tag} -> ${entry.level}`);
|
||||
}
|
||||
this.data.set(key, entry);
|
||||
this.cache.set(key, entry);
|
||||
await prisma.level.upsert({
|
||||
where: { userId_guildId: { userId: message.author.id, guildId: message.guild.id } },
|
||||
update: { xp: entry.xp, level: entry.level },
|
||||
create: { userId: message.author.id, guildId: message.guild.id, xp: entry.xp, level: entry.level }
|
||||
});
|
||||
}
|
||||
|
||||
getLevel(userId: string, guildId: string) {
|
||||
const key = `${guildId}:${userId}`;
|
||||
return this.data.get(key) ?? { xp: 0, level: 0 };
|
||||
async getLevel(userId: string, guildId: string) {
|
||||
const key = this.key(guildId, userId);
|
||||
const cached = this.cache.get(key);
|
||||
if (cached) return cached;
|
||||
return this.loadLevel(guildId, userId);
|
||||
}
|
||||
|
||||
private async loadLevel(guildId: string, userId: string): Promise<LevelData> {
|
||||
const key = this.key(guildId, userId);
|
||||
if (this.cache.has(key)) return this.cache.get(key)!;
|
||||
const row = await prisma.level.findUnique({ where: { userId_guildId: { guildId, userId } } }).catch(() => null);
|
||||
const entry: LevelData = { xp: row?.xp ?? 0, level: row?.level ?? 0 };
|
||||
this.cache.set(key, entry);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user