DOC: Added *.db to the .gitignore to prevent any data from being shared.

FEAT: Updated code to start following GDPR compliance.
This commit is contained in:
Dan 2024-06-19 09:29:16 -04:00
parent 19b48dd67d
commit 27b051f9eb
4 changed files with 92 additions and 8 deletions

1
.gitignore vendored
View File

@ -160,3 +160,4 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
*.db

View File

@ -5,16 +5,40 @@ import aiosqlite
import os import os
import sys import sys
import subprocess import subprocess
from gdpr import check_consent, give_consent, revoke_consent
class ModCommands(commands.Cog): class ModCommands(commands.Cog):
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
@app_commands.command(name="consent",
description="Give consent to store data")
async def consent(self, interaction: discord.Interaction):
await give_consent(interaction.user.id)
await interaction.response.send_message(
"Consent given to store your data."
)
@app_commands.command(name="revoke_consent",
description="Revoke consent to store data")
async def revoke_consent(self, interaction: discord.Interaction):
await revoke_consent(interaction.user.id)
await interaction.response.send_message(
"Consent revoked and your data has been deleted."
)
@app_commands.command(name="addnote", @app_commands.command(name="addnote",
description="Add a note to a user and/or add strikes") # noqa: E501 description="Add a note to a user and optionally "
"add strikes")
async def add_note(self, interaction: discord.Interaction, async def add_note(self, interaction: discord.Interaction,
user: discord.User, note: str, strikes: int = 0): user: discord.User, note: str, strikes: int = 0):
if not await check_consent(user.id):
await interaction.response.send_message(
f"{user.name} has not given consent to store data."
)
return
async with aiosqlite.connect("ariella.db") as db: async with aiosqlite.connect("ariella.db") as db:
cursor = await db.execute( cursor = await db.execute(
"SELECT notes, strikes FROM user_notes WHERE user_id = ?", "SELECT notes, strikes FROM user_notes WHERE user_id = ?",
@ -40,9 +64,16 @@ class ModCommands(commands.Cog):
f"Note added for {user.name}: {note}. Strikes: {strikes}" f"Note added for {user.name}: {note}. Strikes: {strikes}"
) )
@app_commands.command(name="warn", description="Warn a user") @app_commands.command(name="warn",
description="Warn a user")
async def warn_user(self, interaction: discord.Interaction, async def warn_user(self, interaction: discord.Interaction,
user: discord.User, reason: str): user: discord.User, reason: str):
if not await check_consent(user.id):
await interaction.response.send_message(
f"{user.name} has not given consent to store data."
)
return
async with aiosqlite.connect("ariella.db") as db: async with aiosqlite.connect("ariella.db") as db:
cursor = await db.execute( cursor = await db.execute(
"SELECT strikes FROM user_notes WHERE user_id = ?", "SELECT strikes FROM user_notes WHERE user_id = ?",
@ -64,18 +95,24 @@ class ModCommands(commands.Cog):
) )
await db.commit() await db.commit()
await interaction.response.send_message( await interaction.response.send_message(
f"User {user.name} warned for: {reason}." f"User {user.name} warned for: {reason}. They now have {strikes} "
f"They now have {strikes} strikes." f"strikes."
) )
await user.send( await user.send(
f"You have been warned for: {reason}." f"You have been warned for: {reason}. You now have {strikes} "
f"You now have {strikes} strikes." f"strikes."
) )
@app_commands.command(name="removestrikes", @app_commands.command(name="removestrikes",
description="Remove strikes from a user") description="Remove strikes from a user")
async def remove_strikes(self, interaction: discord.Interaction, async def remove_strikes(self, interaction: discord.Interaction,
user: discord.User, strikes: int): user: discord.User, strikes: int):
if not await check_consent(user.id):
await interaction.response.send_message(
f"{user.name} has not given consent to store data."
)
return
async with aiosqlite.connect("ariella.db") as db: async with aiosqlite.connect("ariella.db") as db:
cursor = await db.execute( cursor = await db.execute(
"SELECT strikes FROM user_notes WHERE user_id = ?", "SELECT strikes FROM user_notes WHERE user_id = ?",
@ -102,6 +139,12 @@ class ModCommands(commands.Cog):
description="Check notes and strikes of a user") description="Check notes and strikes of a user")
async def check_notes(self, interaction: discord.Interaction, async def check_notes(self, interaction: discord.Interaction,
user: discord.User): user: discord.User):
if not await check_consent(user.id):
await interaction.response.send_message(
f"{user.name} has not given consent to store data."
)
return
async with aiosqlite.connect("ariella.db") as db: async with aiosqlite.connect("ariella.db") as db:
cursor = await db.execute( cursor = await db.execute(
"SELECT notes, strikes FROM user_notes WHERE user_id = ?", "SELECT notes, strikes FROM user_notes WHERE user_id = ?",
@ -130,7 +173,8 @@ class ModCommands(commands.Cog):
await interaction.followup.send("Restarting the bot...") await interaction.followup.send("Restarting the bot...")
os.execv(sys.executable, ['python'] + sys.argv) os.execv(sys.executable, ['python'] + sys.argv)
@app_commands.command(name="help", description="List all commands") @app_commands.command(name="help",
description="List all commands")
async def help_command(self, interaction: discord.Interaction): async def help_command(self, interaction: discord.Interaction):
commands = self.bot.tree.walk_commands() commands = self.bot.tree.walk_commands()
help_text = "Here are the available commands:\n" help_text = "Here are the available commands:\n"

33
gdpr.py Normal file
View File

@ -0,0 +1,33 @@
import aiosqlite
async def check_consent(user_id: int) -> bool:
async with aiosqlite.connect("ariella.db") as db:
cursor = await db.execute(
"SELECT consent FROM user_consent WHERE user_id = ?",
(user_id,)
)
row = await cursor.fetchone()
return row and row[0] == 1
async def give_consent(user_id: int):
async with aiosqlite.connect("ariella.db") as db:
await db.execute(
"INSERT OR REPLACE INTO user_consent (user_id, consent) VALUES (?, ?)", # noqa: E501
(user_id, 1)
)
await db.commit()
async def revoke_consent(user_id: int):
async with aiosqlite.connect("ariella.db") as db:
await db.execute(
"DELETE FROM user_consent WHERE user_id = ?",
(user_id,)
)
await db.execute(
"DELETE FROM user_notes WHERE user_id = ?",
(user_id,)
)
await db.commit()

View File

@ -9,8 +9,8 @@ from dotenv import load_dotenv
load_dotenv() load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD_ID = int(os.getenv('GUILD_ID')) GUILD_ID = int(os.getenv('GUILD_ID'))
TOKEN = os.getenv('DISCORD_TOKEN')
intents = discord.Intents.default() intents = discord.Intents.default()
intents.message_content = True intents.message_content = True
@ -40,6 +40,12 @@ async def init_db():
strikes INTEGER strikes INTEGER
) )
""") """)
await db.execute("""
CREATE TABLE IF NOT EXISTS user_consent (
user_id INTEGER PRIMARY KEY,
consent INTEGER
)
""")
await db.commit() await db.commit()