From 4d60c12d17ee58278d06b67e0c38bbee597a841b Mon Sep 17 00:00:00 2001 From: Xargana Date: Thu, 8 May 2025 20:31:41 +0300 Subject: [PATCH] added the timestamp thingye --- bot/commands/timestamp_command.py | 82 +++++++++++++++++++++++++++++++ bot/handlers/message_handler.py | 64 ++++++++++++++++++++++++ utils/time_parser.py | 3 +- 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 bot/commands/timestamp_command.py diff --git a/bot/commands/timestamp_command.py b/bot/commands/timestamp_command.py new file mode 100644 index 0000000..bd58ca5 --- /dev/null +++ b/bot/commands/timestamp_command.py @@ -0,0 +1,82 @@ +import re +import time +import datetime +from utils.time_parser import parse_time + +def parse_relative_time(time_str): + """ + Parse relative time strings like "in 2 hours", "in 30 minutes" + + Args: + time_str: String in format like "in 2 hours", "in 30 minutes" + + Returns: + Unix timestamp (seconds since epoch) for the future time + """ + # Handle "in X time" format + in_match = re.match(r'in\s+(.+)', time_str, re.IGNORECASE) + if in_match: + time_part = in_match.group(1) + # Convert to format our parse_time can handle + time_part = time_part.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) + + # If not a relative time, try to parse as a specific date/time + # For simplicity, returning None for now + return None + +def create_discord_timestamp(unix_time, format_code='F'): + """ + Create a Discord timestamp string + + Args: + unix_time: Unix timestamp (seconds since epoch) + format_code: Discord timestamp format code + F: Full date and time (default) + R: Relative time + t: Short time (HH:MM) + T: Long time (HH:MM:SS) + d: Short date (MM/DD/YYYY) + D: Long date (Month DD, YYYY) + + Returns: + Discord timestamp string + """ + return f"" + +async def run(client, message, args): + """ + Create a Discord timestamp from a natural language time description + + Usage: .timestamp in 2 hours + .timestamp in 30 minutes R + """ + if not args: + await message.channel.send("Usage: `.timestamp in X hours/minutes/days [format]`\nFormats: F (full), R (relative), t (short time), T (long time), d (short date), D (long date)") + return + + # Check if the last argument is a format code + format_code = 'F' # Default format + if len(args) > 1 and args[-1] in ['F', 'R', 't', 'T', 'd', 'D']: + format_code = args[-1] + time_str = ' '.join(args[:-1]) + else: + time_str = ' '.join(args) + + # Parse the time + unix_time = parse_relative_time(time_str) + + if unix_time: + timestamp = create_discord_timestamp(unix_time, format_code) + # Send the timestamp so user can copy it + await message.channel.send(f"Discord timestamp: `{timestamp}`\nPreview: {timestamp}") + else: + await message.channel.send("I couldn't understand that time format. Try something like 'in 2 hours' or 'in 30 minutes'.") \ No newline at end of file diff --git a/bot/handlers/message_handler.py b/bot/handlers/message_handler.py index e0b171f..20b0f9c 100644 --- a/bot/handlers/message_handler.py +++ b/bot/handlers/message_handler.py @@ -1,11 +1,14 @@ 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): @@ -24,7 +27,68 @@ class MessageHandler: 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+(?:hour|hours|minute|minutes|day|days|second|seconds)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"" + + 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: diff --git a/utils/time_parser.py b/utils/time_parser.py index 5b3e715..eaec55a 100644 --- a/utils/time_parser.py +++ b/utils/time_parser.py @@ -1,6 +1,7 @@ import re -time_regex = re.compile(r'(\d+)([smhd])') # Matches 4m2s, 1h30m, etc. +# Define the time_regex that was missing +time_regex = re.compile(r'(\d+)([smhd])') def parse_time(time_str): """