From c7791fc4aa16c31b559313cb3741d7ed84075d1a Mon Sep 17 00:00:00 2001 From: Dan Date: Sat, 4 May 2024 21:30:49 -0400 Subject: [PATCH] adding a consent requirement --- dolly/consent.py | 37 +++++++++++++++++++++++++++++++++++++ dolly/database.py | 8 +++++++- dolly/dolly.py | 28 +++++++++++++++++++++------- 3 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 dolly/consent.py diff --git a/dolly/consent.py b/dolly/consent.py new file mode 100644 index 0000000..2cf99bb --- /dev/null +++ b/dolly/consent.py @@ -0,0 +1,37 @@ +import discord +from discord.ui import View, Button +import aiosqlite + +DATABASE = "dolly.db" + +class ConsentView(View): + def __init__(self): + super().__init__() + self.value = None + + @discord.ui.button(label="Consent to Data Storage", style=discord.ButtonStyle.green) + async def confirm(self, interaction: discord.Interaction, button: Button): + self.value = True + await interaction.response.send_message("Thank you for consenting to data storage!", ephemeral=True) + self.stop() + + @discord.ui.button(label="Decline", style=discord.ButtonStyle.grey) + async def cancel(self, interaction: discord.Interaction, button: Button): + self.value = False + await interaction.response.send_message("You have declined data storage. You cannot use this bot without consenting.", ephemeral=True) + self.stop() + + +async def check_user_consent(user_id): + """Check if the user has given consent to data storage.""" + async with aiosqlite.connect(DATABASE) as db: + cursor = await db.execute("SELECT consent_given FROM user_consents WHERE user_id = ?", (user_id,)) + result = await cursor.fetchone() + return result[0] if result else False + +async def store_user_consent(user_id): + """Store the user's consent to data storage.""" + async with aiosqlite.connect(DATABASE) as db: + await db.execute("INSERT OR REPLACE INTO user_consents (user_id, consent_given) VALUES (?, TRUE)", (user_id,)) + await db.commit() + diff --git a/dolly/database.py b/dolly/database.py index 8102045..d071634 100644 --- a/dolly/database.py +++ b/dolly/database.py @@ -22,6 +22,12 @@ async def init_db(): priority TEXT, FOREIGN KEY(project_id) REFERENCES projects(id))''' ) + await db.execute( + '''CREATE TABLE IF NOT EXISTS user_consents( + user_id INTEGER PRIMARY KEY, + consent_given BOOLEAN NOT NULL + )''' + ) await db.commit() async def add_project(name, description): @@ -47,7 +53,7 @@ async def add_task_to_project(project_id, description, assignee, deadline, statu # Change the date format to MM/DD/YYYY deadline_date = datetime.strptime(deadline, "%m/%d/%Y").date() await db.execute("INSERT INTO tasks(project_id, description, assignee, deadline, status, priority) VALUES(?, ?, ?, ?, ?, ?)", - (project_id, description, assignee, deadline_date, status, priority)) + (project_id, description, assignee, deadline_date, status, priority)) await db.commit() async def update_task(task_id, description, assignee, deadline, status, priority): diff --git a/dolly/dolly.py b/dolly/dolly.py index ad5cff1..d9044f8 100644 --- a/dolly/dolly.py +++ b/dolly/dolly.py @@ -1,25 +1,23 @@ import discord from discord import app_commands from .commands import DollyTracker +from .consent import ConsentView, check_user_consent, store_user_consent from dotenv import load_dotenv import os load_dotenv() GUILD_ID = int(os.getenv("DISCORD_GUILD_ID")) -OWNER_ID = int(os.getenv("AUTHORIZED_USER_ID")) # Ensure your .env has your Discord user ID +OWNER_ID = int(os.getenv("AUTHORIZED_USER_ID")) class Dolly(discord.Client): - def __init__(self): super().__init__(intents=discord.Intents.default()) self.tree = app_commands.CommandTree(self) - + async def setup_hook(self): self.tree.add_command(DollyTracker()) - self.tree.copy_global_to(guild = discord.Object(id=GUILD_ID)) await self.tree.sync(guild=discord.Object(id=GUILD_ID)) - # Adding a guild-specific shutdown command @self.tree.command(name="shutdown", description="Shut down the bot", guild=discord.Object(id=GUILD_ID)) async def shutdown(interaction: discord.Interaction): if interaction.user.id == OWNER_ID: @@ -30,6 +28,22 @@ class Dolly(discord.Client): async def on_ready(self): print(f"Logged on as {self.user}!") - # Ensuring commands are only available in specified guild self.tree.copy_global_to(guild=discord.Object(id=GUILD_ID)) - await self.tree.sync(guild=discord.Object(id=GUILD_ID)) \ No newline at end of file + await self.tree.sync(guild=discord.Object(id=GUILD_ID)) + + async def on_interaction(self, interaction: discord.Interaction): + if interaction.type == discord.InteractionType.application_command: + if not await check_user_consent(interaction.user.id): + view = ConsentView() + await interaction.response.send_message( + "By using this bot, you consent to the storage of your data necessary for functionality. Please confirm your consent.", + view=view, + ephemeral=True + ) + await view.wait() + if view.value: + await store_user_consent(interaction.user.id) + else: + # Optionally, handle the case where the user declines consent + await interaction.followup.send("You must consent to data storage to use this bot.", ephemeral=True) + return # Stop processing if they do not consent