Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env.example

This file was deleted.

2 changes: 1 addition & 1 deletion cogs/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class NotificationsView(discord.ui.View):
def __init__(self, bot, categories):
super().__init__()
self.bot = bot

print(self.bot.guilds) # del this line (but keep empty)
for category in categories:
role = self.bot.guilds[0].get_role(category["role"])
self.add_item(RoleButton(role))
Expand Down
29 changes: 25 additions & 4 deletions cogs/reminders.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import discord
from discord.ext import commands, tasks
from datetime import datetime, timedelta
from random import choice
from string import ascii_lowercase, ascii_uppercase

from util import is_discord_member
from timeutil import UserFriendlyTime
Expand All @@ -19,7 +21,8 @@ async def remind_me(self, ctx, *, time: UserFriendlyTime):
user_id=ctx.author.id,
channel_id=ctx.channel.id,
message=message,
timestamp=time.dt
timestamp=time.dt,
key=''.join(choice(ascii_lowercase + ascii_uppercase, k=ctx.bot.config["reminder_key_length"]))
)
await ctx.reply(f"{ctx.author.mention}: I will remind you at {time.dt.strftime('%Y-%m-%d %H:%M:%S')} UTC with the message: {message}")

Expand All @@ -32,9 +35,9 @@ async def my_reminders(self, ctx):
return await ctx.reply(f"{ctx.author.display_name}: You have no reminders set.")
elif len(reminders) < 25:
embed = discord.Embed(title=f"{ctx.author.display_name}'s Reminders", color=discord.Color.blue())
for message, _, timestamp in reminders:
for message, _, timestamp, key in reminders:
embed.add_field(
name=f"Reminder at {timestamp.strftime('%Y-%m-%d %H:%M:%S')}",
name=f"Reminder at {timestamp.strftime('%Y-%m-%d %H:%M:%S')}; key={key}",
value=f"Message: {message}",
inline=False
)
Expand All @@ -53,5 +56,23 @@ async def check_reminders(self):
# If the bot cannot send messages to the channel, skip it
continue

@is_discord_member()
@commands.command(name='delete_reminder', aliased=['delreminder'])
async def delete_reminder(self, ctx, *, key: str) -> None:
"""Delete all reminders of the user with the given key."""
for char in key:
if not char in ascii_lowercase + ascii_uppercase:
return await ctx.reply(f"{ctx.author.display_name}: Key contains non alphabetical characters.")

reminders = await self.bot.database.get_reminders(ctx.author.id)
if not reminders:
return await ctx.reply(f"{ctx.author.display_name}: You have no reminders to delete.")

if not any(reminder[3] == key for reminder in reminders):
return await ctx.reply(f"{ctx.author.display_name}: {key} not valid for any of your reminders.")

await self.bot.database.delete_reminder(user_id=ctx.author.id, key=key)
await ctx.reply(f"{ctx.author.mention}: Reminder deleted successfully.")

async def setup(bot):
await bot.add_cog(Reminders(bot))
await bot.add_cog(Reminders(bot))
4 changes: 4 additions & 0 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ fractalDeets:
maxIterations: 10000
messiness: 30
zoom: 3.5
spirographDeets:
height: 2000
width: 2000
length: 1000
automod_regexes:
- "^test(ing)?$"
- "f[0o]+"
Expand Down
27 changes: 20 additions & 7 deletions database.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ async def connect(self):
user_id INTEGER,
channel_id INTEGER,
message TEXT,
timestamp DATETIME
timestamp DATETIME,
key TEXT
)"""
)
await cursor.execute(
Expand Down Expand Up @@ -224,7 +225,7 @@ async def get_timers(self, user_id):
await self.connection.commit()
return rows

async def add_reminder(self, user_id, channel_id, message, timestamp):
async def add_reminder(self, *, user_id, channel_id, message, timestamp, key: str):
"""Add a reminder for a user. The reminder is stored in the database with the user's ID, message, and timestamp.

Args:
Expand All @@ -234,11 +235,11 @@ async def add_reminder(self, user_id, channel_id, message, timestamp):
timestamp (datetime): The time when the reminder should be triggered
"""
async with self.connection.cursor() as cur:
query = "INSERT INTO reminders(user_id, channel_id, message, timestamp) VALUES(?, ?, ?, ?)"
await cur.execute(query, (user_id, channel_id, message, timestamp))
query = "INSERT INTO reminders(user_id, channel_id, message, timestamp, key) VALUES(?, ?, ?, ?, \)"
await cur.execute(query, (user_id, channel_id, message, timestamp, key))
await self.connection.commit()

async def get_reminders(self, user_id):
async def get_reminders(self, user_id) -> list[tuple[str, str, str, str]]: # I suppose the DB just returns strings and not Python objects
"""Get all reminders for a user. The reminders are returned as a list of tuples with the message and timestamp of each reminder.

Args:
Expand All @@ -248,7 +249,7 @@ async def get_reminders(self, user_id):
list: A list of tuples with the message, channel and timestamp of each reminder
"""
async with self.connection.cursor() as cur:
query = "SELECT message, channel_id, timestamp FROM reminders WHERE user_id = ?"
query = "SELECT message, channel_id, timestamp, key FROM reminders WHERE user_id = ?"
await cur.execute(query, (user_id,))
rows = await cur.fetchall()
return rows
Expand All @@ -261,7 +262,19 @@ async def pop_expired_reminders(self):
rows = await cur.fetchall()
await self.connection.commit()
return rows


async def delete_reminder(self, *, user_id, key: str) -> None:
"""Remove reminder from the user, filtered by key, from the database.

Args:
user_id (int): The id of the user wanting to delete a reminder
key (str): The key we use to filter out the reminder
"""
async with self.connection.cursor() as cur:
query = "DELETE FROM reminders WHERE user_id = ? AND key = ? RETURNING message"
await cur.execute(query, (user_id, key))
await self.connection.commit()

async def add_tempban(self, user_id, reason, timestamp):
"""Add a temporary ban for a user. The ban is stored in the database with the user's ID, reason, and expiration time.

Expand Down
Empty file added latest.log
Empty file.