from datetime import datetime, timedelta, timezone from db_utils import get_player, insert_player, delete_player, insert_pull, get_last_rolled_at, get_random_character from add_character import add_character from config import GACHA_ROLL_INTERVAL def do_roll(full_user): '''Determines whether the user can roll, then pulls a random character''' user_id = get_player(full_user) if not user_id: return f'@{full_user} 🛑 You haven’t signed up yet! Use the `signup` command to start playing.' # Get date of user's last roll date = get_last_rolled_at(user_id) # No date means it's users first roll if date: # SQLite timestamps returned by the DB are always in UTC # Below timestamps are to be converted to UTC prev = datetime.strptime(date + '+0000', '%Y-%m-%d %H:%M:%S%z') now = datetime.now(timezone.utc) time_since_last_roll = now - prev roll_interval = timedelta(seconds=GACHA_ROLL_INTERVAL) duration = roll_interval - time_since_last_roll # User needs to wait before they can roll again if time_since_last_roll < roll_interval: remaining_duration = None if duration.seconds > 3600: remaining_duration = f'{-(duration.seconds // -3600)} hours' elif duration.seconds > 60: remaining_duration = f'{-(duration.seconds // -60)} minutes' else: remaining_duration = f'{duration.seconds} seconds' return f'{full_user} ⏱️ Please wait another {remaining_duration} before rolling again.' character_id, character_name, file_id, rarity = get_random_character() if not character_id: return f'{full_user} Uwaaa... something went wrong! No characters found. 😿' insert_pull(user_id,character_id) stars = '⭐️' * rarity return([f"@{full_user} 🎲 Congrats! You rolled {stars} **{character_name}**\n\ She's all yours now~ 💖✨",[file_id]]) def do_signup(full_user): '''Registers a new user if they haven’t signed up yet.''' user_id = get_player(full_user) if user_id: return f'@{full_user} 👀 You’re already signed up! Let the rolling begin~ 🎲' new_user_id = insert_player(full_user) return f'@{full_user} ✅ Signed up successfully! Your gacha destiny begins now... ✨ Use the roll command to start!' def is_float(val): '''Returns true if `val` can be converted to a float''' try: float(val) return True except ValueError: return False def do_create(full_user, arguments, note_obj): '''Creates a character''' # Example call from bot logic image_url = note_obj.get('files', [{}])[0].get('url') if note_obj.get('files') else None if not image_url: return f'{full_user}{full_user} You need an image to create a character, dumbass.' if len(arguments) != 3: return '{full_user}Please specify the following attributes in order: \ name, rarity, drop weighting' if not (arguments[1].isnumeric() and 1 <= int(arguments[1]) <= 5): return f'{full_user}Invalid rarity: \'{arguments[1]}\' must be a number between 1 and 5' if not (is_float(arguments[2]) and 0.0 < float(arguments[2]) <= 1.0): return f'{full_user}Invalid drop weight: \'{arguments[2]}\' \ must be a decimal value between 0.0 and 1.0' character_id, file_id = add_character( name=arguments[0], rarity=int(arguments[1]), weight=float(arguments[2]), image_url=image_url ) return([f'{full_user}Added {arguments[0]}, ID {character_id}.',[file_id]]) def do_help(full_user): '''Provides a list of commands that the bot can do.''' return f'{full_user} Here\'s what I can do:\n \ - `roll` Pulls a random character.\ - `create ` Creates a character using a given image.\ - `signup` Registers your account.\ - `delete_account` Deletes your account.\ - `help` Shows this message' def delete_account(full_user): return ( f'@{full_user} ⚠️ This will permanently delete your account and all your cards.\n' 'If you’re sure, reply with `confirm_delete` to proceed.\n\n' '**There is no undo.** Your gacha luck will be lost to the void... 💀✨' ) def confirm_delete(full_user): success = delete_player(full_user) if not success: return f'@{full_user} ❌ No account found to delete. Maybe it’s already gone?' return f'@{full_user} 🧼 Your account and all your cards have been deleted. RIP your gacha history 🕊️✨' def generate_response(parsed_command): '''Given a command with arguments, processes the game state and returns a response''' command, full_user, arguments, note_obj = parsed_command match command: case 'roll': return do_roll(full_user) case 'create': return do_create(full_user, arguments, note_obj) case 'help': return do_help(command) case 'signup': return do_signup(full_user) case 'delete_account': return delete_account(full_user) case 'confirm_delete': return confirm_delete(full_user) case _: return None