Add new IRC games and enhance bot functionality

- Add Rock Paper Scissors game with PvP and bot modes
  - Fixed syntax errors and improved game mechanics
  - PvP moves now require PM for secrecy

- Add Word Scramble game with difficulty levels
  - Multiple word categories and persistent scoring

- Enhance duck hunt with better statistics tracking
  - Separate points vs duck count tracking
  - Fixed migration logic issues

- Add core rate limiting system (5 commands/30s)
  - Admin whitelist for megasconed
  - Automatic cleanup and unblocking

- Improve reload functionality for hot-reloading plugins
- Add channel-specific commands (\!stopducks/\!startducks)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
megaproxy 2025-07-17 20:06:32 +00:00
parent a3ed25f8dd
commit 8552887b6c
9 changed files with 1536 additions and 30 deletions

View file

@ -33,6 +33,76 @@ module.exports = {
const now = new Date().toLocaleString();
bot.say(context.replyTo, `Current time: ${now}`);
}
},
{
name: 'ratelimit',
description: 'Check your rate limit status',
execute(context, bot) {
// Only allow in #bakedbeans or for admins
if (context.channel !== '#bakedbeans' && !bot.rateLimitConfig.adminWhitelist.includes(context.nick)) {
bot.say(context.replyTo, '🚫 This command can only be used in #bakedbeans!');
return;
}
const userLimits = bot.rateLimits.get(context.nick);
const config = bot.rateLimitConfig;
if (config.adminWhitelist.includes(context.nick)) {
bot.say(context.replyTo, `${context.nick}: You are whitelisted (no rate limits)`);
return;
}
if (!userLimits) {
bot.say(context.replyTo, `${context.nick}: No rate limit data (you're clean!)`);
return;
}
const now = Date.now();
if (userLimits.blocked && now < userLimits.blockExpiry) {
const remainingMs = userLimits.blockExpiry - now;
const remainingSeconds = Math.ceil(remainingMs / 1000);
bot.say(context.replyTo, `🚫 ${context.nick}: Rate limited for ${remainingSeconds} more seconds`);
return;
}
const windowStart = now - config.windowMs;
const recentCommands = userLimits.commands.filter(timestamp => timestamp > windowStart);
const remaining = config.maxCommands - recentCommands.length;
bot.say(context.replyTo, `📊 ${context.nick}: ${recentCommands.length}/${config.maxCommands} commands used in last ${config.windowMs/1000}s (${remaining} remaining)`);
}
},
{
name: 'reload',
description: 'Reload all plugins (admin only)',
execute(context, bot) {
// Only allow for admin
if (context.nick !== 'megasconed') {
bot.say(context.replyTo, '🚫 Only admins can reload plugins!');
return;
}
// Only allow in #bakedbeans
if (context.channel !== '#bakedbeans') {
bot.say(context.replyTo, '🚫 Plugin reload can only be done in #bakedbeans!');
return;
}
bot.say(context.replyTo, '🔄 Reloading all plugins...');
const pluginCount = bot.plugins.size;
try {
bot.reloadAllPlugins();
const newCommandCount = bot.commands.size;
bot.say(context.replyTo, `✅ Reloaded ${pluginCount} plugins successfully! Now have ${newCommandCount} commands available.`);
} catch (error) {
console.error('❌ Error during plugin reload:', error);
bot.say(context.replyTo, '❌ Error during plugin reload - check console for details.');
}
}
}
]
};