diff --git a/nomen/notifications.py b/nomen/notifications.py index d18d343..f49060e 100644 --- a/nomen/notifications.py +++ b/nomen/notifications.py @@ -22,6 +22,19 @@ class NotifierLogAdapter(logging.LoggerAdapter): ) +class KeywordError(Exception): + def __init__(self, msg=None, dm_msg=None, *args): + self.msg = msg + self.dm_msg = dm_msg + super().__init__(msg, dm_msg, *args) + + async def send(self, ctx): + if self.msg: + await ctx.send(self.msg + " (check DMs)") + if self.dm_msg: + await ctx.author.send(self.dm_msg) + + async def handle_notification(db_updates, ctx, message, keyword, user_id, use_embed): """ Async task to dispatch a notification @@ -158,64 +171,47 @@ class Notifications(Cog): """ await ctx.send_help(self.keyword) - async def _add_keyword(self, ctx, keyword: str, regex: bool): - log.debug( - f"Adding {'regex' if regex else 'keyword'}: {keyword} of {ctx.author} ({ctx.author.id}) on {ctx.guild} ({ctx.guild.id})" + async def _check_conflicts(self, guild_id, user_id, keyword): + return await self.bot.db.fetch_unpacked( + "SELECT keyword FROM keywords WHERE guild_id=? AND user_id=? AND contains(?, keyword, regex)", + (guild_id, user_id, keyword), ) - params = { - "keyword": keyword, - "guild_id": ctx.guild.id, - "user_id": ctx.author.id, - "regex": regex, - } + async def _check_redundants(self, guild_id, user_id, keyword, regex): + return await self.bot.db.fetch_unpacked( + "SELECT keyword FROM keywords WHERE guild_id=? AND user_id=? AND contains(keyword, ?, ?)", + (guild_id, user_id, keyword, regex), + ) - existing = """ - SELECT keyword FROM keywords - WHERE guild_id=:guild_id - AND user_id=:user_id - AND contains(:keyword, keyword, regex) - """ - redundant = """ - SELECT keyword FROM keywords - WHERE guild_id=:guild_id - AND user_id=:user_id - AND contains(keyword, :keyword, :regex) - """ + async def add_keyword(self, guild_id: int, user_id: int, keyword: str, regex: bool, initial_count: int = 0): + log.debug( + f"Adding {'regex' if regex else 'keyword'}: {keyword} of {user_id} on {guild_id} with count {initial_count}" + ) if test_keyword(keyword, regex): log.debug("Keyword too common") - await ctx.send(f"{'Regex' if regex else 'Keyword'} matches a word that is too common") - return + raise KeywordError(f"{'Regex' if regex else 'Keyword'} matches a word that is too common") - conflicts = await ctx.bot.db.fetch_unpacked(existing, params) - - if conflicts: + if conflicts := await self._check_conflicts(guild_id, user_id, keyword): log.debug("Keyword conflicts with existing keyword") - await ctx.send(f"Any instance of `{keyword}` would be matched by existing keywords (check DMs)") - await ctx.author.send( - f"Conflicts with keyword `{keyword}`:\n" + "\n".join(f"- `{conflict}`" for conflict in conflicts) + raise KeywordError( + f"Any instance of `{keyword}` would be matched by existing keywords", + f"Conflicts with keyword `{keyword}`:\n" + "\n".join(f"- `{conflict}`" for conflict in conflicts), ) - return - conflicts = await ctx.bot.db.fetch_unpacked(redundant, params) - - if conflicts: + if redundants := await self._check_redundants(guild_id, user_id, keyword, regex): log.debug("Keyword renders existing redundant") - await ctx.send(f"Adding `{keyword}` will cause existing keywords to never match (check DMs)") - await ctx.author.send( - f"Keywords redundant from `{keyword}`:\n" + "\n".join(f" - `{conflict}`" for conflict in conflicts) + raise KeywordError( + f"Adding `{keyword}` will cause existing keywords to never match", + f"Keywords redundant from `{keyword}`:\n" + "\n".join(f" - `{conflict}`" for conflict in redundants), ) - return log.debug("Keyword valid, adding") - await ctx.bot.db.execute( - "INSERT INTO keywords (guild_id, keyword, user_id, regex) VALUES (:guild_id, :keyword, :user_id, :regex)", - params, + await self.bot.db.execute( + "INSERT INTO keywords VALUES (?, ?, ?, ?, ?)", (guild_id, keyword, user_id, regex, initial_count) ) - await ctx.bot.db.commit() - await ctx.send(f"Added `{keyword}` to your list of keywords") + await self.bot.db.commit() @keyword.command() @guild_only() @@ -226,7 +222,12 @@ class Notifications(Cog): Use quotes for a keyword with spaces! """ - await self._add_keyword(ctx, keyword, False) + try: + await self.add_keyword(ctx.guild.id, ctx.author.id, keyword, False) + except KeywordError as e: + await e.send(ctx) + else: + await ctx.send(f"Added `{keyword}` to your list of keywords") @keyword.command() @guild_only() @@ -238,7 +239,12 @@ class Notifications(Cog): """ # TODO: Add regex names to make notifications cleaner - await self._add_keyword(ctx, keyword, True) + try: + await self.add_keyword(ctx.guild.id, ctx.author.id, keyword, True) + except KeywordError as e: + await e.send(ctx) + else: + await ctx.send(f"Added regex `{keyword}` to your list of keywords") @keyword.command(aliases=["delete", "del"]) @guild_only()