Compare commits

...

9 commits

3 changed files with 61 additions and 20 deletions

View file

@ -13,11 +13,12 @@ schema = """
PRAGMA user_version = 1; PRAGMA user_version = 1;
PRAGMA main.synchronous = NORMAL; PRAGMA main.synchronous = NORMAL;
PRAGMA foreign_keys = ON;
CREATE TABLE keywords ( CREATE TABLE keywords (
guild_id INTEGER NOT NULL, guild_id INTEGER NOT NULL,
keyword TEXT NOT NULL, keyword TEXT NOT NULL,
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
regex INTEGER NOT NULL DEFAULT 0 CHECK(regex IN (0, 1)), regex INTEGER NOT NULL DEFAULT 0 CHECK(regex IN (0, 1)),
count INTEGER NOT NULL DEFAULT 0 count INTEGER NOT NULL DEFAULT 0
); );
@ -33,22 +34,34 @@ CREATE TABLE users (
disabled INTEGER NOT NULL DEFAULT 0 CHECK(disabled IN (0, 1)), disabled INTEGER NOT NULL DEFAULT 0 CHECK(disabled IN (0, 1)),
use_embed INTEGER NOT NULL DEFAULT 1 CHECK(use_embed IN (0, 1)), use_embed INTEGER NOT NULL DEFAULT 1 CHECK(use_embed IN (0, 1)),
notify_self INTEGER NOT NULL DEFAULT 0 CHECK(notify_self IN (0, 1)), notify_self INTEGER NOT NULL DEFAULT 0 CHECK(notify_self IN (0, 1)),
bots_notify INTEGER NOT NULL DEFAULT 0 CHECK(bots_notify IN (0, 1)) bots_notify INTEGER NOT NULL DEFAULT 0 CHECK(bots_notify IN (0, 1)),
ignore_active INTEGER NOT NULL DEFAULT 0 CHECK(bots_notify IN (0, 1))
) )
WITHOUT ROWID; WITHOUT ROWID;
CREATE TABLE user_ignores ( CREATE TABLE user_ignores (
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
guild_id INTEGER NOT NULL, guild_id INTEGER NOT NULL,
target INTEGER NOT NULL, target INTEGER NOT NULL, -- channel or user id
PRIMARY KEY (user_id, guild_id, target) PRIMARY KEY (user_id, guild_id, target)
); );
CREATE TABLE user_blocks ( CREATE TABLE user_blocks (
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
target INTEGER NOT NULL, target INTEGER NOT NULL,
PRIMARY KEY (user_id, target) PRIMARY KEY (user_id, target)
); );
CREATE TABLE user_pauses (
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
guild_id INTEGER NOT NULL,
PRIMARY KEY (user_id, guild_id)
);
CREATE INDEX keywords_index ON keywords(user_id);
CREATE INDEX user_ignores_index ON user_ignores(user_id);
CREATE INDEX user_blocks_index ON user_blocks(user_id);
CREATE INDEX user_pauses_index ON user_pauses(user_id);
""" """

View file

@ -89,6 +89,13 @@ class Nomen(Bot):
await super().close() await super().close()
await self.db.close() await self.db.close()
async def user_toggle(self, user_id, item):
await self.db.execute(
"REPLACE INTO users (user_id, {item}) VALUES(:user_id, iff((SELECT {item} FROM users WHERE user_id=:user_id)), 0, 1)",
{"user_id": user_id},
)
await self.db.commit()
bot = Nomen( bot = Nomen(
description="Keeper of Names", description="Keeper of Names",

View file

@ -1,8 +1,9 @@
import logging import logging
from asyncio import TaskGroup from asyncio import TaskGroup
from textwrap import indent from textwrap import indent
from typing import Union
from disnake import Embed from disnake import Embed, Member, TextChannel
from disnake.ext.commands import Cog, group, guild_only 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_exists, fetch_unpacked, test_keyword
@ -72,7 +73,9 @@ async def handle_triggers(ctx, message):
"is_bot": ctx.author.bot, "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 fetch_exists(
ctx.bot.db, "SELECT * FROM users WHERE user_id=:author AND unlikely(disabled IS 1)", params
)
if disabled: if disabled:
log.debug(f"User {ctx.author} ({ctx.author.id}) opted out") log.debug(f"User {ctx.author} ({ctx.author.id}) opted out")
@ -86,17 +89,17 @@ async def handle_triggers(ctx, message):
SELECT keyword, user_id, use_embed, row_number() over (partition by user_id) n SELECT keyword, user_id, use_embed, row_number() over (partition by user_id) n
FROM keywords FROM keywords
LEFT JOIN users USING (user_id) LEFT JOIN users USING (user_id)
WHERE disabled IS NOT 1 -- Don't notify users who opted out WHERE likely(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 (unlikely(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 (unlikely(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... AND likely(NOT EXISTS(SELECT * FROM ( -- Don't notify if...
SELECT target FROM user_ignores -- Author is ignored in this guild SELECT target FROM user_ignores -- Author or channel is ignored in this guild
WHERE user_id=user_id AND guild_id=guild_id WHERE user_id=user_id AND guild_id=guild_id
UNION UNION
SELECT target FROM user_blocks -- Author is blocked SELECT target FROM user_blocks -- Author is blocked
WHERE user_id=user_id WHERE user_id=user_id
) ) WHERE target IN (:author, :channel)))
AND guild_id=:guild AND contains(:content, keyword, regex) AND guild_id=:guild AND unlikely(contains(:content, keyword, regex))
) )
WHERE n=1 WHERE n=1
""" """
@ -135,6 +138,9 @@ class Notifications(Cog):
await handle_triggers(ctx, message) await handle_triggers(ctx, message)
async def cog_before_invoke(ctx):
await ctx.bot.db.execute("INSERT OR IGNORE INTO users (userid) VALUE(?)", (ctx.author.id,))
@group( @group(
aliases=["kw", "notification", "notifications", "notif", "noti"], aliases=["kw", "notification", "notifications", "notif", "noti"],
invoke_without_command=True, invoke_without_command=True,
@ -297,17 +303,32 @@ class Notifications(Cog):
@keyword.command() @keyword.command()
@guild_only() @guild_only()
async def pause(self, ctx): async def pause(self, ctx):
pass params = (ctx.author.id, ctx.guild_id)
# TODO: Pause guild notifications if await fetch_exists("SELECT * FROM user_pauses WHERE user_id=? AND guild_id=?"):
await ctx.bot.db.execute("DELETE FROM user_pauses WHERE user_id=? AND guild_id=?", params)
await ctx.bot.send(f"Resumed notifications in {ctx.guild}")
else:
await ctx.bot.db.execute("INSERT INTO user_pauses VALUES(?, ?)", params)
await ctx.bot.send(f"Paused notifications in {ctx.guild}")
# TODO: Pause guild notifications in handler
@keyword.group(invoke_without_command=True) @keyword.group(invoke_without_command=True)
@guild_only() @guild_only()
async def ignore(self, ctx, channel): async def ignore(self, ctx, target: Union[TextChannel, Member]):
await ctx.bot.db.execute("INSERT INTO user_ignores VALUES(?, ?, ?)", (ctx.author.id, ctx.guild.id, target.id))
await ctx.bot.db.commit()
await ctx.send(f"Now ignoring {target}")
@keyword.command()
@guild_only()
async def uningnore(self, ctx, target: Union[TextChannel, Member]):
pass pass
# TODO: Ignore channels and users # TODO: Unignore
@ignore.command() @ignore.command()
@guild_only() @guild_only()
async def active(self, ctx): async def active(self, ctx):
pass await ctx.bot.user_toggle(ctx.author.id, "ignore_active")
# TODO: Ignore active channel await ctx.bot.send("Toggled ignore active channel") # TODO: Send current state
# TODO: Ignore active channel in handler