refactor notification handling

This commit is contained in:
Infinidoge 2024-12-19 01:12:23 -05:00
parent 8487f60cff
commit 0fb455ef53
Signed by: Infinidoge
SSH key fingerprint: SHA256:oAMyvotlNFraMmZmr+p6AxnNfW/GioTs1pOn3V4tQ7A

View file

@ -4,7 +4,7 @@ from asyncio import TaskGroup
from disnake import Embed from disnake import Embed
from disnake.ext.commands import Cog, group, guild_only 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 = logging.getLogger("nomen.notifications")
log.setLevel(logging.INFO) 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): 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") log.debug(f"User {ctx.author} ({ctx.author.id}) opted out")
return return
handled_users = [ctx.author.id]
db_updates = [] 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 TaskGroup() as tg:
async with ctx.bot.db.execute( async with ctx.bot.db.execute(search_query, params) as cur:
"""SELECT keyword, user_id async for keyword, user_id, use_embed in cur:
FROM keywords LEFT JOIN users USING (user_id) log.debug(f"- Creating notification task: '{keyword}' for {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)
tg.create_task(handle_notification(db_updates, ctx, message, keyword, user_id)) tg.create_task(handle_notification(db_updates, ctx, message, keyword, user_id))