import { Guild, GuildMember, PermissionFlagsBits } from 'discord.js'; import { prisma } from '../../core/client'; import { config } from '../../core/config'; type DangerousAction = 'CHANNEL_DELETE' | 'BAN_ADD' | 'KICK' | 'ROLE_DELETE' | 'WEBHOOK_DELETE'; interface HeatEvent { userId: string; action: DangerousAction; timestamp: Date; } export class HeatSystem { private heatCache: Map = new Map(); isWhitelisted(userId: string): boolean { return config.security.whitelistedUsers.includes(userId); } async recordAction(userId: string, action: DangerousAction, guild: Guild): Promise { if (this.isWhitelisted(userId)) { return false; } const now = new Date(); const event: HeatEvent = { userId, action, timestamp: now }; await prisma.heatEvent.create({ data: { userId, action, timestamp: now }, }); const events = this.heatCache.get(userId) || []; events.push(event); const windowStart = new Date(now.getTime() - config.security.heatWindowMs); const recentEvents = events.filter(e => e.timestamp >= windowStart); this.heatCache.set(userId, recentEvents); console.log(`🔥 Heat event: ${action} by ${userId} (${recentEvents.length}/${config.security.heatThreshold})`); if (recentEvents.length >= config.security.heatThreshold) { console.log(`🚨 THRESHOLD EXCEEDED for ${userId}!`); await this.triggerLockdown(userId, guild, recentEvents); return true; } return false; } private async triggerLockdown(userId: string, guild: Guild, events: HeatEvent[]): Promise { console.log(`🔒 LOCKDOWN INITIATED in ${guild.name}`); try { const member = await guild.members.fetch(userId).catch(() => null); if (member && member.bannable) { await member.ban({ reason: `[SENTINEL] Anti-nuke triggered: ${events.length} dangerous actions in ${config.security.heatWindowMs}ms`, deleteMessageSeconds: 0, }); console.log(`🔨 Banned ${member.user.tag} for nuke attempt`); } } catch (error) { console.error('❌ Failed to ban attacker:', error); } try { const everyoneRole = guild.roles.everyone; await everyoneRole.setPermissions( everyoneRole.permissions.remove([ PermissionFlagsBits.SendMessages, PermissionFlagsBits.AddReactions, PermissionFlagsBits.CreatePublicThreads, PermissionFlagsBits.CreatePrivateThreads, ]), '[SENTINEL] Lockdown mode activated' ); console.log(`🔒 Locked down @everyone permissions`); } catch (error) { console.error('❌ Failed to modify @everyone permissions:', error); } await this.sendLockdownAlert(guild, userId, events); await prisma.user.upsert({ where: { id: userId }, update: { heatLevel: events.length }, create: { id: userId, heatLevel: events.length }, }); } private async sendLockdownAlert(guild: Guild, attackerId: string, events: HeatEvent[]): Promise { const owner = await guild.fetchOwner().catch(() => null); if (!owner) return; try { await owner.send({ content: `🚨 **LOCKDOWN ALERT** 🚨\n\n` + `Server: **${guild.name}**\n` + `Attacker ID: \`${attackerId}\`\n` + `Actions detected: ${events.length}\n` + `Actions: ${events.map(e => e.action).join(', ')}\n\n` + `The attacker has been banned and @everyone permissions have been restricted.\n` + `Please review audit logs and restore permissions when safe.`, }); } catch (error) { console.error('❌ Failed to DM server owner:', error); } } async unlockGuild(guild: Guild): Promise { try { const everyoneRole = guild.roles.everyone; await everyoneRole.setPermissions( everyoneRole.permissions.add([ PermissionFlagsBits.SendMessages, PermissionFlagsBits.AddReactions, ]), '[SENTINEL] Lockdown lifted' ); console.log(`🔓 Lifted lockdown in ${guild.name}`); } catch (error) { console.error('❌ Failed to unlock guild:', error); } } clearHeat(userId: string): void { this.heatCache.delete(userId); } } export const heatSystem = new HeatSystem();