From 26e5109631616c30dc4a3744c46d017e8969f9ab Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Sun, 14 Feb 2021 23:44:39 +0100 Subject: [PATCH 1/9] add notification toggles and checks --- bot.py | 29 +++++++++++++-- core/database.py | 91 +++++++++++++++++++++++++++++------------------- core/schema.py | 41 +++++++++++++++++++--- 3 files changed, 118 insertions(+), 43 deletions(-) diff --git a/bot.py b/bot.py index 0452bf30..5ee8780a 100644 --- a/bot.py +++ b/bot.py @@ -131,15 +131,18 @@ def restart(): async def database_updates(): - handler = schema.SchemaHandler(db_file) + handler = schema.SchemaHandler(db_file, bot) if handler.version == 0: - handler.update() + handler.zero_to_one() messages = db.fetch_all_messages() for message in messages: channel_id = message[1] channel = await getchannel(channel_id) db.add_guild(channel.id, channel.guild.id) + if handler.version == 1: + handler.one_to_two() + async def system_notification(guild_id, text): # Send a message to the system channel (if set) @@ -379,7 +382,6 @@ async def on_ready(): ) await database_updates() - db.migrate_admins(bot) maintain_presence.start() cleandb.start() check_cleanup_queued_guilds.start() @@ -436,6 +438,8 @@ async def on_raw_reaction_add(payload): if user_id != bot.user.id: try: await member.add_roles(role) + if db.notify(guild_id): + await user.send(f"You now have the following role: {role.mention}") except discord.Forbidden: await system_notification( @@ -483,6 +487,8 @@ async def on_raw_reaction_remove(payload): role = discord.utils.get(server.roles, id=role_id) try: await member.remove_roles(role) + if db.notify(guild_id): + await user.send(f"You do not have the following role anymore: {role.mention}") except discord.Forbidden: await system_notification( @@ -1054,6 +1060,23 @@ async def set_systemchannel(ctx): else: await ctx.send("You do not have an admin role.") + +@bot.command(name="notify") +async def toggle_notify(ctx): + if isadmin(ctx.message.author, ctx.guild.id): + notify = db.toggle_notify(ctx.guild.id) + if notify: + ctx.send( + "Notifications have been set to ON for this server.\n" + "Use this command again to turn them off." + ) + else: + ctx.send( + "Notifications have been set to OFF for this server.\n" + "Use this command again to turn them on." + ) + + @commands.is_owner() @bot.command(name="colour") async def set_colour(ctx): diff --git a/core/database.py b/core/database.py index 7d7cb777..6ec5a1fb 100644 --- a/core/database.py +++ b/core/database.py @@ -45,6 +45,12 @@ def initialize(database): "CREATE TABLE IF NOT EXISTS 'systemchannels' ('guild_id' INT, 'channel_id'" " INT);" ) + cursor.execute( + "CREATE TABLE IF NOT EXISTS 'guild_settings' ('guild_id' INT, 'notify' INT);" + ) + cursor.execute( + "CREATE UNIQUE INDEX IF NOT EXISTS guild_id_idx ON guild_settings (guild_id);" + ) cursor.execute( "CREATE UNIQUE INDEX IF NOT EXISTS reactionrole_idx ON messages (reactionrole_id);" ) @@ -66,41 +72,6 @@ def __init__(self, database): self.reactionrole_creation = {} - def migrate_admins(self, client): - import discord - conn = sqlite3.connect(self.database) - cursor = conn.cursor() - cursor.execute("PRAGMA table_info(admins);") - result = cursor.fetchall() - columns = [value[1] for value in result] - if "guild_id" not in columns: - cursor.execute("SELECT role_id FROM admins") - admins = cursor.fetchall() - admins2 = [] - for admin in admins: - admins2.append(admin[0]) - admins = admins2 - guilds = {} - for guild in client.guilds: - guilds[guild.id] = [] - for admin_id in admins: - role = discord.utils.get(guild.roles, id=admin_id) - if role is not None: - guilds[guild.id].append(role.id) - - cursor.execute("ALTER TABLE admins ADD COLUMN 'guild_id' INT;") - conn.commit() - for guild in guilds: - for admin_id in guilds[guild]: - cursor.execute("UPDATE admins SET guild_id = ? WHERE role_id = ?;", (guild, admin_id)) - conn.commit() - cursor.execute("DELETE FROM admins WHERE guild_id IS NULL;") - conn.commit() - print("Successfully migrated admins.") - - cursor.close() - conn.close() - def add_reaction_role(self, rl_dict: dict): try: conn = sqlite3.connect(self.database) @@ -505,3 +476,53 @@ def fetch_cleanup_guilds(self, guild_ids_only=False): except sqlite3.Error as e: return e + + def toggle_notify(self, guild_id: int): + # SQLite doesn't support booleans + # INTs are used: 1 = True, 0 = False + try: + conn = sqlite3.connect(self.database) + cursor = conn.cursor() + cursor.execute("SELECT notify FROM guild_settings WHERE guild_id = ?", (guild_id,)) + results = cursor.fetchall() + if not results: + # If the guild was not in the table because the command was never used before + notify = 1 + cursor.execute("INSERT INTO 'guild_settings' ('guild_id', 'notify') values(?,?);", (guild_id, notify)) + else: + notify = results[0][0] + if notify: + notify = 0 + cursor.execute("UPDATE guild_settings SET notify = ? WHERE guild_id = ?", (notify, guild_id)) + + else: + notify = 1 + cursor.execute("UPDATE guild_settings SET notify = ? WHERE guild_id = ?", (notify, guild_id)) + conn.commit() + cursor.close() + conn.close() + return notify + + except sqlite3.Error as e: + return e + + def notify(self, guild_id: int): + # SQLite doesn't support booleans + # INTs are used: 1 = True, 0 = False + try: + conn = sqlite3.connect(self.database) + cursor = conn.cursor() + cursor.execute("SELECT notify FROM guild_settings WHERE guild_id = ?", (guild_id,)) + results = cursor.fetchall() + if not results: + # If the guild was not in the table because the command was never used before + notify = 0 + cursor.execute("INSERT INTO 'guild_settings' ('guild_id', 'notify') values(?,?);", (guild_id, notify)) + else: + notify = results[0][0] + cursor.close() + conn.close() + return notify + + except sqlite3.Error as e: + return e diff --git a/core/schema.py b/core/schema.py index 340d9d8e..123374d9 100644 --- a/core/schema.py +++ b/core/schema.py @@ -24,11 +24,13 @@ import sqlite3 +import discord class SchemaHandler: - def __init__(self, database): + def __init__(self, database, client): self.database = database + self.client = client self.version = self.version_check() def version_check(self): @@ -45,10 +47,6 @@ def version_check(self): version = version[0][0] return version - def update(self): - if self.version == 0: - self.zero_to_one() - def set_version(self, version): conn = sqlite3.connect(self.database) cursor = conn.cursor() @@ -79,3 +77,36 @@ def zero_to_one(self): cursor.close() conn.close() self.set_version(1) + + def one_to_two(self): + conn = sqlite3.connect(self.database) + cursor = conn.cursor() + cursor.execute("PRAGMA table_info(admins);") + result = cursor.fetchall() + columns = [value[1] for value in result] + if "guild_id" not in columns: + cursor.execute("SELECT role_id FROM admins") + admins = cursor.fetchall() + admins2 = [] + for admin in admins: + admins2.append(admin[0]) + admins = admins2 + guilds = {} + for guild in self.client.guilds: + guilds[guild.id] = [] + for admin_id in admins: + role = discord.utils.get(guild.roles, id=admin_id) + if role is not None: + guilds[guild.id].append(role.id) + + cursor.execute("ALTER TABLE admins ADD COLUMN 'guild_id' INT;") + conn.commit() + for guild in guilds: + for admin_id in guilds[guild]: + cursor.execute("UPDATE admins SET guild_id = ? WHERE role_id = ?;", (guild, admin_id)) + cursor.execute("DELETE FROM admins WHERE guild_id IS NULL;") + conn.commit() + + cursor.close() + conn.close() + self.set_version(2) From b104e182f505846a5f34eb5a8cd439babb859d6f Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Mon, 15 Feb 2021 23:09:51 +0100 Subject: [PATCH 2/9] merge systemchannels into guild_settings --- core/database.py | 24 ++++++++++-------------- core/schema.py | 13 +++++++++++++ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/core/database.py b/core/database.py index 6ec5a1fb..90858711 100644 --- a/core/database.py +++ b/core/database.py @@ -42,11 +42,7 @@ def initialize(database): cursor.execute("CREATE TABLE IF NOT EXISTS 'cleanup_queue_guilds' ('guild_id' INT, 'unix_timestamp' INT);") cursor.execute("CREATE TABLE IF NOT EXISTS 'dbinfo' ('version' INT);") cursor.execute( - "CREATE TABLE IF NOT EXISTS 'systemchannels' ('guild_id' INT, 'channel_id'" - " INT);" - ) - cursor.execute( - "CREATE TABLE IF NOT EXISTS 'guild_settings' ('guild_id' INT, 'notify' INT);" + "CREATE TABLE IF NOT EXISTS 'guild_settings' ('guild_id' INT, 'notify' INT, 'systemchannel' INT);" ) cursor.execute( "CREATE UNIQUE INDEX IF NOT EXISTS guild_id_idx ON guild_settings (guild_id);" @@ -54,9 +50,6 @@ def initialize(database): cursor.execute( "CREATE UNIQUE INDEX IF NOT EXISTS reactionrole_idx ON messages (reactionrole_id);" ) - cursor.execute( - "CREATE UNIQUE INDEX IF NOT EXISTS guild_id_idx ON systemchannels (guild_id);" - ) cursor.execute( "CREATE UNIQUE INDEX IF NOT EXISTS guild_id_index ON cleanup_queue_guilds (guild_id);" ) @@ -208,9 +201,9 @@ def remove_guild(self, guild_id): "DELETE FROM reactionroles WHERE reactionrole_id = ?;", (reactionrole_id,), ) - # Deleting the guilds systemchannels database entries + # Deleting the guilds guild_settings database entries cursor.execute( - "DELETE FROM systemchannels WHERE guild_id = ?;", + "DELETE FROM guild_settings WHERE guild_id = ?;", (guild_id,), ) # Delete the guilds admin roles @@ -309,7 +302,7 @@ def add_systemchannel(self, guild_id, channel_id): conn = sqlite3.connect(self.database) cursor = conn.cursor() cursor.execute( - "REPLACE INTO 'systemchannels' ('guild_id', 'channel_id')" + "REPLACE INTO 'guild_settings' ('guild_id', 'systemchannel')" " values(?, ?);", (guild_id, channel_id), ) @@ -324,8 +317,11 @@ def remove_systemchannel(self, guild_id): try: conn = sqlite3.connect(self.database) cursor = conn.cursor() + channel_id = 0 # Set to false cursor.execute( - "DELETE FROM systemchannels WHERE guild_id = ?;", (guild_id,) + "REPLACE INTO guild_settings ('guild_id', 'systemchannel')" + " values(?, ?);", + (guild_id, channel_id), ) conn.commit() cursor.close() @@ -339,7 +335,7 @@ def fetch_systemchannel(self, guild_id): conn = sqlite3.connect(self.database) cursor = conn.cursor() cursor.execute( - "SELECT channel_id FROM systemchannels WHERE guild_id = ?;", (guild_id,) + "SELECT systemchannel FROM guild_settings WHERE guild_id = ?;", (guild_id,) ) result = cursor.fetchall() cursor.close() @@ -356,7 +352,7 @@ def fetch_all_guilds(self): cursor.execute("SELECT guild_id FROM messages;") message_guilds = cursor.fetchall() - cursor.execute("SELECT guild_id FROM systemchannels;") + cursor.execute("SELECT guild_id FROM guild_settings;") systemchannel_guilds = cursor.fetchall() cursor.execute("SELECT guild_id FROM admins;") diff --git a/core/schema.py b/core/schema.py index 123374d9..1c66b895 100644 --- a/core/schema.py +++ b/core/schema.py @@ -107,6 +107,19 @@ def one_to_two(self): cursor.execute("DELETE FROM admins WHERE guild_id IS NULL;") conn.commit() + cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='systemchannels';") + systemchannels_table = cursor.fetchall() + if systemchannels_table: + cursor.execute("SELECT * FROM systemchannels;") + entries = cursor.fetchall() + for entry in entries: + guild_id = entry[0] + channel_id = entry[1] + notify = 0 # Set default to not notify + cursor.execute("INSERT INTO guild_settings ('guild_id', 'notify', 'systemchannel') values(?, ?, ?);", (guild_id, notify, channel_id)) + cursor.execute("DROP TABLE systemchannels;") + conn.commit() + cursor.close() conn.close() self.set_version(2) From 128a5d2cbb4b754f09f1bb49b6c731216ef122fe Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Mon, 15 Feb 2021 23:11:25 +0100 Subject: [PATCH 3/9] fix role.mention --- bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index 5ee8780a..0a533fbb 100644 --- a/bot.py +++ b/bot.py @@ -439,7 +439,7 @@ async def on_raw_reaction_add(payload): try: await member.add_roles(role) if db.notify(guild_id): - await user.send(f"You now have the following role: {role.mention}") + await user.send(f"You now have the following role: **{role.name}**") except discord.Forbidden: await system_notification( @@ -488,7 +488,7 @@ async def on_raw_reaction_remove(payload): try: await member.remove_roles(role) if db.notify(guild_id): - await user.send(f"You do not have the following role anymore: {role.mention}") + await user.send(f"You do not have the following role anymore: **{role.name}**") except discord.Forbidden: await system_notification( From aa07bb9c61cb67d7daec1c331ce38434281a5e81 Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Mon, 15 Feb 2021 23:19:52 +0100 Subject: [PATCH 4/9] fix system channel exists check --- bot.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bot.py b/bot.py index 0a533fbb..f9deccf7 100644 --- a/bot.py +++ b/bot.py @@ -157,6 +157,12 @@ async def system_notification(guild_id, text): ) return + if server_channel: + server_channel = server_channel[0][0] + + else: + await system_notification(None, text) + if server_channel: try: target_channel = await getchannel(server_channel[0][0]) From 2a4eb4d0411e9042c911d8fb92ccee2f4654c1ad Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Tue, 16 Feb 2021 20:43:48 +0100 Subject: [PATCH 5/9] fix NULL values for systemchannel with notify --- core/database.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/core/database.py b/core/database.py index 90858711..1bf55773 100644 --- a/core/database.py +++ b/core/database.py @@ -301,10 +301,15 @@ def add_systemchannel(self, guild_id, channel_id): try: conn = sqlite3.connect(self.database) cursor = conn.cursor() + notify = 0 cursor.execute( - "REPLACE INTO 'guild_settings' ('guild_id', 'systemchannel')" + "INSERT OR IGNORE INTO guild_settings ('guild_id', 'notify', 'systemchannel')" " values(?, ?);", - (guild_id, channel_id), + (guild_id, notify, channel_id), + ) + cursor.execute( + "UPDATE guild_settings SET systemchannel = ? WHERE guild_id = ?;", + (channel_id, guild_id), ) conn.commit() cursor.close() @@ -318,10 +323,15 @@ def remove_systemchannel(self, guild_id): conn = sqlite3.connect(self.database) cursor = conn.cursor() channel_id = 0 # Set to false + notify = 0 cursor.execute( - "REPLACE INTO guild_settings ('guild_id', 'systemchannel')" + "INSERT OR IGNORE INTO guild_settings ('guild_id', 'notify', 'systemchannel')" " values(?, ?);", - (guild_id, channel_id), + (guild_id, notify, channel_id), + ) + cursor.execute( + "UPDATE guild_settings SET systemchannel = ? WHERE guild_id = ?;", + (channel_id, guild_id), ) conn.commit() cursor.close() @@ -484,7 +494,8 @@ def toggle_notify(self, guild_id: int): if not results: # If the guild was not in the table because the command was never used before notify = 1 - cursor.execute("INSERT INTO 'guild_settings' ('guild_id', 'notify') values(?,?);", (guild_id, notify)) + systemchannel = 0 + cursor.execute("INSERT INTO 'guild_settings' ('guild_id', 'notify') values(?, ?, ?);", (guild_id, systemchannel, notify)) else: notify = results[0][0] if notify: @@ -513,7 +524,8 @@ def notify(self, guild_id: int): if not results: # If the guild was not in the table because the command was never used before notify = 0 - cursor.execute("INSERT INTO 'guild_settings' ('guild_id', 'notify') values(?,?);", (guild_id, notify)) + systemchannel = 0 + cursor.execute("INSERT INTO 'guild_settings' ('guild_id', `systemchannel`, 'notify') values(?, ?, ?);", (guild_id, systemchannel, notify)) else: notify = results[0][0] cursor.close() From 8f84c423af8688964f348b265da61dc1b3bd5d92 Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Tue, 16 Feb 2021 20:48:45 +0100 Subject: [PATCH 6/9] fix awaits --- bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index f9deccf7..58605485 100644 --- a/bot.py +++ b/bot.py @@ -1072,12 +1072,12 @@ async def toggle_notify(ctx): if isadmin(ctx.message.author, ctx.guild.id): notify = db.toggle_notify(ctx.guild.id) if notify: - ctx.send( + await ctx.send( "Notifications have been set to ON for this server.\n" "Use this command again to turn them off." ) else: - ctx.send( + await ctx.send( "Notifications have been set to OFF for this server.\n" "Use this command again to turn them on." ) From c3e1f43ba27e0bb79714c1630f5ec9cc2fb8a079 Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Tue, 16 Feb 2021 20:52:45 +0100 Subject: [PATCH 7/9] fix double subscriptable --- bot.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bot.py b/bot.py index 58605485..8a1a5aca 100644 --- a/bot.py +++ b/bot.py @@ -157,12 +157,6 @@ async def system_notification(guild_id, text): ) return - if server_channel: - server_channel = server_channel[0][0] - - else: - await system_notification(None, text) - if server_channel: try: target_channel = await getchannel(server_channel[0][0]) From c488d53f11dc6b04e8034d6935af9d56e325e5d5 Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Tue, 16 Feb 2021 20:59:09 +0100 Subject: [PATCH 8/9] fix nameerror on role remove with notifications on --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 8a1a5aca..793edaab 100644 --- a/bot.py +++ b/bot.py @@ -488,7 +488,7 @@ async def on_raw_reaction_remove(payload): try: await member.remove_roles(role) if db.notify(guild_id): - await user.send(f"You do not have the following role anymore: **{role.name}**") + await member.send(f"You do not have the following role anymore: **{role.name}**") except discord.Forbidden: await system_notification( From 809d2706436ce1504dbd1e6cc0b1fa88f94bc12e Mon Sep 17 00:00:00 2001 From: eibex <40539455+eibex@users.noreply.github.com> Date: Tue, 16 Feb 2021 21:07:42 +0100 Subject: [PATCH 9/9] actually fix double subscriptable --- bot.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 793edaab..24421ada 100644 --- a/bot.py +++ b/bot.py @@ -157,9 +157,12 @@ async def system_notification(guild_id, text): ) return + if server_channel: + server_channel = server_channel[0][0] + if server_channel: try: - target_channel = await getchannel(server_channel[0][0]) + target_channel = await getchannel(server_channel) await target_channel.send(text) except discord.Forbidden: