aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar MarkKoz <[email protected]>2020-07-18 10:31:35 -0700
committerGravatar MarkKoz <[email protected]>2020-07-31 23:01:22 -0700
commit022b43c2651cd568592327e8b493fbefaa4f332a (patch)
treec11080fa52f7232c90738e2b41f9b09f430122a8
parentAdd util function to get value from arg (diff)
Reminders: make operations mutually exclusive
This fixes race conditions between editing, deleting, and sending a reminder. If one operation is already happening, the others will be aborted.
-rw-r--r--bot/cogs/reminders.py7
1 files changed, 7 insertions, 0 deletions
diff --git a/bot/cogs/reminders.py b/bot/cogs/reminders.py
index a043b7d75..1a0a9d303 100644
--- a/bot/cogs/reminders.py
+++ b/bot/cogs/reminders.py
@@ -4,6 +4,7 @@ import random
import textwrap
import typing as t
from datetime import datetime, timedelta
+from functools import partial
from operator import itemgetter
import discord
@@ -14,14 +15,17 @@ from discord.ext.commands import Cog, Context, Greedy, group
from bot.bot import Bot
from bot.constants import Guild, Icons, MODERATION_ROLES, POSITIVE_REPLIES, STAFF_ROLES
from bot.converters import Duration
+from bot.decorators import mutually_exclusive
from bot.pagination import LinePaginator
from bot.utils.checks import without_role_check
+from bot.utils.function import get_arg_value
from bot.utils.messages import send_denial
from bot.utils.scheduling import Scheduler
from bot.utils.time import humanize_delta
log = logging.getLogger(__name__)
+NAMESPACE = "reminders" # Used for the mutually_exclusive decorator; constant to prevent typos
WHITELISTED_CHANNELS = Guild.reminder_whitelist
MAXIMUM_REMINDERS = 5
@@ -164,6 +168,7 @@ class Reminders(Cog):
log.trace(f"Scheduling new task #{reminder['id']}")
self.schedule_reminder(reminder)
+ @mutually_exclusive(NAMESPACE, lambda args: get_arg_value("reminder", args)["id"])
async def send_reminder(self, reminder: dict, late: relativedelta = None) -> None:
"""Send the reminder."""
is_valid, user, channel = self.ensure_valid_reminder(reminder)
@@ -370,6 +375,7 @@ class Reminders(Cog):
mention_ids = [mention.id for mention in mentions]
await self.edit_reminder(ctx, id_, {"mentions": mention_ids})
+ @mutually_exclusive(NAMESPACE, partial(get_arg_value, "id_"))
async def edit_reminder(self, ctx: Context, id_: int, payload: dict) -> None:
"""Edits a reminder with the given payload, then sends a confirmation message."""
reminder = await self._edit_reminder(id_, payload)
@@ -387,6 +393,7 @@ class Reminders(Cog):
await self._reschedule_reminder(reminder)
@remind_group.command("delete", aliases=("remove", "cancel"))
+ @mutually_exclusive(NAMESPACE, partial(get_arg_value, "id_"))
async def delete_reminder(self, ctx: Context, id_: int) -> None:
"""Delete one of your active reminders."""
await self.bot.api_client.delete(f"bot/reminders/{id_}")