From 0fb455ef534257ff245ded9c3af63e9118fe830d Mon Sep 17 00:00:00 2001 From: Infinidoge Date: Thu, 19 Dec 2024 01:12:23 -0500 Subject: [PATCH] refactor notification handling --- nomen/notifications.py | 60 +++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/nomen/notifications.py b/nomen/notifications.py index 95e4461..138b8e9 100644 --- a/nomen/notifications.py +++ b/nomen/notifications.py @@ -4,7 +4,7 @@ from asyncio import TaskGroup from disnake import Embed from disnake.ext.commands import Cog, group, guild_only -from .utils import can_view, confirm, test_keyword, unpack +from .utils import can_view, confirm, fetch_unpacked, test_keyword log = logging.getLogger("nomen.notifications") log.setLevel(logging.INFO) @@ -40,31 +40,53 @@ async def handle_notification(db_updates, ctx, message, keyword, user_id): async def handle_triggers(ctx, message): - cur = await ctx.bot.db.execute("SELECT disabled FROM users WHERE user_id=?", (ctx.author.id,)) - res = await cur.fetchone() + """ + Main function that handles message triggers + """ - if res and res[0]: + params = { + "author": ctx.author.id, + "channel": ctx.channel.id, + "guild": ctx.guild.id, + "content": message.content, + "is_bot": ctx.author.bot, + } + + disabled = await ctx.bot.db.execute_fetchall( + "SELECT EXISTS(SELECT * FROM users WHERE user_id=:author AND disabled IS 1)", params + )[0] + + if disabled: log.debug(f"User {ctx.author} ({ctx.author.id}) opted out") return - handled_users = [ctx.author.id] db_updates = [] + search_query = """ + SELECT keyword, user_id, use_embed + FROM ( -- Deduplicate notification recipients by user_id + SELECT keyword, user_id, use_embed, row_number() over (partition by user_id) n + FROM keywords + LEFT JOIN users USING (user_id) + WHERE disabled IS NOT 1 -- Don't notify users who opted out + AND (notify_self IS 1 OR user_id IS NOT :author) -- Don't notify author unless wanted + AND (bots_notify IS 1 OR :is_bot IS NOT 1) -- Don't notify from bots unless wanted + AND :author NOT IN ( -- Don't notify if... + SELECT target FROM user_ignores -- Author is ignored in this guilde + WHERE user_id=user_id AND guild_id=guild_id + UNION + SELECT target FROM user_blocks -- Author is blocked + WHERE user_id=user_id + ) + AND guild_id=:guild AND contains(:content, keyword, regex) + ) + WHERE n=1 + """ + async with TaskGroup() as tg: - async with ctx.bot.db.execute( - """SELECT keyword, user_id - FROM keywords LEFT JOIN users USING (user_id) - WHERE disabled IS NOT 1 AND guild_id=? AND contains(?, keyword, regex)""", - (ctx.guild.id, message.content), - ) as cur: - async for keyword, user_id in cur: - log.debug(f"- Handling '{keyword}' for {user_id}") - - if user_id in handled_users: - log.debug(f"- - Ignoring {user_id}") - continue - - handled_users.append(user_id) + async with ctx.bot.db.execute(search_query, params) as cur: + async for keyword, user_id, use_embed in cur: + log.debug(f"- Creating notification task: '{keyword}' for {user_id}") tg.create_task(handle_notification(db_updates, ctx, message, keyword, user_id))