selfbot-legacy/bot/handlers/message_handler.py
2025-05-08 20:47:48 +03:00

180 lines
7.1 KiB
Python

import discord
import asyncio
import re
import time
from config import BLACKLISTED_USERS, BUCKET_REACT_USERS, AUTO_DELETE_USERS, SPECIAL_RESPONSES
from bot.commands.afk_commands import AfkCommands
from bot.commands.utility_commands import UtilityCommands
from bot.commands.fun_commands import FunCommands
from bot.commands.admin_commands import AdminCommands
from bot.commands.test_commands import TestCommands
from utils.time_parser import parse_time
class MessageHandler:
def __init__(self, bot):
self.bot = bot
# Initialize command handlers
self.afk_commands = AfkCommands(bot)
self.utility_commands = UtilityCommands(bot)
self.fun_commands = FunCommands(bot)
self.admin_commands = AdminCommands(bot)
self.test_commands = TestCommands(bot)
# Attach command handlers to the bot for easier access from tests
bot.afk_commands = self.afk_commands
bot.utility_commands = self.utility_commands
bot.fun_commands = self.fun_commands
bot.admin_commands = self.admin_commands
bot.test_commands = self.test_commands
# Regex for detecting "in X time" patterns
self.time_pattern = re.compile(
r'in\s+((?:\d+\s*(?:seconds?|minutes?|hours?|days?|s|m|h|d)\s*)+)',
re.IGNORECASE
)
def parse_relative_time(self, time_str):
"""
Parse relative time strings like "2 hours", "30 minutes"
Args:
time_str: String in format like "2 hours", "30 minutes"
Returns:
Unix timestamp (seconds since epoch) for the future time or None if invalid
"""
# Convert to format our parse_time can handle
time_part = time_str.replace('hours', 'h').replace('hour', 'h')
time_part = time_part.replace('minutes', 'm').replace('minute', 'm')
time_part = time_part.replace('seconds', 's').replace('second', 's')
time_part = time_part.replace('days', 'd').replace('day', 'd')
# Remove spaces to match expected format like "2h30m"
time_part = re.sub(r'\s+', '', time_part)
seconds = parse_time(time_part)
if seconds:
return int(time.time() + seconds)
return None
def create_discord_timestamp(self, unix_time, format_code='R'):
"""Create a Discord timestamp string"""
return f"<t:{unix_time}:{format_code}>"
def replace_time_patterns(self, content):
"""Replace "in X time" patterns with Discord timestamps"""
def replace_match(match):
time_str = match.group(1)
unix_time = self.parse_relative_time(time_str)
if unix_time:
return self.create_discord_timestamp(unix_time)
return match.group(0) # Return original text if parsing fails
return self.time_pattern.sub(replace_match, content)
async def handle_message(self, message):
# Skip bot messages
if message.author.bot:
return
# Skip command messages (they start with . usually)
if message.content.startswith('.'):
return
# Look for and replace time patterns
original_content = message.content
modified_content = self.replace_time_patterns(original_content)
# If the content was modified, edit the original message
if modified_content != original_content:
try:
await message.edit(content=modified_content)
except Exception as e:
# If we don't have permission to edit, just ignore
pass
# Handle special responses
for user_id, data in SPECIAL_RESPONSES.items():
if message.author.id == user_id and data["trigger"] in message.content:
await message.reply(data["response"])
# Handle automatic reactions
if message.channel.id in self.bot.horsin:
await message.add_reaction("🐴")
if message.author.id in BUCKET_REACT_USERS:
await message.add_reaction("🪣")
# Handle auto-delete for specific users
if message.author.id in AUTO_DELETE_USERS:
try:
await message.delete()
except:
pass
# Handle DM if in AFK mode
if isinstance(message.channel, discord.DMChannel) and message.author != self.bot.user:
await self.afk_commands.handle_afk_dm(message)
# Don't process further if the message is not from the bot user
if message.author != self.bot.user:
return
# Handle commands
await self.handle_commands(message)
async def handle_blacklist(self, message):
"""Handle blacklisted users"""
if message.author.id in BLACKLISTED_USERS:
await message.reply("no")
return True
return False
async def handle_commands(self, message):
"""Handle commands issued by the bot user"""
content = message.content
# AFK Commands
if content.startswith(".afk"):
await self.afk_commands.cmd_afk(message)
elif content.startswith(".unafk"):
await self.afk_commands.cmd_unafk(message)
# Fun Commands
elif content.startswith(".horse"):
await self.fun_commands.cmd_horse(message)
elif content.startswith(".rps "):
if not await self.handle_blacklist(message):
await self.fun_commands.cmd_rps(message)
elif content.startswith(".repeat29"):
await self.fun_commands.cmd_repeat(message)
# Utility Commands
elif content.startswith(".remindme "):
if not await self.handle_blacklist(message):
await self.utility_commands.cmd_remindme(message)
elif content.startswith(".fmt "):
await self.utility_commands.cmd_fmt(message)
elif content.startswith(".eval "):
await self.utility_commands.cmd_eval(message)
elif content.startswith(".delrecent "):
await self.utility_commands.cmd_delrecent(message)
elif content.startswith(".nuke"):
await self.utility_commands.cmd_nuke_server(message)
elif content.startswith(".savechannel"):
await self.utility_commands.cmd_savechannel(message)
# Admin Commands
elif content.startswith(".addcmd "):
await self.admin_commands.cmd_addcmd(message)
elif content.startswith(".delcmd "):
await self.admin_commands.cmd_delcmd(message)
elif content.startswith(".listcmds"):
await self.admin_commands.cmd_listcmds(message)
elif content.startswith(".trackmessages"):
await self.admin_commands.cmd_trackmessages(message)
elif content.startswith(".untrackmessages"):
await self.admin_commands.cmd_untrackmessages(message)
elif content.startswith(".test"):
await self.test_commands.cmd_test(message)