Compare commits

..

No commits in common. "38e41dc1b5d6612f4b6f403355cc04aff62abacb" and "ec54e31b5c5f480df62ac25fd84af76136ca83aa" have entirely different histories.

4 changed files with 33 additions and 59 deletions

View file

@ -23,7 +23,7 @@ logger_disnake.setLevel(logging.WARNING)
log = logging.getLogger("nomen")
log.setLevel(logging.DEBUG)
formatter = logging.Formatter("{asctime} {levelname:8} {name}: {message}", "%Y-%m-%d %H:%M:%S", "{")
formatter = logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s")
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter)
logging.getLogger(None).addHandler(handler)
@ -78,7 +78,10 @@ class Nomen(Bot):
return prefix
async def set_guild_prefix(self, guild: Guild, prefix):
await self.db.execute("REPLACE INTO guilds (guild_id, prefix) VALUES(?, ?)", (guild.id, prefix))
await self.db.execute(
"REPLACE INTO guilds VALUES(?, ?)",
(guild.id, prefix),
)
self.prefixes[guild.id] = prefix
async def start(self, *args, **kwargs):

View file

@ -1,60 +1,42 @@
import logging
from asyncio import TaskGroup
from textwrap import indent
from disnake import Embed
from disnake.ext.commands import Cog, group, guild_only
from .utils import can_view, confirm, fetch_exists, fetch_unpacked, test_keyword
from .utils import can_view, confirm, fetch_unpacked, test_keyword
log = logging.getLogger("nomen.notifications")
log.setLevel(logging.DEBUG)
log_ = log
log.setLevel(logging.INFO)
class NotifierLogAdapter(logging.LoggerAdapter):
def process(self, msg, kwargs):
return (
f"[guild: {self.extra["guild"]}, user: {self.extra["user"]}, keyword: {self.extra["keyword"]}] {msg}",
kwargs,
)
async def handle_notification(db_updates, ctx, message, keyword, user_id, use_embed):
async def handle_notification(db_updates, ctx, message, keyword, user_id):
"""
Async task to dispatch a notification
"""
log.debug(f"- Handling `{keyword}` for {user_id}")
member = await ctx.guild.getch_member(user_id)
log = NotifierLogAdapter(log_.getChild("notifier"), {"guild": ctx.guild, "user": member, "keyword": keyword})
log.debug("Handling notification")
if not await can_view(ctx, member):
log.debug("Missing permission")
log.debug(f"- - Missing permission {user_id}")
return
log.debug("Notifying")
log.debug(f"- - Notifying {user_id}")
db_updates.append((ctx.guild.id, keyword, user_id))
header = f"🔔 `{message.author.display_name}` mentioned `{keyword}` on `{ctx.guild}`:"
footer = f"\n<t:{int(message.created_at.timestamp())}:R> | [Show]({message.jump_url}) | <#{ctx.channel.id}>"
footer = f"\n\n<t:{int(message.created_at.timestamp())}:R> | [Show]({message.jump_url}) | <#{ctx.channel.id}>"
if use_embed:
log.debug("Sending embed")
embed = Embed(description=message.content + "\n" + footer)
embed.set_author(
name=f"{message.author.display_name} ({message.author})",
icon_url=message.author.display_avatar,
)
embed = Embed(
description=message.content + footer,
)
embed.set_author(name=message.author, icon_url=message.author.display_avatar)
await member.send(header, embed=embed)
else:
log.debug("Sending plain message")
await member.send("\n".join((header, indent(message.content, "> ", lambda line: True).strip(), footer)))
log.debug("Sent")
await member.send(
f":bell: `{message.author}` mentioned `{keyword}` on `{ctx.guild}`:",
embed=embed,
)
async def handle_triggers(ctx, message):
@ -62,8 +44,6 @@ async def handle_triggers(ctx, message):
Main function that handles message triggers
"""
log.debug(f"Handling triggers for '{message.content}' from {ctx.author}")
params = {
"author": ctx.author.id,
"channel": ctx.channel.id,
@ -72,9 +52,11 @@ async def handle_triggers(ctx, message):
"is_bot": ctx.author.bot,
}
disabled = await fetch_exists(ctx.bot.db, "SELECT * FROM users WHERE user_id=:author AND disabled IS 1", params)
disabled = await ctx.bot.db.execute_fetchall(
"SELECT EXISTS(SELECT * FROM users WHERE user_id=:author AND disabled IS 1)", params
)
if disabled:
if disabled[0][0]:
log.debug(f"User {ctx.author} ({ctx.author.id}) opted out")
return
@ -90,7 +72,7 @@ async def handle_triggers(ctx, message):
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 guild
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
@ -106,9 +88,8 @@ async def handle_triggers(ctx, message):
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, use_embed))
tg.create_task(handle_notification(db_updates, ctx, message, keyword, user_id))
log.debug("Incrementing notification counts")
await ctx.bot.db.executemany(
"UPDATE keywords SET count = count + 1 WHERE guild_id=? AND keyword=? AND user_id=?",
db_updates,
@ -226,7 +207,7 @@ class Notifications(Cog):
await self._add_keyword(ctx, keyword, True)
@keyword.command(aliases=["delete", "del"])
@keyword.command()
@guild_only()
async def remove(self, ctx, keyword):
"""
@ -304,7 +285,7 @@ class Notifications(Cog):
@guild_only()
async def ignore(self, ctx, channel):
pass
# TODO: Ignore channels and users
# TODO: Ignore channels
@ignore.command()
@guild_only()

View file

@ -91,7 +91,7 @@ You may want to `{ctx.clean_prefix}nomen export` first"""
f"You have now opted-out and will no longer trigger or receive notifications. To opt back in, run `{ctx.clean_prefix}nomen opt-in`"
)
await self.bot.db.execute("REPLACE INTO users (user_id, disabled) VALUES(?, 1)", (ctx.author.id,))
await self.bot.db.execute("REPLACE INTO users VALUES(?, 1)", (ctx.author.id,))
await self.bot.db.commit()
@nomen.command(name="opt-in")
@ -106,5 +106,5 @@ You may want to `{ctx.clean_prefix}nomen export` first"""
f"You have opted back in and will now trigger and receive notifications. To opt out, run `{ctx.clean_prefix}nomen opt-out`"
)
await self.bot.db.execute("REPLACE INTO users (user_id, disabled) VALUES(?, 0)", (ctx.author.id,))
await self.bot.db.execute("REPLACE INTO users VALUES(?, 0)", (ctx.author.id,))
await self.bot.db.commit()

View file

@ -1,12 +1,9 @@
import logging
from asyncio import TimeoutError
from itertools import chain
import re2 as re
from disnake import ChannelType
log = logging.getLogger("nomen.utils")
ALPHABET = list("abcdefghijklmnopqrstuvwxyz ")
COMMON_WORDS = [
@ -112,17 +109,12 @@ def unpack(lst_of_tpl):
async def fetch_unpacked(db, sql, params=None):
cur = await db.cursor()
cur.row_factory = lambda cursor, row: first(row)
cur = db.cursor()
cur.row_factory = first
cur = await cur.execute(sql, params)
return await cur.fetchall()
async def fetch_exists(db, sql, params=None):
result = await db.execute_fetchall(f"SELECT EXISTS({sql})", params)
return result[0][0]
async def in_thread(member, thread):
# FIXME: Currently overlooks the situation where a moderator isn't in a thread but has manage threads
return any(member.id == thread_member.id for thread_member in await thread.fetch_members())
@ -190,7 +182,6 @@ async def confirm(ctx, message, delete_msgs=False, response_check=get_positivity
pass
return reply_bool
def cleanup_code(content):
"""Automatically removes code blocks from the code."""
# remove ```py\n```
@ -200,5 +191,4 @@ def cleanup_code(content):
# remove `foo`
return content.strip("` \n")
# ===== End code borrowed from Avrae =====