File size: 7,744 Bytes
3c7e34b 6ec7384 3c7e34b 6ec7384 3c7e34b 0740360 e771551 c8f3880 3c7e34b 6ec7384 3c7e34b 0740360 e771551 3c7e34b 6ec7384 3c7e34b 6ec7384 3c7e34b 6ec7384 6bab161 6ec7384 6bab161 6ec7384 3c7e34b 6ec7384 3c7e34b 6ec7384 6bab161 6ec7384 6bab161 6ec7384 6bab161 6ec7384 6bab161 6ec7384 c8f3880 6ec7384 6bab161 6ec7384 3c7e34b c8f3880 3c7e34b 6ec7384 c8f3880 3c7e34b 6ec7384 3c7e34b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | const { ChannelType } = require('discord.js');
const { errorEmbed, infoEmbed, successEmbed, createEmbed } = require('../utils/embeds');
const { logCommand } = require('../systems/logger');
const { startDropSession, hasSession, getPrompt, handleDropMessage, canDrop } = require('../systems/drops');
const { stmts } = require('../database');
const { Colors } = require('../config');
// Import command handlers
const setup = require('../commands/setup');
const createRoles = require('../commands/createRoles');
const createChannels = require('../commands/createChannels');
const backupLayout = require('../commands/backupLayout');
const shutdown = require('../commands/shutdown');
const ticketStats = require('../commands/ticketStats');
const permissionAudit = require('../commands/permissionAudit');
const postRules = require('../commands/postRules');
const postDisclaimer = require('../commands/postDisclaimer');
const applyUpdates = require('../commands/applyUpdates');
const fixPings = require('../commands/fixPings');
const clearDrops = require('../commands/clearDrops');
const OWNER_ID = process.env.OWNER_ID;
// Owner-only command registry
const commands = {
'setup server': setup,
'create roles': createRoles,
'create channels': createChannels,
'backup layout': backupLayout,
'shutdown bot': shutdown,
'ticket stats': ticketStats,
'permission audit': permissionAudit,
'post rules': postRules,
'post disclaimer': postDisclaimer,
'apply updates': applyUpdates,
'fix pings': fixPings,
};
module.exports = {
name: 'messageCreate',
async execute(client, message) {
if (message.author.bot) return;
if (message.channel.type !== ChannelType.DM) return;
const userId = message.author.id;
const content = message.content.trim().toLowerCase();
// ββ Handle active drop session (owner OR whitelisted) ββ
if (hasSession(userId)) {
try {
const handled = await handleDropMessage(message);
if (handled) return;
} catch (err) {
console.error('[Drop Error]', err);
await message.reply({ content: `β Drop error: ${err.message}` }).catch(() => { });
return;
}
}
// ββ Whitelisted user: only allow "drop" ββ
if (userId !== OWNER_ID) {
if (content === 'drop') {
const check = canDrop(userId);
if (!check.allowed) {
if (check.reason === 'not_whitelisted') {
return; // Silently ignore non-whitelisted users
}
// Rate limited
return message.reply({
embeds: [createEmbed({
title: 'β³ Drop Cooldown',
description: `You've used all **${check.limit} drops** in the last 24 hours.\n\n> Resets in **${check.resetIn}**`,
color: Colors.WARNING,
})],
});
}
const session = startDropSession(userId);
await message.reply({
...getPrompt(session),
content: `π¦ **Drop ${check.limit - check.remaining + 1}/${check.limit} for today**`,
});
return;
}
return; // Whitelisted users can only use "drop"
}
// ββ Owner-only commands below ββββββββββββββββββββββββββ
// Drop (no rate limit for owner)
if (content === 'drop') {
await logCommand(client, 'drop');
const session = startDropSession(userId);
await message.reply(getPrompt(session));
return;
}
// Whitelist management
if (content.startsWith('whitelist ') && !content.startsWith('whitelist <')) {
const args = content.split(' ').slice(1);
const targetId = args[0]?.trim();
const limit = parseInt(args[1]) || 3;
if (!targetId || !/^\d{17,20}$/.test(targetId)) {
return message.reply({ embeds: [errorEmbed('Invalid ID', 'Usage: `whitelist <user_id> [limit]`\nExample: `whitelist 123456789 5`')] });
}
stmts.addWhitelist.run(targetId, limit, userId);
const user = await client.users.fetch(targetId).catch(() => null);
const name = user ? `**${user.tag}**` : `ID \`${targetId}\``;
return message.reply({ embeds: [successEmbed('β
Whitelisted', `${name} can now use \`drop\` (**${limit}** per day)`)] });
}
if (content.startsWith('unwhitelist ')) {
const targetId = content.split(' ')[1]?.trim();
if (!targetId) return message.reply({ embeds: [errorEmbed('Invalid ID', 'Usage: `unwhitelist <user_id>`')] });
stmts.removeWhitelist.run(targetId);
return message.reply({ embeds: [successEmbed('β
Removed', `User \`${targetId}\` removed from whitelist`)] });
}
// Clear Drops
if (content.startsWith('clear ')) {
const args = content.split(' ').slice(1);
return clearDrops.execute(client, message, args);
}
if (content === 'whitelist') {
const all = stmts.getAllWhitelist.all();
if (all.length === 0) {
return message.reply({ embeds: [infoEmbed('Whitelist', 'No users whitelisted.\n\nUse `whitelist <user_id>` to add.')] });
}
const lines = [];
for (const w of all) {
const user = await client.users.fetch(w.user_id).catch(() => null);
const name = user ? user.tag : 'Unknown';
const drops = stmts.getDropCount24h.get(w.user_id);
lines.push(`β’ **${name}** (\`${w.user_id}\`) β ${drops.count}/${w.max_drops} drops today`);
}
return message.reply({ embeds: [infoEmbed('π Whitelist', lines.join('\n'))] });
}
// Show help
if (content === 'help') {
const allCommands = [...Object.keys(commands), 'drop', 'whitelist', 'whitelist <id> [limit]', 'unwhitelist <id>', 'clear <channel_id>'];
const embed = infoEmbed('WSB Commands', [
'All commands are **DM-only** and **Owner-only**.\n',
...allCommands.map(cmd => `\`${cmd}\``),
].join('\n'));
return message.reply({ embeds: [embed] });
}
// Find matching command
const handler = commands[content];
if (!handler) {
if (content.startsWith('setup') || content.startsWith('create') ||
content.startsWith('backup') || content.startsWith('shutdown') ||
content.startsWith('ticket') || content.startsWith('permission') ||
content.startsWith('post') || content.startsWith('drop') ||
content.startsWith('apply') || content.startsWith('fix') ||
content.startsWith('clear')) {
return message.reply({ embeds: [errorEmbed('Unknown Command', `Did you mean one of these?\n${[...Object.keys(commands), 'drop', 'clear <channel_id>'].map(c => `\`${c}\``).join('\n')}`)] });
}
return;
}
try {
await logCommand(client, content);
await handler.execute(client, message);
} catch (err) {
console.error(`[Command Error] ${content}:`, err);
await message.reply({ embeds: [errorEmbed('Error', `Command failed: \`${err.message}\``)] }).catch(() => { });
}
},
};
|