From e39833a98bc47119eed414e0994ea30f5e639ab2 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 28 Jun 2024 14:01:48 -0400 Subject: [PATCH] FIX: Made the currency and xp guild-based now --- modules/user/currency.py | 100 +++++++++++---------------- modules/user/xp.py | 141 +++++++++++++++------------------------ 2 files changed, 93 insertions(+), 148 deletions(-) diff --git a/modules/user/currency.py b/modules/user/currency.py index 68e3b7b..77b6572 100644 --- a/modules/user/currency.py +++ b/modules/user/currency.py @@ -1,79 +1,59 @@ +# currency.py import discord from discord import app_commands -import random import sqlite3 -from datetime import datetime, timedelta +import random class Currency: def __init__(self, bot): self.bot = bot self.db_path = 'data/selena.db' - self._init_db() - self.cooldowns = {} - - def _init_db(self): - with sqlite3.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute(''' - CREATE TABLE IF NOT EXISTS users ( - user_id TEXT PRIMARY KEY, - kibble INTEGER DEFAULT 0, - xp INTEGER DEFAULT 0, - level INTEGER DEFAULT 1 - ) - ''') - conn.commit() - - def _get_user_kibble(self, user_id): - with sqlite3.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute('SELECT kibble FROM users WHERE user_id = ?', (user_id,)) - row = cursor.fetchone() - return row[0] if row else 0 - - def _update_user_kibble(self, user_id, amount): - with sqlite3.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute('INSERT OR IGNORE INTO users (user_id, kibble) VALUES (?, ?)', (user_id, 0)) - cursor.execute('UPDATE users SET kibble = kibble + ? WHERE user_id = ?', (amount, user_id)) - conn.commit() async def earn_kibble(self, interaction: discord.Interaction): + guild_id = str(interaction.guild_id) user_id = str(interaction.user.id) - now = datetime.utcnow() + earned = random.randint(1, 10) + + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + cursor.execute(""" + INSERT INTO guild_currency (guild_id, user_id, balance) + VALUES (?, ?, ?) + ON CONFLICT(guild_id, user_id) + DO UPDATE SET balance = balance + ? + """, (guild_id, user_id, earned, earned)) + conn.commit() + cursor.execute("SELECT balance FROM guild_currency WHERE guild_id = ? AND user_id = ?", (guild_id, user_id)) + balance = cursor.fetchone()[0] + conn.close() - if user_id in self.cooldowns: - if now < self.cooldowns[user_id]: - retry_after = (self.cooldowns[user_id] - now).total_seconds() - await interaction.response.send_message( - f'{interaction.user.mention}, you are on a cooldown. Please wait {retry_after:.2f} seconds before using this command again.', - ephemeral=True - ) - return - - self.cooldowns[user_id] = now + timedelta(seconds=30) - amount = random.choices([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100], [0.01, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0.01])[0] - self._update_user_kibble(user_id, amount) - await interaction.response.send_message(f'{interaction.user.mention} earned {amount} Kibble!') + await interaction.response.send_message(f"You earned {earned} Kibble! You now have {balance} Kibble.", ephemeral=False) async def balance(self, interaction: discord.Interaction): + guild_id = str(interaction.guild_id) user_id = str(interaction.user.id) - balance = self._get_user_kibble(user_id) - await interaction.response.send_message(f'{interaction.user.mention} has {balance} Kibble.') - def setup(self, tree): - tree.add_command(app_commands.Command( - name='earn_kibble', - description='Earn Kibble', - callback=self.earn_kibble - )) - tree.add_command(app_commands.Command( - name='balance', - description='Check your Kibble balance', - callback=self.balance - )) + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + cursor.execute("SELECT balance FROM guild_currency WHERE guild_id = ? AND user_id = ?", (guild_id, user_id)) + result = cursor.fetchone() + conn.close() + balance = result[0] if result else 0 + await interaction.response.send_message(f"You have {balance} Kibble.", ephemeral=False) -def setup(bot): - bot.tree.add_cog(Currency(bot)) + def setup(self, tree: app_commands.CommandTree): + @tree.command(name="earn_kibble", description="Earn Kibble currency") + async def earn_kibble_command(interaction: discord.Interaction): + await self.earn_kibble(interaction) + + @tree.command(name="balance", description="Check your Kibble balance") + async def balance_command(interaction: discord.Interaction): + await self.balance(interaction) + + if not tree.get_command("earn_kibble"): + tree.add_command(earn_kibble_command) + + if not tree.get_command("balance"): + tree.add_command(balance_command) diff --git a/modules/user/xp.py b/modules/user/xp.py index 512865b..0e0ab02 100644 --- a/modules/user/xp.py +++ b/modules/user/xp.py @@ -1,107 +1,72 @@ +# xp.py import discord from discord import app_commands -from datetime import datetime, timedelta import sqlite3 +import random class XP: def __init__(self, bot): self.bot = bot self.db_path = 'data/selena.db' - self._init_db() - self.cooldowns = {} - def _init_db(self): - with sqlite3.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute(''' - CREATE TABLE IF NOT EXISTS users ( - user_id TEXT PRIMARY KEY, - kibble INTEGER DEFAULT 0, - xp INTEGER DEFAULT 0, - level INTEGER DEFAULT 1 - ) - ''') - conn.commit() - - def _get_user_xp(self, user_id): - with sqlite3.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute('SELECT xp, level FROM users WHERE user_id = ?', (user_id,)) - row = cursor.fetchone() - return row if row else (0, 1) - - def _update_user_xp(self, user_id, xp): - with sqlite3.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute('INSERT OR IGNORE INTO users (user_id, xp, level) VALUES (?, ?, ?)', (user_id, 0, 1)) - cursor.execute('UPDATE users SET xp = xp + ? WHERE user_id = ?', (xp, user_id)) - conn.commit() - - def _update_user_level(self, user_id, level): - with sqlite3.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute('UPDATE users SET level = ? WHERE user_id = ?', (level, user_id)) - conn.commit() - - def xp_needed_for_next_level(self, level): - return 5 * (level ** 2) + 50 * level + 100 - - async def on_message(self, message): - if message.author.bot: - return - - user_id = str(message.author.id) - now = datetime.now() - - if user_id in self.cooldowns: - if now < self.cooldowns[user_id]: - return - - self.cooldowns[user_id] = now + timedelta(seconds=10) - - xp, level = self._get_user_xp(user_id) - self._update_user_xp(user_id, 10) - xp += 10 - - if xp >= self.xp_needed_for_next_level(level): + def calculate_level(self, xp): + level = 1 + while xp >= 5 * (level ** 2) + 50 * level + 100: level += 1 - self._update_user_level(user_id, level) - await message.channel.send(f'{message.author.mention} has leveled up to level {level}!') + return level - @app_commands.command(name='earn_xp', description='Manually earn XP (for testing)') - @app_commands.checks.cooldown(1, 10, key=lambda i: (i.user.id)) - async def earn_xp(self, interaction: discord.Interaction): + async def add_xp(self, interaction: discord.Interaction): + guild_id = str(interaction.guild_id) user_id = str(interaction.user.id) - xp, level = self._get_user_xp(user_id) - self._update_user_xp(user_id, 10) - xp += 10 + earned_xp = random.randint(5, 15) + + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + cursor.execute(""" + INSERT INTO guild_xp (guild_id, user_id, xp, level) + VALUES (?, ?, ?, 1) + ON CONFLICT(guild_id, user_id) + DO UPDATE SET xp = xp + ? + """, (guild_id, user_id, earned_xp, earned_xp)) + conn.commit() + cursor.execute("SELECT xp, level FROM guild_xp WHERE guild_id = ? AND user_id = ?", (guild_id, user_id)) + xp, level = cursor.fetchone() + new_level = self.calculate_level(xp) + if new_level > level: + cursor.execute("UPDATE guild_xp SET level = ? WHERE guild_id = ? AND user_id = ?", (new_level, guild_id, user_id)) + conn.commit() + conn.close() - if xp >= self.xp_needed_for_next_level(level): - level += 1 - self._update_user_level(user_id, level) - await interaction.response.send_message(f'{interaction.user.mention} has leveled up to level {level}!') + await interaction.response.send_message(f"You earned {earned_xp} XP! You now have {xp} XP and are level {new_level}.", ephemeral=False) + + async def check_xp(self, interaction: discord.Interaction): + guild_id = str(interaction.guild_id) + user_id = str(interaction.user.id) + + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + cursor.execute("SELECT xp, level FROM guild_xp WHERE guild_id = ? AND user_id = ?", (guild_id, user_id)) + result = cursor.fetchone() + conn.close() + + if result: + xp, level = result + await interaction.response.send_message(f"You have {xp} XP and are level {level}.", ephemeral=False) else: - await interaction.response.send_message(f'{interaction.user.mention} earned 10 XP!') + await interaction.response.send_message("You don't have any XP yet.", ephemeral=False) - @earn_xp.error - async def earn_xp_error(self, interaction: discord.Interaction, error: app_commands.AppCommandError): - if isinstance(error, app_commands.CommandOnCooldown): - await interaction.response.send_message(f'{interaction.user.mention}, you are on cooldown. Try again in {error.retry_after:.2f} seconds.', ephemeral=True) + def setup(self, tree: app_commands.CommandTree): + @tree.command(name="earn_xp", description="Earn XP") + async def earn_xp_command(interaction: discord.Interaction): + await self.add_xp(interaction) - @app_commands.command(name='check_progress', description='Check your XP progress towards the next level') - async def check_progress(self, interaction: discord.Interaction): - user_id = str(interaction.user.id) - xp, level = self._get_user_xp(user_id) - xp_needed = self.xp_needed_for_next_level(level) - xp_to_next_level = xp_needed - xp + @tree.command(name="check_xp", description="Check your XP and level") + async def check_xp_command(interaction: discord.Interaction): + await self.check_xp(interaction) - await interaction.response.send_message(f'{interaction.user.mention}, you need {xp_to_next_level} more XP to reach the next level.') + if not tree.get_command("earn_xp"): + tree.add_command(earn_xp_command) - def setup(self, tree): - tree.add_command(self.earn_xp) - tree.add_command(self.check_progress) - - -def setup(bot): - bot.tree.add_cog(XP(bot)) + if not tree.get_command("check_xp"): + tree.add_command(check_xp_command)