From da2ca4cfec1039861e952b750fad01122a85dbd5 Mon Sep 17 00:00:00 2001 From: w Date: Sun, 1 Jun 2025 18:08:51 -0300 Subject: [PATCH 1/6] Split get_or_create_user --- bot/db_utils.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/bot/db_utils.py b/bot/db_utils.py index daff8c5..6f94cc8 100644 --- a/bot/db_utils.py +++ b/bot/db_utils.py @@ -28,21 +28,19 @@ def get_random_character(): return chosen['id'], chosen['name'], chosen['file_id'], chosen['rarity'] -def get_or_create_user(username): - '''Retrieves an ID for a given user, if the user does not exist, it will be - created.''' +def get_player(username): + '''Retrieve a player ID by username, or return None if not found.''' CURSOR.execute('SELECT id FROM users WHERE username = ?', (username,)) user = CURSOR.fetchone() - if user: - return user[0] + return user[0] if user else None - # New user starts with has_rolled = False +def insert_player(username): + '''Insert a new player with default has_rolled = False and return their user ID.''' CURSOR.execute( 'INSERT INTO users (username, has_rolled) VALUES (?, ?)', (username, False) ) - user_id = CURSOR.lastrowid - return user_id + return CURSOR.lastrowid def insert_character(name: str, rarity: int, weight: float, file_id: str) -> int: '''Inserts a character''' From a0ed6ded41c0ef242040d6dda40b5c220d98d15f Mon Sep 17 00:00:00 2001 From: w Date: Sun, 1 Jun 2025 22:03:37 -0300 Subject: [PATCH 2/6] adding signup command --- bot/response.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/bot/response.py b/bot/response.py index ea0abe5..3d0a348 100644 --- a/bot/response.py +++ b/bot/response.py @@ -1,12 +1,14 @@ from datetime import datetime, timedelta, timezone -from db_utils import get_or_create_user, insert_pull, get_last_rolled_at, get_random_character +from db_utils import get_player, insert_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_or_create_user(full_user) + 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) @@ -43,6 +45,16 @@ def do_roll(full_user): 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: @@ -96,5 +108,7 @@ def generate_response(parsed_command): return do_create(full_user, arguments, note_obj) case 'help': return do_help(command) + case 'signup': + return do_signup(full_user) case _: return None From dce2c9072b3187c7fa4ce88fa3036a6fe07ae612 Mon Sep 17 00:00:00 2001 From: w Date: Sun, 1 Jun 2025 23:25:18 -0300 Subject: [PATCH 3/6] account deletion --- bot/db_utils.py | 28 ++++++++++++++++++++++++++++ bot/response.py | 24 +++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/bot/db_utils.py b/bot/db_utils.py index 6f94cc8..a9f3f06 100644 --- a/bot/db_utils.py +++ b/bot/db_utils.py @@ -42,6 +42,34 @@ def insert_player(username): ) return CURSOR.lastrowid +def delete_player(username): + '''Permanently deletes a user and all their pulls.''' + CURSOR.execute( + 'SELECT id FROM users WHERE username = ?', + (username,) + ) + user = CURSOR.fetchone() + + if not user: + return False # No such user + + user_id = user[0] + + # Delete pulls + CURSOR.execute( + 'DELETE FROM pulls WHERE user_id = ?', + (user_id,) + ) + + # Delete user + CURSOR.execute( + 'DELETE FROM users WHERE id = ?', + (user_id,) + ) + + return True + + def insert_character(name: str, rarity: int, weight: float, file_id: str) -> int: '''Inserts a character''' CURSOR.execute( diff --git a/bot/response.py b/bot/response.py index 3d0a348..85a4073 100644 --- a/bot/response.py +++ b/bot/response.py @@ -1,5 +1,5 @@ from datetime import datetime, timedelta, timezone -from db_utils import get_player, insert_player, insert_pull, get_last_rolled_at, get_random_character +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 @@ -94,7 +94,25 @@ def do_help(full_user): 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 @@ -110,5 +128,9 @@ def generate_response(parsed_command): 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 From b7d82d9117330ba9a303d5b13d5a4d5e032d3972 Mon Sep 17 00:00:00 2001 From: w Date: Mon, 2 Jun 2025 00:37:39 -0300 Subject: [PATCH 4/6] fix --- bot/db_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/db_utils.py b/bot/db_utils.py index 88660d9..5597bc5 100644 --- a/bot/db_utils.py +++ b/bot/db_utils.py @@ -44,7 +44,7 @@ def get_player(username: str) -> int: if user: return int(user[0]) -def insert_player(username): +def insert_player(username: str) -> int: '''Insert a new player with default has_rolled = False and return their user ID.''' CURSOR.execute( 'INSERT INTO users (username, has_rolled) VALUES (?, ?)', @@ -52,7 +52,7 @@ def insert_player(username): ) return CURSOR.lastrowid -def delete_player(username): +def delete_player(username: str) -> bool: '''Permanently deletes a user and all their pulls.''' CURSOR.execute( 'SELECT id FROM users WHERE username = ?', From 3a09b481e520dcb3271729de626a41a0bb82edfa Mon Sep 17 00:00:00 2001 From: w Date: Mon, 2 Jun 2025 01:03:06 -0300 Subject: [PATCH 5/6] more fixes --- bot/response.py | 50 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/bot/response.py b/bot/response.py index 17a12dd..6966d1e 100644 --- a/bot/response.py +++ b/bot/response.py @@ -7,12 +7,14 @@ from config import GACHA_ROLL_INTERVAL from custom_types import BotResponse, ParsedNotification -def do_roll(full_user: str) -> BotResponse: +def do_roll(author: str) -> BotResponse: '''Determines whether the user can roll, then pulls a random character''' - user_id = get_player(full_user) - + user_id = get_player(author) if not user_id: - return f'@{full_user} 🛑 You haven’t signed up yet! Use the `signup` command to start playing.' + return { + 'message':f'{author} 🛑 You haven’t signed up yet! Use the `signup` command to start playing.', + 'attachment_urls': None + } # Get date of user's last roll date = get_last_rolled_at(user_id) @@ -38,7 +40,7 @@ def do_roll(full_user: str) -> BotResponse: remaining_duration = f'{duration.seconds} seconds' return { - 'message': f'{full_user} ⏱️ Please wait another \ + 'message': f'{author} ⏱️ Please wait another \ {remaining_duration} before rolling again.', 'attachment_urls': None } @@ -47,7 +49,7 @@ def do_roll(full_user: str) -> BotResponse: if not character: return { - 'message': f'{full_user} Uwaaa... something went wrong! No \ + 'message': f'{author} Uwaaa... something went wrong! No \ characters found. 😿', 'attachment_urls': None } @@ -55,7 +57,7 @@ characters found. 😿', insert_pull(user_id, character['id']) stars = '⭐️' * character['rarity'] return { - 'message': f'@{full_user} 🎲 Congrats! You rolled {stars} \ + 'message': f'{author} 🎲 Congrats! You rolled {stars} \ **{character['name']}**\nShe\'s all yours now~ 💖✨', 'attachment_urls': [character['image_url']] } @@ -66,13 +68,13 @@ def do_signup(author: str) -> BotResponse: if user_id: return { - f'@{author} 👀 You’re already signed up! Let the rolling begin~ 🎲', + 'message':f'{author} 👀 You’re already signed up! Let the rolling begin~ 🎲', 'attachment_urls': None } new_user_id = insert_player(author) return { - 'message': f'@{author} ✅ Signed up successfully! Your gacha destiny begins now... ✨ Use the roll command to start!', + 'message': f'{author} ✅ Signed up successfully! Your gacha destiny begins now... ✨ Use the roll command to start!', 'attachment_urls': None } @@ -86,7 +88,7 @@ def is_float(val: Any) -> bool: def do_create( - full_user: str, + author: str, arguments: List[str], note_obj: Dict[str, Any]) -> BotResponse: '''Creates a character''' @@ -96,27 +98,27 @@ def do_create( if not image_url: return { - 'message': f'{full_user} You need an image to create a character, \ + 'message': f'{author} You need an image to create a character, \ dumbass.', 'attachment_urls': None } if len(arguments) != 3: return { - 'message': f'{full_user} Please specify the following attributes \ + 'message': f'{author} Please specify the following attributes \ in order: name, rarity, drop weighting', 'attachment_urls': None } if not (arguments[1].isnumeric() and 1 <= int(arguments[1]) <= 5): return { - 'message': f'{full_user} Invalid rarity: \'{arguments[1]}\' must \ + 'message': f'{author} Invalid rarity: \'{arguments[1]}\' must \ be a number between 1 and 5', 'attachment_urls': None } if not (is_float(arguments[2]) and 0.0 < float(arguments[2]) <= 1.0): return { - 'message': f'{full_user} Invalid drop weight: \'{arguments[2]}\' \ + 'message': f'{author} Invalid drop weight: \'{arguments[2]}\' \ must be a decimal value between 0.0 and 1.0', 'attachment_urls': None } @@ -128,7 +130,7 @@ must be a decimal value between 0.0 and 1.0', image_url=image_url ) return { - 'message': f'{full_user} Added {arguments[0]}, ID {character_id}.', + 'message': f'{author} Added {arguments[0]}, ID {character_id}.', 'attachment_urls': [file_id] } @@ -136,7 +138,7 @@ must be a decimal value between 0.0 and 1.0', def do_help(author: str) -> BotResponse: '''Provides a list of commands that the bot can do.''' return { - 'message':f'{full_user} Here\'s what I can do:\n \ + 'message':f'{author} Here\'s what I can do:\n \ - `roll` Pulls a random character.\ - `create ` Creates a character using a given image.\ - `signup` Registers your account.\ @@ -147,7 +149,7 @@ def do_help(author: str) -> BotResponse: def delete_account(author: str) -> BotResponse: return { - 'message':f'@{author} ⚠️ This will permanently delete your account and all your cards.\n' + 'message':f'{author} ⚠️ 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... 💀✨', 'attachment_urls': None @@ -164,7 +166,7 @@ def confirm_delete(author: str) -> BotResponse: } return { - 'message':f'@{author} 🧼 Your account and all your cards have been deleted. RIP your gacha history 🕊️✨', + 'message':f'{author} 🧼 Your account and all your cards have been deleted. RIP your gacha history 🕊️✨', 'attachment_urls': None } @@ -177,7 +179,7 @@ def generate_response(notification: ParsedNotification) -> BotResponse | None: res: BotResponse | None = None # TODO: Check if the user has an account author = notification['author'] - user_id = get_or_create_user(author) + user_id = get_player(author) command = notification['command'] # Check if the user is an administrator # user_is_administrator = user_is_administrator() @@ -185,11 +187,11 @@ def generate_response(notification: ParsedNotification) -> BotResponse | None: # Unrestricted commands match command: case 'signup': - res = do_signup() + res = do_signup(author) case 'help': res = do_help(author) - - + case 'roll': + res = do_roll(author) case _: pass @@ -198,10 +200,6 @@ def generate_response(notification: ParsedNotification) -> BotResponse | None: # User commands match command: - case 'delete_account': - pass - case 'roll': - res = do_roll(author) case 'create': res = do_create( author, From 3de6a9ac3dd47bcf4c3e99f080149784066587e6 Mon Sep 17 00:00:00 2001 From: w Date: Tue, 3 Jun 2025 23:23:42 -0300 Subject: [PATCH 6/6] remove unused parts of the code --- bot/db_utils.py | 3 --- bot/response.py | 9 ++------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/bot/db_utils.py b/bot/db_utils.py index 5597bc5..bf4b25f 100644 --- a/bot/db_utils.py +++ b/bot/db_utils.py @@ -60,9 +60,6 @@ def delete_player(username: str) -> bool: ) user = CURSOR.fetchone() - if not user: - return False # No such user - user_id = user[0] # Delete pulls diff --git a/bot/response.py b/bot/response.py index 6966d1e..bd56f20 100644 --- a/bot/response.py +++ b/bot/response.py @@ -157,13 +157,8 @@ def delete_account(author: str) -> BotResponse: } def confirm_delete(author: str) -> BotResponse: - success = delete_player(author) - - if not success: - return { - 'message':f'@{author} ❌ No account found to delete. Maybe it’s already gone?', - 'attachment_urls': None - } + + delete_player(author) return { 'message':f'{author} 🧼 Your account and all your cards have been deleted. RIP your gacha history 🕊️✨',