aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/cogs/reminders.py228
1 files changed, 73 insertions, 155 deletions
diff --git a/bot/cogs/reminders.py b/bot/cogs/reminders.py
index f6ed111dc..78f1cd73b 100644
--- a/bot/cogs/reminders.py
+++ b/bot/cogs/reminders.py
@@ -1,8 +1,9 @@
import asyncio
-import datetime
import logging
import random
import textwrap
+from datetime import datetime
+from operator import itemgetter
from aiohttp import ClientResponseError
from dateutil.relativedelta import relativedelta
@@ -13,6 +14,7 @@ from bot.constants import (
Channels, Icons, Keys, NEGATIVE_REPLIES,
POSITIVE_REPLIES, Roles, URLs
)
+from bot.converters import ExpirationDate
from bot.pagination import LinePaginator
from bot.utils.scheduling import Scheduler
from bot.utils.time import humanize_delta, parse_rfc1123, wait_until
@@ -28,24 +30,20 @@ class Reminders(Scheduler):
def __init__(self, bot: Bot):
self.bot = bot
- self.headers = {"X-API-Key": Keys.site_api}
super().__init__()
async def on_ready(self):
# Get all the current reminders for re-scheduling
- response = await self.bot.http_session.get(
- url=URLs.site_reminders_api,
- headers=self.headers
+ response = await self.bot.api_client.get(
+ 'bot/reminders',
+ params={'active': 'true'}
)
- response_data = await response.json()
-
- # Find the current time, timezone-aware.
- now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
+ now = datetime.utcnow()
loop = asyncio.get_event_loop()
- for reminder in response_data["reminders"]:
- remind_at = parse_rfc1123(reminder["remind_at"])
+ for reminder in response:
+ remind_at = datetime.fromisoformat(reminder['expiration'][:-1])
# If the reminder is already overdue ...
if remind_at < now:
@@ -56,32 +54,16 @@ class Reminders(Scheduler):
self.schedule_task(loop, reminder["id"], reminder)
@staticmethod
- async def _send_confirmation(ctx: Context, response: dict, on_success: str):
+ async def _send_confirmation(ctx: Context, on_success: str):
"""
- Send an embed confirming whether or not a change was made successfully.
-
- :return: A Boolean value indicating whether it failed (True) or passed (False)
+ Send an embed confirming the change was made successfully.
"""
embed = Embed()
-
- if not response.get("success"):
- embed.colour = Colour.red()
- embed.title = random.choice(NEGATIVE_REPLIES)
- embed.description = response.get("error_message", "An unexpected error occurred.")
-
- log.warn(f"Unable to create/edit/delete a reminder. Response: {response}")
- failed = True
-
- else:
- embed.colour = Colour.green()
- embed.title = random.choice(POSITIVE_REPLIES)
- embed.description = on_success
-
- failed = False
-
+ embed.colour = Colour.green()
+ embed.title = random.choice(POSITIVE_REPLIES)
+ embed.description = on_success
await ctx.send(embed=embed)
- return failed
async def _scheduled_task(self, reminder: dict):
"""
@@ -92,7 +74,7 @@ class Reminders(Scheduler):
"""
reminder_id = reminder["id"]
- reminder_datetime = parse_rfc1123(reminder["remind_at"])
+ reminder_datetime = datetime.fromisoformat(reminder['expiration'][:-1])
# Send the reminder message once the desired duration has passed
await wait_until(reminder_datetime)
@@ -111,18 +93,7 @@ class Reminders(Scheduler):
:param reminder_id: The ID of the reminder.
"""
- # The API requires a list, so let's give it one :)
- json_data = {
- "reminders": [
- reminder_id
- ]
- }
-
- await self.bot.http_session.delete(
- url=URLs.site_reminders_api,
- headers=self.headers,
- json=json_data
- )
+ await self.bot.api_client.delete('bot/reminders/' + str(reminder_id))
# Now we can remove it from the schedule list
self.cancel_task(reminder_id)
@@ -147,8 +118,8 @@ class Reminders(Scheduler):
:param late: How late the reminder is (if at all)
"""
- channel = self.bot.get_channel(int(reminder["channel_id"]))
- user = self.bot.get_user(int(reminder["user_id"]))
+ channel = self.bot.get_channel(reminder["channel_id"])
+ user = self.bot.get_user(reminder["author"])
embed = Embed()
embed.colour = Colour.blurple()
@@ -173,15 +144,15 @@ class Reminders(Scheduler):
await self._delete_reminder(reminder["id"])
@group(name="remind", aliases=("reminder", "reminders"), invoke_without_command=True)
- async def remind_group(self, ctx: Context, duration: str, *, content: str):
+ async def remind_group(self, ctx: Context, expiration: ExpirationDate, *, content: str):
"""
Commands for managing your reminders.
"""
- await ctx.invoke(self.new_reminder, duration=duration, content=content)
+ await ctx.invoke(self.new_reminder, expiration=expiration, content=content)
@remind_group.command(name="new", aliases=("add", "create"))
- async def new_reminder(self, ctx: Context, duration: str, *, content: str):
+ async def new_reminder(self, ctx: Context, expiration: ExpirationDate, *, content: str):
"""
Set yourself a simple reminder.
"""
@@ -200,13 +171,13 @@ class Reminders(Scheduler):
return await ctx.send(embed=embed)
# Get their current active reminders
- response = await self.bot.http_session.get(
- url=URLs.site_reminders_user_api.format(user_id=ctx.author.id),
- headers=self.headers
+ active_reminders = await self.bot.api_client.get(
+ 'bot/reminders',
+ params={
+ 'user__id': str(ctx.author.id)
+ }
)
- active_reminders = await response.json()
-
# Let's limit this, so we don't get 10 000
# reminders from kip or something like that :P
if len(active_reminders) > MAXIMUM_REMINDERS:
@@ -217,45 +188,23 @@ class Reminders(Scheduler):
return await ctx.send(embed=embed)
# Now we can attempt to actually set the reminder.
- try:
- response = await self.bot.http_session.post(
- url=URLs.site_reminders_api,
- headers=self.headers,
- json={
- "user_id": str(ctx.author.id),
- "duration": duration,
- "content": content,
- "channel_id": str(ctx.channel.id)
- }
- )
-
- response_data = await response.json()
-
- # AFAIK only happens if the user enters, like, a quintillion weeks
- except ClientResponseError:
- embed.colour = Colour.red()
- embed.title = random.choice(NEGATIVE_REPLIES)
- embed.description = (
- "An error occurred while adding your reminder to the database. "
- "Did you enter a reasonable duration?"
- )
-
- log.warn(f"User {ctx.author} attempted to create a reminder for {duration}, but failed.")
-
- return await ctx.send(embed=embed)
-
- # Confirm to the user whether or not it worked.
- failed = await self._send_confirmation(
- ctx, response_data,
- on_success="Your reminder has been created successfully!"
+ reminder = await self.bot.api_client.post(
+ 'bot/reminders',
+ json={
+ 'author': ctx.author.id,
+ 'channel_id': ctx.message.channel.id,
+ 'content': content,
+ 'expiration': expiration.isoformat()
+ }
)
- # If it worked, schedule the reminder.
- if not failed:
- loop = asyncio.get_event_loop()
- reminder = response_data["reminder"]
+ # Confirm to the user that it worked.
+ await self._send_confirmation(
+ ctx, on_success="Your reminder has been created successfully!"
+ )
- self.schedule_task(loop, reminder["id"], reminder)
+ loop = asyncio.get_event_loop()
+ self.schedule_task(loop, reminder["id"], reminder)
@remind_group.command(name="list")
async def list_reminders(self, ctx: Context):
@@ -264,31 +213,31 @@ class Reminders(Scheduler):
"""
# Get all the user's reminders from the database.
- response = await self.bot.http_session.get(
- url=URLs.site_reminders_user_api,
- params={"user_id": str(ctx.author.id)},
- headers=self.headers
+ data = await self.bot.api_client.get(
+ 'bot/reminders',
+ params={'user__id': str(ctx.author.id)}
)
- data = await response.json()
- now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
+ now = datetime.utcnow()
# Make a list of tuples so it can be sorted by time.
- reminders = [
- (rem["content"], rem["remind_at"], rem["friendly_id"]) for rem in data["reminders"]
- ]
-
- reminders.sort(key=lambda rem: rem[1])
+ reminders = sorted(
+ (
+ (rem['content'], rem['expiration'], rem['id'])
+ for rem in data
+ ),
+ key=itemgetter(1)
+ )
lines = []
- for index, (content, remind_at, friendly_id) in enumerate(reminders):
+ for content, remind_at, id_ in reminders:
# Parse and humanize the time, make it pretty :D
- remind_datetime = parse_rfc1123(remind_at)
+ remind_datetime = datetime.fromisoformat(remind_at[:-1])
time = humanize_delta(relativedelta(remind_datetime, now))
text = textwrap.dedent(f"""
- **Reminder #{index}:** *expires in {time}* (ID: {friendly_id})
+ **Reminder #{id_}:** *expires in {time}* (ID: {id_})
{content}
""").strip()
@@ -322,84 +271,53 @@ class Reminders(Scheduler):
await ctx.invoke(self.bot.get_command("help"), "reminders", "edit")
@edit_reminder_group.command(name="duration", aliases=("time",))
- async def edit_reminder_duration(self, ctx: Context, friendly_id: str, duration: str):
+ async def edit_reminder_duration(self, ctx: Context, id_: int, expiration: ExpirationDate):
"""
- Edit one of your reminders' duration.
+ Edit one of your reminders' expiration.
"""
# Send the request to update the reminder in the database
- response = await self.bot.http_session.patch(
- url=URLs.site_reminders_user_api,
- headers=self.headers,
- json={
- "user_id": str(ctx.author.id),
- "friendly_id": friendly_id,
- "duration": duration
- }
+ reminder = await self.bot.http_session.patch(
+ 'bot/reminders/' + str(id_),
+ json={'expiration': expiration.isoformat()}
)
# Send a confirmation message to the channel
- response_data = await response.json()
- failed = await self._send_confirmation(
- ctx, response_data,
- on_success="That reminder has been edited successfully!"
+ await self._send_confirmation(
+ ctx, on_success="That reminder has been edited successfully!"
)
- if not failed:
- await self._reschedule_reminder(response_data["reminder"])
+ await self._reschedule_reminder(reminder)
@edit_reminder_group.command(name="content", aliases=("reason",))
- async def edit_reminder_content(self, ctx: Context, friendly_id: str, *, content: str):
+ async def edit_reminder_content(self, ctx: Context, id_: int, *, content: str):
"""
Edit one of your reminders' content.
"""
# Send the request to update the reminder in the database
- response = await self.bot.http_session.patch(
- url=URLs.site_reminders_user_api,
- headers=self.headers,
- json={
- "user_id": str(ctx.author.id),
- "friendly_id": friendly_id,
- "content": content
- }
+ reminder = await self.bot.http_session.patch(
+ 'bot/reminders/' + str(id_),
+ json={'content': content}
)
# Send a confirmation message to the channel
- response_data = await response.json()
- failed = await self._send_confirmation(
- ctx, response_data,
- on_success="That reminder has been edited successfully!"
+ await self._send_confirmation(
+ ctx, on_success="That reminder has been edited successfully!"
)
-
- if not failed:
- await self._reschedule_reminder(response_data["reminder"])
+ await self._reschedule_reminder(reminder)
@remind_group.command("delete", aliases=("remove",))
- async def delete_reminder(self, ctx: Context, friendly_id: str):
+ async def delete_reminder(self, ctx: Context, id_: int):
"""
Delete one of your active reminders.
"""
- # Send the request to delete the reminder from the database
- response = await self.bot.http_session.delete(
- url=URLs.site_reminders_user_api,
- headers=self.headers,
- json={
- "user_id": str(ctx.author.id),
- "friendly_id": friendly_id
- }
- )
-
- response_data = await response.json()
- failed = await self._send_confirmation(
- ctx, response_data,
- on_success="That reminder has been deleted successfully!"
+ await self._delete_reminder(id_)
+ await self._send_confirmation(
+ ctx, on_success="That reminder has been deleted successfully!"
)
- if not failed:
- self.cancel_reminder(response_data["reminder_id"])
-
def setup(bot: Bot):
bot.add_cog(Reminders(bot))