From 2c30533a53a64cb6de1a452fc4a911440b1a524e Mon Sep 17 00:00:00 2001 From: Xarlos89 <57622136+Xarlos89@users.noreply.github.com> Date: Mon, 1 Apr 2024 18:44:50 +0200 Subject: [PATCH 01/38] - saving work for now --- .../ServerConfig/dev/FAKE_DB_settings.json | 73 +++++ .../{Zorak-Dev => dev}/channel_info.toml | 0 .../{Zorak-Dev => dev}/reaction_roles.toml | 0 Resources/ServerConfig/dev/testing.py | 19 ++ .../verification_options.toml | 0 .../channel_info.toml | 0 .../reaction_roles.toml | 0 .../verification_options.toml | 0 src/zorak/__main__.py | 34 ++- .../cogs/admin/admin_automod_spam_messages.py | 6 +- src/zorak/cogs/admin/admin_purge.py | 17 +- src/zorak/cogs/admin/admin_startup.py | 6 + src/zorak/cogs/admin/error_handler.py | 4 +- src/zorak/cogs/admin/moderation_invites.py | 4 +- src/zorak/cogs/admin/reaction_roles.py | 6 +- src/zorak/cogs/admin/verification_on_join.py | 66 +---- .../cogs/admin/verification_on_verified.py | 8 +- src/zorak/cogs/general/general_help.py | 14 +- src/zorak/cogs/general/general_suggest.py | 52 ---- src/zorak/cogs/general/general_tickets.py | 6 +- src/zorak/cogs/logging/logging_avatars.py | 2 +- src/zorak/cogs/logging/logging_member_ban.py | 4 +- src/zorak/cogs/logging/logging_member_kick.py | 4 +- .../cogs/logging/logging_member_leaving.py | 4 +- .../cogs/logging/logging_member_roles.py | 4 +- .../cogs/logging/logging_member_unban.py | 2 +- .../cogs/logging/logging_message_delete.py | 7 +- .../cogs/logging/logging_message_edit.py | 10 +- .../cogs/logging/logging_name_changes.py | 2 +- src/zorak/cogs/logging/logging_tickets.py | 12 +- src/zorak/cogs/utility/_event_challenges.py | 2 +- src/zorak/cogs/utility/_rss.py | 268 +++++++++--------- src/zorak/cogs/utility/points.py | 25 +- .../utilities/cog_helpers/guild_settings.py | 83 ++++++ src/zorak/utilities/core/README.md | 12 + .../{logging_utils.py => logging_options.py} | 0 src/zorak/utilities/core/server_settings.py | 65 ----- src/zorak/utilities/core/settings.py | 42 +++ 38 files changed, 466 insertions(+), 397 deletions(-) create mode 100644 Resources/ServerConfig/dev/FAKE_DB_settings.json rename Resources/ServerConfig/{Zorak-Dev => dev}/channel_info.toml (100%) rename Resources/ServerConfig/{Zorak-Dev => dev}/reaction_roles.toml (100%) create mode 100644 Resources/ServerConfig/dev/testing.py rename Resources/ServerConfig/{Zorak-Dev => dev}/verification_options.toml (100%) rename Resources/ServerConfig/{PracticalPython => prod}/channel_info.toml (100%) rename Resources/ServerConfig/{PracticalPython => prod}/reaction_roles.toml (100%) rename Resources/ServerConfig/{PracticalPython => prod}/verification_options.toml (100%) delete mode 100644 src/zorak/cogs/general/general_suggest.py create mode 100644 src/zorak/utilities/cog_helpers/guild_settings.py rename src/zorak/utilities/core/{logging_utils.py => logging_options.py} (100%) delete mode 100644 src/zorak/utilities/core/server_settings.py create mode 100644 src/zorak/utilities/core/settings.py diff --git a/Resources/ServerConfig/dev/FAKE_DB_settings.json b/Resources/ServerConfig/dev/FAKE_DB_settings.json new file mode 100644 index 00000000..416eb920 --- /dev/null +++ b/Resources/ServerConfig/dev/FAKE_DB_settings.json @@ -0,0 +1,73 @@ +{ + "1031644670436061324": { + "info": { + "id": 1031644670436061324, + "name": "Practical Python", + "website": "https://practical-python-org.github.io/Home/", + "email": "Practicalpython-staff@pm.me", + "review": "https://disboard.org/review/create/900302240559018015", + "invite": "https://discord.gg/vgZmgNwuHw", + "logo": "https://raw.githubusercontent.com/Xarlos89/PracticalPython/main/logo.png" + }, + "channels": { + "verification": { + "verification_channel": 1055126587512721439 + }, + "quarantine": { + "quarantine_channel": 1055126882691076177 + }, + "support": { + "server_support": 1068103243734994964 + }, + "general": { + "role_channel": 1062268986726813758, + "rules_channel": 1062269049121275914, + "general_channel": 1031644670436061327, + "resources_channel": 1062300735338983485, + "python_help_1": 1062302503351365632, + "python_help_2": 12345, + "challenges_channel": 1045104938071633994, + "news_channel": 1071095960538718261, + "suggestions_channel": 117939062999902620 + }, + "logging": { + "chat_log": 1043607758685089932, + "join_log": 1043967844934762556, + "mod_log": 1055124663526752297, + "server_change_log": 1062269270047862884, + "user_log": 1044331443884654692, + "verification_log": 1043621605940674580, + "zorak_log": 1062754277543645324 + } + }, + "roles": { + "admin": { + "owner": 1054762426614157354, + "admin": 1134861924882989097, + "staff": 1031903615310385232, + "staff_networking": 1134861783358775367, + "bot": 1054763353538576437 + }, + "reaction": { + "beginner": 1064259543250522112, + "intermediate": 1064259555497877534, + "professional": 1064259557049761863, + "north_america": 1064259558819770379, + "europe": 1064259561302794361, + "asia": 1064259687924637768, + "africa": 1064259690948722708, + "south_america": 1064259693545013288, + "oceana": 1064259760674840666, + "open_to_work": 1114611004182102218, + "employer": 1114611092677722113 + }, + "punishment": { + "naughty": 1062270109839790110 + }, + "verified": { + "verified": 1173219859878924298 + } + } + } +} + diff --git a/Resources/ServerConfig/Zorak-Dev/channel_info.toml b/Resources/ServerConfig/dev/channel_info.toml similarity index 100% rename from Resources/ServerConfig/Zorak-Dev/channel_info.toml rename to Resources/ServerConfig/dev/channel_info.toml diff --git a/Resources/ServerConfig/Zorak-Dev/reaction_roles.toml b/Resources/ServerConfig/dev/reaction_roles.toml similarity index 100% rename from Resources/ServerConfig/Zorak-Dev/reaction_roles.toml rename to Resources/ServerConfig/dev/reaction_roles.toml diff --git a/Resources/ServerConfig/dev/testing.py b/Resources/ServerConfig/dev/testing.py new file mode 100644 index 00000000..9c674a2c --- /dev/null +++ b/Resources/ServerConfig/dev/testing.py @@ -0,0 +1,19 @@ +import json + +# Function to read data from JSON file +def read_json(file_path, category=None): + with open(file_path, 'r') as f: + if category: + data = json.load(f)["server"][category] + else: + data = json.load(f)["server"] + return data + +# Function to write data to JSON file +def write_json(data, file_path): + with open(file_path, 'w') as json_file: + json.dump(data, json_file, indent=4) + + +x = read_json('FAKE_DB_settings.json', 'info') +print(x) diff --git a/Resources/ServerConfig/Zorak-Dev/verification_options.toml b/Resources/ServerConfig/dev/verification_options.toml similarity index 100% rename from Resources/ServerConfig/Zorak-Dev/verification_options.toml rename to Resources/ServerConfig/dev/verification_options.toml diff --git a/Resources/ServerConfig/PracticalPython/channel_info.toml b/Resources/ServerConfig/prod/channel_info.toml similarity index 100% rename from Resources/ServerConfig/PracticalPython/channel_info.toml rename to Resources/ServerConfig/prod/channel_info.toml diff --git a/Resources/ServerConfig/PracticalPython/reaction_roles.toml b/Resources/ServerConfig/prod/reaction_roles.toml similarity index 100% rename from Resources/ServerConfig/PracticalPython/reaction_roles.toml rename to Resources/ServerConfig/prod/reaction_roles.toml diff --git a/Resources/ServerConfig/PracticalPython/verification_options.toml b/Resources/ServerConfig/prod/verification_options.toml similarity index 100% rename from Resources/ServerConfig/PracticalPython/verification_options.toml rename to Resources/ServerConfig/prod/verification_options.toml diff --git a/src/zorak/__main__.py b/src/zorak/__main__.py index 0d2ee8e9..6ed80133 100644 --- a/src/zorak/__main__.py +++ b/src/zorak/__main__.py @@ -5,20 +5,19 @@ - Practicalpython-staff@pm.me """ import logging +from datetime import datetime import os import discord from discord.ext import commands from zorak.utilities.core.args_utils import parse_args -from zorak.utilities.core.logging_utils import setup_logger +from zorak.utilities.core.logging_options import setup_logger from zorak.utilities.core.mongo import initialise_bot_db -from zorak.utilities.core.server_settings import Settings +from zorak.utilities.core.settings import Settings -logger = logging.getLogger(__name__) -COGS_ROOT_PATH = os.path.join(os.path.dirname(__file__), "cogs") -logger.debug(f"COG_PATH: {COGS_ROOT_PATH}") +logger = logging.getLogger(__name__) server_settings_path = None @@ -28,7 +27,9 @@ def load_cogs(bot): Loads the directories under the /cogs/ folder, then digs through those directories and loads the cogs. """ + COGS_ROOT_PATH = os.path.join(os.path.dirname(__file__), "cogs") logger.info("Loading Cogs...") + logger.info(f"Loading from {COGS_ROOT_PATH}") failed_to_load = [] for directory in os.listdir(COGS_ROOT_PATH): if directory.startswith("_"): @@ -60,29 +61,34 @@ def init_bot(token, bot): try: load_cogs(bot) bot.run(token) + except TypeError as e: print(e) + def main(): args = parse_args() + bot = commands.Bot(command_prefix="/", intents=discord.Intents.all()) + bot.remove_command("help") + + + # Set up global logging across the bot. setup_logger( level=args.log_level if args.log_level else int(os.getenv("LOGGING_LEVEL", 20)), stream_logs=args.console_log if args.console_log != None else bool(os.getenv("STREAM_LOGS", False)), ) - - bot = commands.Bot(command_prefix="/", intents=discord.Intents.all()) - bot.remove_command("help") - if not args.drop_db: logger.info("Initialising Database...") - initialise_bot_db(bot) + #initialise_bot_db(bot) + + settings_path = args.server_settings_path if args.server_settings_path else os.environ.get( + "SERVER_SETTINGS") - server_settings_path = args.server_settings_path if args.server_settings_path else os.environ.get("SERVER_SETTINGS") - if server_settings_path: - logger.info(f"Loading server settings from {server_settings_path}") - bot.server_settings = Settings(server_settings_path) # type: ignore + if settings_path: + logger.info(f"Loading all server settings from {settings_path}") + bot.settings = Settings(settings_path, bot.guilds) # type: ignore if args.discord_token: init_bot(args.discord_token, bot) diff --git a/src/zorak/cogs/admin/admin_automod_spam_messages.py b/src/zorak/cogs/admin/admin_automod_spam_messages.py index 65a2f72a..d433c563 100644 --- a/src/zorak/cogs/admin/admin_automod_spam_messages.py +++ b/src/zorak/cogs/admin/admin_automod_spam_messages.py @@ -93,10 +93,10 @@ async def on_message(self, message): # timeout right away await message.author.timeout(until=datetime.utcnow() + timedelta(seconds=30)) - naughty = message.author.guild.get_role(self.bot.server_settings.user_roles["bad"]["naughty"]) - verified = message.author.guild.get_role(self.bot.server_settings.verified_role['verified']) + naughty = message.author.guild.get_role(self.bot.settings.punishment["naughty"]) + verified = message.author.guild.get_role(self.bot.settings.verified["verified"]) quarantine = await self.bot.fetch_channel( - self.bot.server_settings.channels["moderation"]["quarantine_channel"]) + self.bot.settings.quarantine["quarantine_channel"]) # assign Naughty roll member = message.author diff --git a/src/zorak/cogs/admin/admin_purge.py b/src/zorak/cogs/admin/admin_purge.py index 402c3e5e..03857414 100644 --- a/src/zorak/cogs/admin/admin_purge.py +++ b/src/zorak/cogs/admin/admin_purge.py @@ -25,17 +25,12 @@ async def purge_messages(self, ctx, number_messages): # removes the need for a response await ctx.defer() - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) # Welcome channel - - # Check that users are not removing from log channels - if ctx.channel.id in self.bot.server_settings.log_channel.values(): - await ctx.channel.send(f"{ctx.author.mention}, you should not be purging the {ctx.channel.mention}.") - await logs_channel.send(f"{ctx.author.mention} atempted to purge the {ctx.channel.mention}.") - else: - # Do the purge - await ctx.channel.purge(limit=int(number_messages)) - # Log the purge - await logs_channel.send(f"{number_messages} messages purged" f" from {ctx.channel.mention}" f" by {ctx.author.mention}.") + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) # Welcome channel + + # Do the purge + await ctx.channel.purge(limit=int(number_messages)) + # Log the purge + await logs_channel.send(f"{number_messages} messages purged" f" from {ctx.channel.mention}" f" by {ctx.author.mention}.") async def cog_command_error(self, ctx: commands.Context, error: commands.CommandError): """ diff --git a/src/zorak/cogs/admin/admin_startup.py b/src/zorak/cogs/admin/admin_startup.py index a770cf0a..6d7f6964 100644 --- a/src/zorak/cogs/admin/admin_startup.py +++ b/src/zorak/cogs/admin/admin_startup.py @@ -2,10 +2,13 @@ Called upon startup of our bot. Just logs some info. Nothing really. """ +import os +import json import logging from datetime import datetime from discord.ext import commands +from zorak.utilities.core.args_utils import parse_args logger = logging.getLogger(__name__) @@ -27,6 +30,9 @@ async def on_ready(self): logger.info("Started at: {%s}", datetime.now()) logger.info("Greetings, puny earth-creature.") + # logger.info("---------------------------------") + # logger.critical(self.bot.settings.server) + # logger.info("---------------------------------") def setup(bot): """ diff --git a/src/zorak/cogs/admin/error_handler.py b/src/zorak/cogs/admin/error_handler.py index dc7ebdfd..3de40f58 100644 --- a/src/zorak/cogs/admin/error_handler.py +++ b/src/zorak/cogs/admin/error_handler.py @@ -11,7 +11,7 @@ class error_handler(commands.Cog): def __init__(self, bot): self.bot = bot - self.error_channel = self.bot.server_settings.log_channel["zorak_log"] + self.error_channel = self.bot.settings.channels["zorak_log"] @commands.Cog.listener() async def on_application_command_error(self, ctx, error): @@ -37,4 +37,4 @@ async def on_application_command_error(self, ctx, error): def setup(bot): - bot.add_cog(error_handler(bot)) \ No newline at end of file + bot.add_cog(error_handler(bot)) diff --git a/src/zorak/cogs/admin/moderation_invites.py b/src/zorak/cogs/admin/moderation_invites.py index 4ab69be9..b5cab84a 100644 --- a/src/zorak/cogs/admin/moderation_invites.py +++ b/src/zorak/cogs/admin/moderation_invites.py @@ -84,14 +84,14 @@ def check_for_admin_override(arg_message): if not message.content.startswith('z.invite '): return False - return any(role.id in self.bot.server_settings.admin_roles.values() for role in message.author.roles) + return any(role.id in self.bot.settings.admin.values() for role in message.author.roles) if is_invite(txt): if isinstance(message.channel, discord.DMChannel): return if not check_for_admin_override(txt): - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await logs_channel.send(embed=log_message(message)) await message.delete() await current_channel.send(embed=embed_warning(message)) diff --git a/src/zorak/cogs/admin/reaction_roles.py b/src/zorak/cogs/admin/reaction_roles.py index 05731bba..93328bd3 100644 --- a/src/zorak/cogs/admin/reaction_roles.py +++ b/src/zorak/cogs/admin/reaction_roles.py @@ -95,9 +95,9 @@ def __init__(self, bot): @commands.slash_command(description="Get new roles, or change the ones you have!") async def roles(self, ctx): """The slash command that initiates the fancy menus.""" - if hasattr(self.bot.server_settings, "reaction_role_data"): - if "reaction_roles" in self.bot.server_settings.reaction_role_data: - await ctx.respond("Edit Reaction Roles", view=SelectView(self.bot.server_settings.reaction_role_data), ephemeral=True) + if hasattr(self.bot.settings.roles, "reaction"): + if "reaction_roles" in self.bot.settings.reaction: + await ctx.respond("Edit Reaction Roles", view=SelectView(self.bot.settings.reaction), ephemeral=True) else: await ctx.respond("No reaction roles have been set up!", ephemeral=True) else: diff --git a/src/zorak/cogs/admin/verification_on_join.py b/src/zorak/cogs/admin/verification_on_join.py index c9107f14..0a465c7a 100644 --- a/src/zorak/cogs/admin/verification_on_join.py +++ b/src/zorak/cogs/admin/verification_on_join.py @@ -18,55 +18,6 @@ class LoggingVerification(commands.Cog): def __init__(self, bot): self.bot = bot - self.feature_flag = True - - - - # OLD LOGIC - - async def add_role_and_log(self, member, logging_channel): - # Add verification role - await member.add_roles(member.guild.get_role(self.bot.server_settings.unverified_role["needs_approval"])) - - async def send_welcome_message(self, guild, member): - welcome_message = f""" - Hi there, {member.mention} - I'm Zorak, the moderator of {guild.name}. - - We are very happy that you have decided to join us. - Before you are allowed to chat, you need to verify that you aren't a bot. - Dont worry, it's easy. Just go to - {self.bot.get_channel(self.bot.server_settings.mod_channel['verification_channel']).mention} - and click the green button. - - After you do, all of {guild.name} is available to you. Have a great time :-) - """ - # Send Welcome Message - try: - await member.send(welcome_message) - except discord.errors.Forbidden as catch_dat_forbidden: - logger.debug(f'{member.name} cannot be sent a DM.') - - async def kick_if_unverified(self, member, time_to_kick, logging_channel): - - await sleep(time_to_kick) - - # Start verification timer - if "Needs Approval" in [role.name for role in member.roles]: - # Kick timer, in seconds. - - await sleep(time_to_kick) - - if "Needs Approval" in [role.name for role in member.roles]: - # Log the kick - await logging_channel.send( - f"{member.mention} did not verify, auto-removed." f" ({int((time_to_kick / 3600))} hour/s)") - await member.kick(reason="Did not verify.") - - - - - # NEW LOGIC async def log_unverified_join(self, member, logging_channel): await logging_channel.send(f"<@{member.id}> joined, but has not verified.") @@ -79,23 +30,14 @@ async def kick_if_not_verified(self, member, time_to_kick, logging_channel): f"{member.mention} did not verify after {int((time_to_kick / 3600))} hour/s, auto-removed.") await member.kick(reason="Did not verify.") - - - # EXECUTION @commands.Cog.listener() async def on_member_join(self, member: discord.Member): guild = member.guild - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["verification_log"]) - - if not self.feature_flag: - await self.add_role_and_log(member, logs_channel) - await self.send_welcome_message(guild, member) - await self.kick_if_unverified(member, 3600, logs_channel) + logs_channel = await self.bot.fetch_channel(self.bot.settings.verification["verification_channel"]) - if self.feature_flag: - await self.log_unverified_join(member, logs_channel) - await self.send_welcome_message(guild, member) - await self.kick_if_not_verified(member, 3600, logs_channel) + await self.log_unverified_join(member, logs_channel) + await self.send_welcome_message(guild, member) + await self.kick_if_not_verified(member, 3600, logs_channel) def setup(bot): diff --git a/src/zorak/cogs/admin/verification_on_verified.py b/src/zorak/cogs/admin/verification_on_verified.py index 9514e10f..c87bb3be 100644 --- a/src/zorak/cogs/admin/verification_on_verified.py +++ b/src/zorak/cogs/admin/verification_on_verified.py @@ -43,7 +43,7 @@ async def send_wrong_button_message(self, guild, member): ** _Make sure you press the "Verify me!" button to verify yourself._ ** Please join the server again and try again. - {self.bot.server_settings.server_info['invite']} + {self.bot.settings.info['invite']} """ ) except discord.errors.Forbidden as catch_dat_forbidden: @@ -121,14 +121,14 @@ def __init__(self, bot): @commands.slash_command(description="Verification!") async def verify(self, ctx): """The slash command that initiates the fancy menus.""" - if hasattr(self.bot.server_settings, "verification_options"): - if "selectors" in self.bot.server_settings.verification_options: + if hasattr(self.bot.settings, "verification_options"): + if "selectors" in self.bot.settings.verification_options: if "✅" not in [role.name for role in ctx.author.roles]: await ctx.respond( "# ~ Verification ~ \n" "_Before you can join the server, we need to make sure you are not a robot._\n" "_Please answer the following question._" - , view=SelectView(self.bot, self.bot.server_settings.verification_options) + , view=SelectView(self.bot, self.bot.settings.verification_options) , ephemeral=True ) else: diff --git a/src/zorak/cogs/general/general_help.py b/src/zorak/cogs/general/general_help.py index aa1913dd..c6511acc 100644 --- a/src/zorak/cogs/general/general_help.py +++ b/src/zorak/cogs/general/general_help.py @@ -30,16 +30,16 @@ async def on_timeout(self): async def first_button_callback(self, button, interaction): # staff_role = interaction.guild.get_role(admin_roles["staff"]) embed = discord.Embed( - title=f"{self.server_settings.server_info['name']}", - description=f"**Website** \n{self.server_settings.server_info['website']}\n\n" + title=f"{self.server_settings.info['name']}", + description=f"**Website** \n{self.server_settings.info['website']}\n\n" f"**Owner** \n{interaction.guild.owner.mention}\n\n" # pylint: disable=W1401 - f"**Email** \n{self.server_settings.server_info['email']}\n\n" # pylint: disable=W1401 - f"**Invite Link** \n{self.server_settings.server_info['invite']}\n\n" # pylint: disable=W1401 - f"**Leave a reveiw** \n{self.server_settings.server_info['review']}\n\n" # pylint: disable=W1401 + f"**Email** \n{self.server_settings.info['email']}\n\n" # pylint: disable=W1401 + f"**Invite Link** \n{self.server_settings.info['invite']}\n\n" # pylint: disable=W1401 + f"**Leave a reveiw** \n{self.server_settings.info['review']}\n\n" # pylint: disable=W1401 f"**Questions?** \nMake a ticket using **/ticket**, or send us an email.", color=discord.Color.yellow(), ) - embed.set_thumbnail(url=self.server_settings.server_info["logo"]) + embed.set_thumbnail(url=self.server_settings.info["logo"]) await interaction.response.send_message(embed=embed) @discord.ui.button(label="Running code", row=0, style=discord.ButtonStyle.success) @@ -69,7 +69,7 @@ async def help(self, ctx): A standard slash command. """ logger.info("%s used the %s command.", ctx.author.name, ctx.command) - await ctx.respond("What do you want, human?", view=HelpButtons(self.bot.server_settings, timeout=120)) + await ctx.respond("What do you want, human?", view=HelpButtons(self.bot.settings, timeout=120)) def setup(bot): diff --git a/src/zorak/cogs/general/general_suggest.py b/src/zorak/cogs/general/general_suggest.py deleted file mode 100644 index 5801253a..00000000 --- a/src/zorak/cogs/general/general_suggest.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Adds an embed question, with a thumbsup and thumbsdown emoji -for voting on things. -""" -import logging -import discord -from discord.ext import commands - - -from zorak.utilities.cog_helpers._embeds import embed_suggestions, embed_suggestion_error # pylint: disable=E0401 - - -logger = logging.getLogger(__name__) - - -class GeneralSuggest(commands.Cog): - """ - Adds an embed question, with a thumbsup and thumbsdown emoji - for voting on things. - """ - def __init__(self, bot): - self.bot = bot - - @commands.slash_command() - async def suggest(self, ctx, question): - """ - Adds an embed question, with a thumbsup and thumbsdown emoji - for voting on things. - """ - logger.info("%s used the %s command." - , ctx.author.name - , ctx.command) - - ''' - If the channel name/ID of the command matches with the current - channel, the suggestion will be posted. If not, an error message will occur. - ''' - suggest_channel = await self.bot.fetch_channel(self.bot.server_settings.normal_channel["suggestions_channel"]) - if ctx.channel_id == suggest_channel.id: - await ctx.response.send_message(embed=embed_suggestions(ctx.author, question)) - msg = await ctx.interaction.original_response() - - await msg.add_reaction(emoji="👍") - await msg.add_reaction(emoji="👎") - - else: - await ctx.respond(embed=embed_suggestion_error(suggest_channel)) - - -def setup(bot): - """Required.""" - bot.add_cog(GeneralSuggest(bot)) diff --git a/src/zorak/cogs/general/general_tickets.py b/src/zorak/cogs/general/general_tickets.py index 45c80f6a..c54328d8 100644 --- a/src/zorak/cogs/general/general_tickets.py +++ b/src/zorak/cogs/general/general_tickets.py @@ -25,7 +25,7 @@ async def ticket(self, ctx): logger.info("%s used the %s command.", ctx.author.name, ctx.command) await ctx.respond( "Do you need help, or do you have a question for the Staff?", - view=MakeATicket(self.bot.server_settings), + view=MakeATicket(self.bot.settings), ephemeral=True, ) @@ -49,8 +49,8 @@ async def button_callback(self, button, interaction): button.disabled = True await interaction.edit_original_response(view=self) - support = await interaction.guild.fetch_channel(self.server_settings.mod_channel["server_support"]) - staff = interaction.guild.get_role(self.server_settings.admin_roles["staff"]) + support = await interaction.guild.fetch_channel(self.server_settings.support["server_support"]) + staff = interaction.guild.get_role(self.server_settings.admin["staff"]) ticket = await support.create_thread( name=f"[Ticket] - {interaction.user}", diff --git a/src/zorak/cogs/logging/logging_avatars.py b/src/zorak/cogs/logging/logging_avatars.py index 96ebe276..7691c405 100644 --- a/src/zorak/cogs/logging/logging_avatars.py +++ b/src/zorak/cogs/logging/logging_avatars.py @@ -23,7 +23,7 @@ async def on_user_update(self, before, after): if before.avatar != after.avatar: embed = embed_avatar(before, after) - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_member_ban.py b/src/zorak/cogs/logging/logging_member_ban.py index 34e8b7ce..a63cd335 100644 --- a/src/zorak/cogs/logging/logging_member_ban.py +++ b/src/zorak/cogs/logging/logging_member_ban.py @@ -24,14 +24,14 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - current_guild = self.bot.get_guild(self.bot.server_settings.server_info["id"]) + current_guild = self.bot.get_guild(self.bot.settings.info["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.ban": if audit_log.target == member: embed = embed_ban(member, audit_log) - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_member_kick.py b/src/zorak/cogs/logging/logging_member_kick.py index 156f5c5d..6df3aeaa 100644 --- a/src/zorak/cogs/logging/logging_member_kick.py +++ b/src/zorak/cogs/logging/logging_member_kick.py @@ -24,14 +24,14 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - current_guild = self.bot.get_guild(self.bot.server_settings.server_info["id"]) + current_guild = self.bot.get_guild(self.bot.settings.info["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.kick": if audit_log.target == member: embed = embed_kick(member, audit_log) - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_member_leaving.py b/src/zorak/cogs/logging/logging_member_leaving.py index 2786c60e..29fb249d 100644 --- a/src/zorak/cogs/logging/logging_member_leaving.py +++ b/src/zorak/cogs/logging/logging_member_leaving.py @@ -24,13 +24,13 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - current_guild = self.bot.get_guild(self.bot.server_settings.server_info["id"]) + current_guild = self.bot.get_guild(self.bot.settings.info["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) != "AuditLogAction.ban" and str(audit_log.action) != "AuditLogAction.kick": embed = embed_leave(member) - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["join_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["join_log"]) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_member_roles.py b/src/zorak/cogs/logging/logging_member_roles.py index 9227e0c2..e7eac4ef 100644 --- a/src/zorak/cogs/logging/logging_member_roles.py +++ b/src/zorak/cogs/logging/logging_member_roles.py @@ -23,7 +23,7 @@ async def on_member_update(self, before, after): Checks what roles were changed, and logs it in the log channel. Can be quite spammy. """ - current_guild = self.bot.get_guild(self.bot.server_settings.server_info["id"]) + current_guild = self.bot.get_guild(self.bot.settings.info["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.member_role_update": @@ -31,7 +31,7 @@ async def on_member_update(self, before, after): responsible_member = audit_log.user changed_roles = [] - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) if len(before.roles) > len(after.roles): for role in before.roles: if role not in after.roles: diff --git a/src/zorak/cogs/logging/logging_member_unban.py b/src/zorak/cogs/logging/logging_member_unban.py index 5f10ea28..65dd335e 100644 --- a/src/zorak/cogs/logging/logging_member_unban.py +++ b/src/zorak/cogs/logging/logging_member_unban.py @@ -21,7 +21,7 @@ async def on_member_unban(self, member): """ embed = embed_unban(member) - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_message_delete.py b/src/zorak/cogs/logging/logging_message_delete.py index 0b1f1f57..a583a2c9 100644 --- a/src/zorak/cogs/logging/logging_message_delete.py +++ b/src/zorak/cogs/logging/logging_message_delete.py @@ -23,9 +23,9 @@ async def on_message_delete(self, message): """ If a mod deletes, take the audit log event. If a user deletes, handle it normally. """ - current_guild = self.bot.get_guild(self.bot.server_settings.server_info['id']) + current_guild = self.bot.get_guild(self.bot.settings.info['id']) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["chat_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["chat_log"]) # If the audit log is triggered, it means someone OTHER than the author deleted the message. # https://discordpy.readthedocs.io/en/stable/api.html @@ -40,7 +40,8 @@ async def on_message_delete(self, message): username = message.author for role in message.author.roles: - if role.id in self.bot.server_settings.admin_roles.values(): + # TODO: .admin_roles no longer exists, find a workaround here. + if role.id in self.bot.settings.admin.values(): await logs_channel.send(embed=embed_message_delete(username, message)) return diff --git a/src/zorak/cogs/logging/logging_message_edit.py b/src/zorak/cogs/logging/logging_message_edit.py index bca8489a..6d34ab02 100644 --- a/src/zorak/cogs/logging/logging_message_edit.py +++ b/src/zorak/cogs/logging/logging_message_edit.py @@ -1,12 +1,15 @@ """ Logs when messages are edited. """ +import logging from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import guild_settings from zorak.utilities.cog_helpers._embeds import ( embed_message_edit, # pylint: disable=E0401 ) +logger = logging.getLogger(__name__) class LoggingMessageEdit(commands.Cog): """ @@ -15,9 +18,11 @@ class LoggingMessageEdit(commands.Cog): def __init__(self, bot): self.bot = bot + self.settings = self.bot.settings.server @commands.Cog.listener() async def on_message_edit(self, message_before, message_after): + self.settings = guild_settings(self.settings, message_before.guild) # IGNORE /run, since we will set up an on_message_edit handler there with opposite logic if message_before.content.startswith('/run') or message_after.content.startswith('/run'): @@ -33,13 +38,14 @@ async def on_message_edit(self, message_before, message_after): author = message_before.author for role in message_before.author.roles: - if role.id not in self.bot.server_settings.admin_roles.values(): + # TODO: .admin_roles no longer exists, find a workaround here. + if role.id not in self.settings.admin_roles: # Dont log admin actions. # This just gets really messy when we are cleaning things up # or doing dodgy business in secret places. embed = embed_message_edit(username, author, message_before, message_after) - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["chat_log"]) + logs_channel = await self.bot.fetch_channel(self.settings.chat_log) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_name_changes.py b/src/zorak/cogs/logging/logging_name_changes.py index a34f5cd5..dc8b1a77 100644 --- a/src/zorak/cogs/logging/logging_name_changes.py +++ b/src/zorak/cogs/logging/logging_name_changes.py @@ -35,7 +35,7 @@ async def on_member_update(self, before, after): if before.nick != after.nick and before.nick is not None: embed = embed_name_change(before, after, username_before, username_after) - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await logs_channel.send(f"{username_after.mention}", embed=embed) diff --git a/src/zorak/cogs/logging/logging_tickets.py b/src/zorak/cogs/logging/logging_tickets.py index 9520d1ab..ecd78dec 100644 --- a/src/zorak/cogs/logging/logging_tickets.py +++ b/src/zorak/cogs/logging/logging_tickets.py @@ -24,14 +24,14 @@ async def on_thread_create(self): """ When a thread is created """ - current_guild = self.bot.get_guild(self.bot.server_settings.server_info["id"]) + current_guild = self.bot.get_guild(self.bot.settings.info["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)] entry = audit_log[0] target = "AuditLogAction.thread_create" if str(entry.action) == target and str(entry.target).startswith("[Ticket]"): - mod_log = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) embed = embed_ticket_create(entry.user, entry.target.mention) await mod_log.send(embed=embed) return @@ -41,7 +41,7 @@ async def on_thread_update(self, before): """ When a thread is updated, deleted or removed. """ - current_guild = self.bot.get_guild(self.bot.server_settings.server_info["id"]) + current_guild = self.bot.get_guild(self.bot.settings.info["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)] entry = audit_log[0] @@ -50,19 +50,19 @@ async def on_thread_update(self, before): remove = "AuditLogAction.thread_remove" if str(entry.action) == update and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) embed = embed_ticket_update(entry.user, before.id) await logs_channel.send(embed=embed) return if str(entry.action) == delete and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) embed = embed_ticket_delete(entry.user, before.id) await logs_channel.send(embed=embed) return if str(entry.action) == remove and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) embed = embed_ticket_remove(entry.user, before.id) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/utility/_event_challenges.py b/src/zorak/cogs/utility/_event_challenges.py index cee5d63a..fdc978cf 100644 --- a/src/zorak/cogs/utility/_event_challenges.py +++ b/src/zorak/cogs/utility/_event_challenges.py @@ -39,7 +39,7 @@ async def challenge(self, ctx, day): ) embed.set_thumbnail( url="https://raw.githubusercontent.com/Xarlos89/" - "PracticalPython/main/logo.png" + "prod/main/logo.png" ) embed.add_field( name=f"Challenge #{day}:", value=current_day, inline=True diff --git a/src/zorak/cogs/utility/_rss.py b/src/zorak/cogs/utility/_rss.py index b9bc3bda..c2c81cef 100644 --- a/src/zorak/cogs/utility/_rss.py +++ b/src/zorak/cogs/utility/_rss.py @@ -1,134 +1,134 @@ -""" -Grabs info from an RSS feed, and posts it in the server. TODO Clean - -this cog is retired, and not loaded by the bot. If we want to add the features again, we can. -""" -from asyncio import sleep - -import discord -import feedparser -import html2text -from discord.ext import commands - - -class RSS(commands.Cog): - """ - The main class for the RSS handler. - """ - - def __init__(self, bot): - self.bot = bot - - @commands.Cog.listener() - async def rss_on_ready(self): - """ - This gets called to check if new stories are ready. - """ - - def get_ids(): - """Grabs the most recent article ID from each URL in - the TOML, so that we can check what we have already sent""" - most_recent_ids = [] - - for news_source in self.bot.server_settings.rss_feed.keys(): - news_feed = feedparser.parse(self.bot.server_settings.rss_feed[news_source]) - - id_code = news_feed["entries"][0]["id"] - most_recent_ids.append(id_code) - - return most_recent_ids - - def send_news(id_to_send): - """Uses the RSS ID's we grab from get_IDs that are NOT already in the DB. - Sends out the news story if it is not in our DB. - Each news story is parsed 'slightly' different, which is annoying.""" - - def send_python_software_foundation(id_tag): - newsfeed = feedparser.parse(self.bot.server_settings.rss_feed["Python_Software_foundation"]) - id_code = newsfeed["entries"][0]["id"] - if id_tag == id_code: - # if the ID code in the article matches the ID we grabbed in get_IDs(), send. - html_reader = html2text.HTML2Text() - html_reader.ignore_links = False - - embed = discord.Embed( - title=newsfeed["entries"][0]["title"], - description=f"By: {newsfeed['entries'][0]['authors'][0]['name']}" f" at the Python Software Foundation!", - color=discord.Color.blue(), - ) - - embed.add_field( - name="Preview: ", - value=f"{html_reader.handle(newsfeed['entries'][0]['summary'])[0:1015]}" f" ...", - inline=False, - ) - - embed.add_field( - name="Read more: ", - value=f"[{newsfeed['entries'][0]['link']}]" f"({newsfeed['entries'][0]['link']})", - inline=False, - ) - embed.set_thumbnail(url="https://www.python.org/static/img/python-logo@2x.png") - - return embed - return None - - def send_jetbrains(id_tag): - jetbrains = self.bot.server_settings.rss_feed["jetbrains"] - newsfeed = feedparser.parse(jetbrains) - id_code = newsfeed["entries"][0]["id"] - if id_tag == id_code: - # if the ID code in the article matches the ID we grabbed in get_IDs(), send. - - html_reader = html2text.HTML2Text() - html_reader.ignore_links = False - - # html = html_reader.handle(NewsFeed['entries'][0]['content'][0]['value']) - - embed = discord.Embed( - title=f"**{newsfeed['entries'][0]['title']}**", - description=f"By: **{newsfeed['entries'][0]['author']}** at Jetbrains!", - color=discord.Color.blue(), - ) - - summary_text = f"{newsfeed['entries'][0]['summary'][0:1015]} ..." - embed.add_field(name="**Preview: **", value=summary_text, inline=False) - embed.add_field( - name="**Read more: **", - value=f"[{newsfeed['entries'][0]['link']}]" f"({newsfeed['entries'][0]['link']})", - inline=False, - ) - embed.set_thumbnail(url=newsfeed["entries"][0]["featuredimage"]) - return embed - return None - - embed = send_python_software_foundation(id_to_send) - embed2 = send_jetbrains(id_to_send) - if embed is not None: - return embed - return embed2 - - while True: - sent_id_list = [] - - all_ids = self.bot.db_client.get_all_stories() - for id_feed in all_ids: - sent_id_list.append(id_feed) - - print(sent_id_list) - story_queue = get_ids() - - for entry in story_queue: - if entry not in sent_id_list: - news_channel = await self.bot.fetch_channel(self.bot.server_settings.normal_channel["news_channel"]) - - await news_channel.send(embed=send_news(entry)) - self.bot.db_client.add_story_to_table(entry) - - wait_time_in_seconds = 86400 # 24 hour - await sleep(wait_time_in_seconds) - - -def setup(bot): - """required""" - bot.add_cog(RSS(bot)) +# """ +# Grabs info from an RSS feed, and posts it in the server. TODO Clean +# +# this cog is retired, and not loaded by the bot. If we want to add the features again, we can. +# """ +# from asyncio import sleep +# +# import discord +# import feedparser +# import html2text +# from discord.ext import commands +# +# +# class RSS(commands.Cog): +# """ +# The main class for the RSS handler. +# """ +# +# def __init__(self, bot): +# self.bot = bot +# +# @commands.Cog.listener() +# async def rss_on_ready(self): +# """ +# This gets called to check if new stories are ready. +# """ +# +# def get_ids(): +# """Grabs the most recent article ID from each URL in +# the TOML, so that we can check what we have already sent""" +# most_recent_ids = [] +# +# for news_source in self.bot.server_settings.rss_feed.keys(): +# news_feed = feedparser.parse(self.bot.server_settings.rss_feed[news_source]) +# +# id_code = news_feed["entries"][0]["id"] +# most_recent_ids.append(id_code) +# +# return most_recent_ids +# +# def send_news(id_to_send): +# """Uses the RSS ID's we grab from get_IDs that are NOT already in the DB. +# Sends out the news story if it is not in our DB. +# Each news story is parsed 'slightly' different, which is annoying.""" +# +# def send_python_software_foundation(id_tag): +# newsfeed = feedparser.parse(self.bot.server_settings.rss_feed["Python_Software_foundation"]) +# id_code = newsfeed["entries"][0]["id"] +# if id_tag == id_code: +# # if the ID code in the article matches the ID we grabbed in get_IDs(), send. +# html_reader = html2text.HTML2Text() +# html_reader.ignore_links = False +# +# embed = discord.Embed( +# title=newsfeed["entries"][0]["title"], +# description=f"By: {newsfeed['entries'][0]['authors'][0]['name']}" f" at the Python Software Foundation!", +# color=discord.Color.blue(), +# ) +# +# embed.add_field( +# name="Preview: ", +# value=f"{html_reader.handle(newsfeed['entries'][0]['summary'])[0:1015]}" f" ...", +# inline=False, +# ) +# +# embed.add_field( +# name="Read more: ", +# value=f"[{newsfeed['entries'][0]['link']}]" f"({newsfeed['entries'][0]['link']})", +# inline=False, +# ) +# embed.set_thumbnail(url="https://www.python.org/static/img/python-logo@2x.png") +# +# return embed +# return None +# +# def send_jetbrains(id_tag): +# jetbrains = self.bot.server_settings.rss_feed["jetbrains"] +# newsfeed = feedparser.parse(jetbrains) +# id_code = newsfeed["entries"][0]["id"] +# if id_tag == id_code: +# # if the ID code in the article matches the ID we grabbed in get_IDs(), send. +# +# html_reader = html2text.HTML2Text() +# html_reader.ignore_links = False +# +# # html = html_reader.handle(NewsFeed['entries'][0]['content'][0]['value']) +# +# embed = discord.Embed( +# title=f"**{newsfeed['entries'][0]['title']}**", +# description=f"By: **{newsfeed['entries'][0]['author']}** at Jetbrains!", +# color=discord.Color.blue(), +# ) +# +# summary_text = f"{newsfeed['entries'][0]['summary'][0:1015]} ..." +# embed.add_field(name="**Preview: **", value=summary_text, inline=False) +# embed.add_field( +# name="**Read more: **", +# value=f"[{newsfeed['entries'][0]['link']}]" f"({newsfeed['entries'][0]['link']})", +# inline=False, +# ) +# embed.set_thumbnail(url=newsfeed["entries"][0]["featuredimage"]) +# return embed +# return None +# +# embed = send_python_software_foundation(id_to_send) +# embed2 = send_jetbrains(id_to_send) +# if embed is not None: +# return embed +# return embed2 +# +# while True: +# sent_id_list = [] +# +# all_ids = self.bot.db_client.get_all_stories() +# for id_feed in all_ids: +# sent_id_list.append(id_feed) +# +# print(sent_id_list) +# story_queue = get_ids() +# +# for entry in story_queue: +# if entry not in sent_id_list: +# news_channel = await self.bot.fetch_channel(self.bot.server_settings.normal_channel["news_channel"]) +# +# await news_channel.send(embed=send_news(entry)) +# self.bot.db_client.add_story_to_table(entry) +# +# wait_time_in_seconds = 86400 # 24 hour +# await sleep(wait_time_in_seconds) +# +# +# def setup(bot): +# """required""" +# bot.add_cog(RSS(bot)) diff --git a/src/zorak/cogs/utility/points.py b/src/zorak/cogs/utility/points.py index 16d34d02..7c705f13 100644 --- a/src/zorak/cogs/utility/points.py +++ b/src/zorak/cogs/utility/points.py @@ -41,7 +41,7 @@ async def on_message(self, message: discord.Message): async def on_message_delete(self, message: discord.Message): """When a member deletes a message, remove a point.""" message_value = len(message.content.split(" ")) - mod_log = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await mod_log.send(f"{message_value} Point/s removed from {message.author} for deleting a message.") self.bot.db_client.remove_points_from_user(message.author.id, abs(message_value)) # @@ -66,7 +66,7 @@ async def add_points_to_user(self, ctx, mention, points): """Add points to a user.""" user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.add_points_to_user(user.id, int(points)) - mod_log = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await mod_log.send(f"{points} point{('s', '')[abs(int(points)) == 1]} added to {mention} by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(int(points)) == 1]} added to {mention}.") @@ -75,7 +75,7 @@ async def add_points_to_user(self, ctx, mention, points): async def add_points_to_all_users(self, ctx, points): """Add points to all users.""" self.bot.db_client.add_points_to_all_users(int(points)) - mod_log = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await mod_log.send(f"{points} point{('s', '')[abs(int(points)) == 1]} added to all users by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(int(points)) == 1]} added to all users.") @@ -87,7 +87,7 @@ async def remove_points_from_user(self, ctx, mention, points): points = int(points) user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.remove_points_from_user(user.id, points) - mod_log = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await mod_log.send(f"{points} point{('s', '')[abs(points) == 1]} removed from {mention} by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(points) == 1]} removed from {mention}.") @@ -97,7 +97,7 @@ async def remove_points_from_all_users(self, ctx, points): """Remove points from all users.""" points = int(points) self.bot.db_client.remove_points_from_all_users(points) - mod_log = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await mod_log.send(f"{points} point{('s', '')[abs(points) == 1]} removed from all users by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(points) == 1]} removed from all users.") @@ -108,7 +108,7 @@ async def reset_points_for_user(self, ctx, mention): mention = str(mention) user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.set_user_points(user.id, 0) - mod_log = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await mod_log.send(f"Points reset for {mention} by {ctx.author}.") await ctx.respond(f"Points reset for {mention}.") @@ -117,7 +117,7 @@ async def reset_points_for_user(self, ctx, mention): async def reset_points_for_all_users(self, ctx): """Reset points for all users.""" self.bot.db_client.set_all_user_points(0) - mod_log = await self.bot.fetch_channel(self.bot.server_settings.log_channel["mod_log"]) + mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) await mod_log.send(f"Points reset for all users by {ctx.author}.") await ctx.respond("Points reset for all users.") @@ -135,14 +135,15 @@ async def leaderboard(self, ctx): def is_staff(member_obj): """ Tells us if the 'member_obj' has an admin role. """ - for role in self.bot.server_settings.admin_roles: - if self.bot.server_settings.admin_roles[role] in [y.id for y in member_obj.roles]: + # TODO: .admin_roles no longer exists, find a workaround here. + for role in self.bot.settings.admin: + if self.bot.settings.admin[role] in [y.id for y in member_obj.roles]: return True return False top10_no_staff = [] points = self.bot.db_client.get_top_10() - guild = self.bot.get_guild(self.bot.server_settings.server_info['id']) + guild = self.bot.get_guild(self.bot.settings.info['id']) for iteration, person in enumerate(points): if len(top10_no_staff) < 10: # should only allow 10 people into the list @@ -152,8 +153,8 @@ def is_staff(member_obj): else: return - embed = embed_leaderboard(top10_no_staff, self.bot.server_settings.server_info['name'], - self.bot.server_settings.server_info['logo']) + embed = embed_leaderboard(top10_no_staff, self.bot.settings.info['name'], + self.bot.settings.info['logo']) await ctx.respond(embed=embed) diff --git a/src/zorak/utilities/cog_helpers/guild_settings.py b/src/zorak/utilities/cog_helpers/guild_settings.py new file mode 100644 index 00000000..c2580458 --- /dev/null +++ b/src/zorak/utilities/cog_helpers/guild_settings.py @@ -0,0 +1,83 @@ +import logging + + +logger = logging.getLogger(__name__) + + +class guild_settings(): + def __init__(self, settings, guild): + self.settings = settings + self.guild_name = guild + self.guild_id = str(guild.id) + self.guild_settings = self.settings[self.guild_id] + + if self.guild_id not in self.settings: + logger.warning(f"No settings found for guild: {self.guild_id}") + if self.guild_settings is None: + logger.warning(f"No settings found for guild: {self.guild_id}") + + # All Channel information for guilds + try: + self.general_channels = self.guild_settings["channels"]["general"] # has sub-channels + self.quarantine_channel = self.guild_settings["channels"]["quarantine"]["quarantine_channel"] # Explicit + self.support_channel = self.guild_settings["channels"]["support"]["server_support"] # Explicit + self.verification_channel = self.guild_settings["channels"]["verification"]["verification_channel"] # Explicit + except Exception as e: + logger.warning(f"Failed to grab channel info. Error: {e}") + self.general_channels = None + self.quarantine_channel = None + self.support_channel = None + self.verification_channel = None + + # All Logging channel information for guilds + try: + self.chat_log = self.guild_settings["channels"]["logging"]["chat_log"] + self.error_log =self.guild_settings["channels"]["logging"]["zorak_log"] + self.join_log = self.guild_settings["channels"]["logging"]["join_log"] + self.mod_log =self.guild_settings["channels"]["logging"]["mod_log"] + self.server_log =self.guild_settings["channels"]["logging"]["server_change_log"] + self.user_log = self.guild_settings["channels"]["logging"]["user_log"] + self.verification_log =self.guild_settings["channels"]["logging"]["verification_log"] + except Exception as e: + logger.warning(f"Failed to grab logging channels. Error: {e}") + self.chat_log = None + self.error_log = None + self.join_log = None + self.mod_log = None + self.server_log = None + self.user_log = None + self.verification_log = None + + # All Role information for guilds + try: + self.admin_roles = self.guild_settings["roles"]["admin"] # has sub-roles + self.reaction_roles = self.guild_settings["roles"]["reaction"] # has sub-roles + self.punishment_role = self.guild_settings["roles"]["punishment"]["naughty"] # explicit + self.verified_role = self.guild_settings["roles"]["verified"]["verified"] # explicit + except Exception as e: + logger.warning(f"Failed to grab role IDs. Error: {e}") + self.admin_roles = None + self.reaction_roles = None + self.punishment_role = None + self.verified_role = None + + # All General information for guilds + try: + self.info = self.guild_settings["info"] + except Exception as e: + logger.warning(f"Failed to grab server info. Error: {e}") + self.info = None + + + + + + + + + + + + + + diff --git a/src/zorak/utilities/core/README.md b/src/zorak/utilities/core/README.md index c4fb2ff2..6b0f6e26 100644 --- a/src/zorak/utilities/core/README.md +++ b/src/zorak/utilities/core/README.md @@ -12,3 +12,15 @@ Contains a function to abstract the configuration and instatiation of Python's b ### mongo.py Contains a class that implements a MongoDB client and abstracts a number of commonly used functions for ease of use. + +### channels.py +Contains the class for turning channels into channel IDs + +### info.py +Contains the class for getting information about a server. + +### log.py +Contains the class for logging channel IDs, and logging options + +### roles.py +Contains the class for roles and role IDs diff --git a/src/zorak/utilities/core/logging_utils.py b/src/zorak/utilities/core/logging_options.py similarity index 100% rename from src/zorak/utilities/core/logging_utils.py rename to src/zorak/utilities/core/logging_options.py diff --git a/src/zorak/utilities/core/server_settings.py b/src/zorak/utilities/core/server_settings.py deleted file mode 100644 index 257388da..00000000 --- a/src/zorak/utilities/core/server_settings.py +++ /dev/null @@ -1,65 +0,0 @@ -import logging -import os - -import toml - -logger = logging.getLogger(__name__) - - -class Settings: - def __init__(self, settings_path): - server_settings_path = os.path.join(settings_path, "channel_info.toml") - try: - server_settings = toml.load(server_settings_path) - - # Server - self.server_info = server_settings["server"]["info"] - - # Channels - self.channels = server_settings["channels"] - self.mod_channel = self.channels["moderation"] - self.log_channel = self.channels["log_channel"] - self.normal_channel = self.channels["normal_channel"] - - # Roles - self.user_roles = server_settings["user_roles"] - self.admin_roles = self.user_roles["admin"] - self.elevated_roles = self.user_roles["elevated"] - self.badboi_role = self.user_roles["bad"] - self.verified_role = self.user_roles["verified"] - self.fun_roles = self.user_roles["fun"] - self.employment_roles = self.user_roles["employment"] - - # RSS Feeds - self.feeds = server_settings["rss_feeds"] - self.rss_feed = self.feeds["links"] - except Exception as e: - logger.warning(f"Failed to grab server info. No file under {server_settings_path}") - self.server_info = None - self.channels = None - self.mod_channel = None - self.log_channel = None - self.normal_channel = None - self.user_roles = None - self.admin_roles = None - self.elevated_roles = None - self.badboi_role = None - self.verified_role = None - self.fun_roles = None - self.employment_roles = None - self.feeds = None - self.rss_feed = None - - reaction_role_config_path = os.path.join(settings_path, "reaction_roles.toml") - try: - self.reaction_role_data = toml.load(reaction_role_config_path) - except Exception as e: - self.reaction_role_data = None - logger.warning(f"Failed to grab reaction roles. No file under {reaction_role_config_path}") - - verification_path = os.path.join(settings_path, "verification_options.toml") - try: - self.verification_options = toml.load(verification_path) - except Exception as f: - self.verification_options = None - logger.warning(f"Failed to grab verification options. No file under {reaction_role_config_path}") diff --git a/src/zorak/utilities/core/settings.py b/src/zorak/utilities/core/settings.py new file mode 100644 index 00000000..61bc00c0 --- /dev/null +++ b/src/zorak/utilities/core/settings.py @@ -0,0 +1,42 @@ +import logging +import os +import toml +import json + + +logger = logging.getLogger(__name__) + + +class Settings: + def __init__(self, settings_path, all_guilds): + + if all_guilds is None: + logger.warning("Settings were triggered, but bot has no guilds!") + return + + + self.settings_path = os.path.join(settings_path, "FAKE_DB_settings.json") + self.reactions_path = os.path.join(settings_path, "reaction_roles.toml") + self.reactions_path = os.path.join(settings_path, "reaction_roles.toml") + self.verification_path = os.path.join(settings_path, "verification_options.toml") + + + with open(self.settings_path, 'r') as f: + server_settings = json.load(f) + self.server = server_settings + + + # Reaction Roles + try: + self.reaction_role_data = toml.load(self.reactions_path) + except Exception as e: + self.reaction_role_data = None + logger.warning(f"Failed to grab reaction roles. No file under {self.reactions_path}") + + # Verification Options + try: + self.verification_options = toml.load(self.verification_path) + + except Exception as f: + logger.warning(f"Failed to grab verification options. No file under {self.reactions_path}") + self.verification_options = None From 7b31066f70e78f01622ae2c41f2ce6191fc22a6a Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:29:02 +0200 Subject: [PATCH 02/38] Applied guild settings to Logging files --- src/zorak/cogs/logging/logging_avatars.py | 7 +++++-- src/zorak/cogs/logging/logging_member_ban.py | 7 +++++-- src/zorak/cogs/logging/logging_member_kick.py | 6 ++++-- .../cogs/logging/logging_member_leaving.py | 6 ++++-- src/zorak/cogs/logging/logging_member_roles.py | 6 ++++-- src/zorak/cogs/logging/logging_member_unban.py | 4 +++- .../cogs/logging/logging_message_delete.py | 14 +++++++++----- src/zorak/cogs/logging/logging_message_edit.py | 11 ++++------- src/zorak/cogs/logging/logging_name_changes.py | 5 ++++- src/zorak/cogs/logging/logging_tickets.py | 18 +++++++++++------- .../utilities/cog_helpers/guild_settings.py | 2 +- 11 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/zorak/cogs/logging/logging_avatars.py b/src/zorak/cogs/logging/logging_avatars.py index 7691c405..9b39b410 100644 --- a/src/zorak/cogs/logging/logging_avatars.py +++ b/src/zorak/cogs/logging/logging_avatars.py @@ -4,6 +4,7 @@ """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_avatar # pylint: disable=E0401 @@ -11,19 +12,21 @@ class LoggingAvatars(commands.Cog): """ Simple listener to on_user_update """ - def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_user_update(self, before, after): + """ if the avatar before is != to the avatar after, do stuff. """ + settings = GuildSettings(self.bot.settings.server, before.guild) + if before.avatar != after.avatar: embed = embed_avatar(before, after) - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_member_ban.py b/src/zorak/cogs/logging/logging_member_ban.py index a63cd335..4e109027 100644 --- a/src/zorak/cogs/logging/logging_member_ban.py +++ b/src/zorak/cogs/logging/logging_member_ban.py @@ -3,6 +3,7 @@ """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_ban # pylint: disable=E0401 @@ -24,14 +25,16 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - current_guild = self.bot.get_guild(self.bot.settings.info["id"]) + settings = GuildSettings(self.bot.settings.server, member.guild) + current_guild = self.bot.get_guild(member.guild) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] + if str(audit_log.action) == "AuditLogAction.ban": if audit_log.target == member: embed = embed_ban(member, audit_log) - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_member_kick.py b/src/zorak/cogs/logging/logging_member_kick.py index 6df3aeaa..1d3974ac 100644 --- a/src/zorak/cogs/logging/logging_member_kick.py +++ b/src/zorak/cogs/logging/logging_member_kick.py @@ -3,6 +3,7 @@ """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_kick # pylint: disable=E0401 @@ -24,14 +25,15 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - current_guild = self.bot.get_guild(self.bot.settings.info["id"]) + settings = GuildSettings(self.bot.settings.server, member.guild) + current_guild = self.bot.get_guild(member.guild) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.kick": if audit_log.target == member: embed = embed_kick(member, audit_log) - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_member_leaving.py b/src/zorak/cogs/logging/logging_member_leaving.py index 29fb249d..9fafe34a 100644 --- a/src/zorak/cogs/logging/logging_member_leaving.py +++ b/src/zorak/cogs/logging/logging_member_leaving.py @@ -3,6 +3,7 @@ """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_leave # pylint: disable=E0401 @@ -24,13 +25,14 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - current_guild = self.bot.get_guild(self.bot.settings.info["id"]) + settings = GuildSettings(self.bot.settings.server, member.guild) + current_guild = self.bot.get_guild(member.guild) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) != "AuditLogAction.ban" and str(audit_log.action) != "AuditLogAction.kick": embed = embed_leave(member) - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["join_log"]) + logs_channel = await self.bot.fetch_channel(settings.join_logs) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_member_roles.py b/src/zorak/cogs/logging/logging_member_roles.py index e7eac4ef..4b063b67 100644 --- a/src/zorak/cogs/logging/logging_member_roles.py +++ b/src/zorak/cogs/logging/logging_member_roles.py @@ -3,6 +3,7 @@ """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( # pylint: disable=E0401 embed_role_add, embed_role_remove, @@ -23,7 +24,8 @@ async def on_member_update(self, before, after): Checks what roles were changed, and logs it in the log channel. Can be quite spammy. """ - current_guild = self.bot.get_guild(self.bot.settings.info["id"]) + settings = GuildSettings(self.bot.settings.server, before.guild) + current_guild = self.bot.get_guild(before.guild) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.member_role_update": @@ -31,7 +33,7 @@ async def on_member_update(self, before, after): responsible_member = audit_log.user changed_roles = [] - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) if len(before.roles) > len(after.roles): for role in before.roles: if role not in after.roles: diff --git a/src/zorak/cogs/logging/logging_member_unban.py b/src/zorak/cogs/logging/logging_member_unban.py index 65dd335e..a6f180c7 100644 --- a/src/zorak/cogs/logging/logging_member_unban.py +++ b/src/zorak/cogs/logging/logging_member_unban.py @@ -3,6 +3,7 @@ """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_unban # pylint: disable=E0401 @@ -20,8 +21,9 @@ async def on_member_unban(self, member): Just listen for the event, embed it, and send it off. """ embed = embed_unban(member) + settings = GuildSettings(self.bot.settings.server, member.guild) - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_message_delete.py b/src/zorak/cogs/logging/logging_message_delete.py index a583a2c9..a8b9c68f 100644 --- a/src/zorak/cogs/logging/logging_message_delete.py +++ b/src/zorak/cogs/logging/logging_message_delete.py @@ -2,12 +2,15 @@ logs when a message is deleted. """ from datetime import datetime - +import logging import discord from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_message_delete +logger = logging.getLogger(__name__) + class LoggingMessageDelete(commands.Cog): """ @@ -23,14 +26,15 @@ async def on_message_delete(self, message): """ If a mod deletes, take the audit log event. If a user deletes, handle it normally. """ - current_guild = self.bot.get_guild(self.bot.settings.info['id']) + settings = GuildSettings(self.bot.settings.server, message.guild) + current_guild = message.guild audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["chat_log"]) + logs_channel = await self.bot.fetch_channel(settings.chat_log) # If the audit log is triggered, it means someone OTHER than the author deleted the message. # https://discordpy.readthedocs.io/en/stable/api.html # ?highlight=audit%20log#discord.AuditLogAction.message_delete - if str(audit_log.action) == 'AuditLogAction.message_delete': + if str(audit_log.action) == 'AuditLogAction.message_delete' and audit_log.user == message.author: embed = embed_message_delete(audit_log.user, message) await logs_channel.send(embed=embed) @@ -41,7 +45,7 @@ async def on_message_delete(self, message): for role in message.author.roles: # TODO: .admin_roles no longer exists, find a workaround here. - if role.id in self.bot.settings.admin.values(): + if role.id in settings.admin_roles.values(): await logs_channel.send(embed=embed_message_delete(username, message)) return diff --git a/src/zorak/cogs/logging/logging_message_edit.py b/src/zorak/cogs/logging/logging_message_edit.py index 6d34ab02..256bc5cf 100644 --- a/src/zorak/cogs/logging/logging_message_edit.py +++ b/src/zorak/cogs/logging/logging_message_edit.py @@ -4,7 +4,7 @@ import logging from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import guild_settings +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( embed_message_edit, # pylint: disable=E0401 ) @@ -18,11 +18,10 @@ class LoggingMessageEdit(commands.Cog): def __init__(self, bot): self.bot = bot - self.settings = self.bot.settings.server @commands.Cog.listener() async def on_message_edit(self, message_before, message_after): - self.settings = guild_settings(self.settings, message_before.guild) + settings = GuildSettings(self.bot.settings.server, message_before.guild) # IGNORE /run, since we will set up an on_message_edit handler there with opposite logic if message_before.content.startswith('/run') or message_after.content.startswith('/run'): @@ -38,14 +37,12 @@ async def on_message_edit(self, message_before, message_after): author = message_before.author for role in message_before.author.roles: - # TODO: .admin_roles no longer exists, find a workaround here. - if role.id not in self.settings.admin_roles: + if role.id not in settings.admin_roles.values(): # Dont log admin actions. # This just gets really messy when we are cleaning things up # or doing dodgy business in secret places. - embed = embed_message_edit(username, author, message_before, message_after) - logs_channel = await self.bot.fetch_channel(self.settings.chat_log) + logs_channel = await self.bot.fetch_channel(settings.chat_log) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_name_changes.py b/src/zorak/cogs/logging/logging_name_changes.py index dc8b1a77..5894659b 100644 --- a/src/zorak/cogs/logging/logging_name_changes.py +++ b/src/zorak/cogs/logging/logging_name_changes.py @@ -3,6 +3,7 @@ """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( # pylint: disable=E0401 embed_name_change, embed_verified_success, @@ -22,6 +23,8 @@ async def on_member_update(self, before, after): """ Just checking if the name before is != to the name after. """ + settings = GuildSettings(self.bot.settings.server, before.guild) + if before.nick is None: username_before = before else: @@ -35,7 +38,7 @@ async def on_member_update(self, before, after): if before.nick != after.nick and before.nick is not None: embed = embed_name_change(before, after, username_before, username_after) - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) await logs_channel.send(f"{username_after.mention}", embed=embed) diff --git a/src/zorak/cogs/logging/logging_tickets.py b/src/zorak/cogs/logging/logging_tickets.py index ecd78dec..b2171b7e 100644 --- a/src/zorak/cogs/logging/logging_tickets.py +++ b/src/zorak/cogs/logging/logging_tickets.py @@ -3,6 +3,7 @@ """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( # pylint: disable=E0401 embed_ticket_create, embed_ticket_delete, @@ -20,18 +21,20 @@ def __init__(self, bot): self.bot = bot @commands.Cog.listener() - async def on_thread_create(self): + async def on_thread_create(self, thread): """ When a thread is created """ - current_guild = self.bot.get_guild(self.bot.settings.info["id"]) + settings = GuildSettings(self.bot.settings.server, thread.guild) + + current_guild = thread.guild audit_log = [entry async for entry in current_guild.audit_logs(limit=1)] entry = audit_log[0] target = "AuditLogAction.thread_create" if str(entry.action) == target and str(entry.target).startswith("[Ticket]"): - mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + mod_log = await self.bot.fetch_channel(settings.mod_log) embed = embed_ticket_create(entry.user, entry.target.mention) await mod_log.send(embed=embed) return @@ -41,7 +44,8 @@ async def on_thread_update(self, before): """ When a thread is updated, deleted or removed. """ - current_guild = self.bot.get_guild(self.bot.settings.info["id"]) + settings = GuildSettings(self.bot.settings.server, before.guild) + current_guild = before.guild audit_log = [entry async for entry in current_guild.audit_logs(limit=1)] entry = audit_log[0] @@ -50,19 +54,19 @@ async def on_thread_update(self, before): remove = "AuditLogAction.thread_remove" if str(entry.action) == update and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) embed = embed_ticket_update(entry.user, before.id) await logs_channel.send(embed=embed) return if str(entry.action) == delete and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) embed = embed_ticket_delete(entry.user, before.id) await logs_channel.send(embed=embed) return if str(entry.action) == remove and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) embed = embed_ticket_remove(entry.user, before.id) await logs_channel.send(embed=embed) return diff --git a/src/zorak/utilities/cog_helpers/guild_settings.py b/src/zorak/utilities/cog_helpers/guild_settings.py index c2580458..d305433d 100644 --- a/src/zorak/utilities/cog_helpers/guild_settings.py +++ b/src/zorak/utilities/cog_helpers/guild_settings.py @@ -4,7 +4,7 @@ logger = logging.getLogger(__name__) -class guild_settings(): +class GuildSettings(): def __init__(self, settings, guild): self.settings = settings self.guild_name = guild From c0309570b5661535228f61bc68a85f970575fca4 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 08:54:18 +0200 Subject: [PATCH 03/38] Oopsie in guild_settings.py --- src/zorak/utilities/cog_helpers/guild_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zorak/utilities/cog_helpers/guild_settings.py b/src/zorak/utilities/cog_helpers/guild_settings.py index d305433d..02c2aad6 100644 --- a/src/zorak/utilities/cog_helpers/guild_settings.py +++ b/src/zorak/utilities/cog_helpers/guild_settings.py @@ -4,7 +4,7 @@ logger = logging.getLogger(__name__) -class GuildSettings(): +class GuildSettings: def __init__(self, settings, guild): self.settings = settings self.guild_name = guild From dfb36429541a767497a4091697e5843b805fe1ff Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 08:54:50 +0200 Subject: [PATCH 04/38] Set up Automoderation to be guild-specific, not only in moderation, but in role/channel options --- .../cogs/admin/admin_automod_spam_messages.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/zorak/cogs/admin/admin_automod_spam_messages.py b/src/zorak/cogs/admin/admin_automod_spam_messages.py index d433c563..ce7c1457 100644 --- a/src/zorak/cogs/admin/admin_automod_spam_messages.py +++ b/src/zorak/cogs/admin/admin_automod_spam_messages.py @@ -7,6 +7,7 @@ import discord.errors from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( embed_spammer, # pylint: disable=E0401 embed_spammer_warn # pylint: disable=E0401 @@ -39,9 +40,16 @@ async def on_message(self, message): if isinstance(message.channel, discord.DMChannel): return + settings = GuildSettings(self.bot.settings.server, message.guild) + # new speaker. Welcome to auto mod. - if message.author.id not in self.records: - self.records[message.author.id] = { + if message.guild.id not in self.records: + self.records[message.guild.id] = {} + + guild_record = self.records[message.guild.id] + + if message.author.id not in guild_record: + guild_record[message.author.id] = { "last_message": message.content , "occurrence": 1 , "1st": {"message_id": message.id, "channel_id": message.channel.id} @@ -52,7 +60,7 @@ async def on_message(self, message): # Old speaker. We are watching you... else: # Check if the last message is the same as the new one. - the_archive = self.records[message.author.id] + the_archive = guild_record[message.author.id] if the_archive["last_message"] == message.content: # If so, increase the occurance by 1 @@ -93,10 +101,9 @@ async def on_message(self, message): # timeout right away await message.author.timeout(until=datetime.utcnow() + timedelta(seconds=30)) - naughty = message.author.guild.get_role(self.bot.settings.punishment["naughty"]) - verified = message.author.guild.get_role(self.bot.settings.verified["verified"]) - quarantine = await self.bot.fetch_channel( - self.bot.settings.quarantine["quarantine_channel"]) + naughty = message.author.guild.get_role(settings.punishment_role) + verified = message.author.guild.get_role(settings.verified_role) + quarantine = await self.bot.fetch_channel(settings.quarantine_channel) # assign Naughty roll member = message.author From efe67e7036cd315f5976009052885dd0ce9c1e5c Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:01:45 +0200 Subject: [PATCH 05/38] checking for a staff role is unnecessary when we check for ban_members, and makes this cog multi-guild acceptable --- src/zorak/cogs/admin/admin_ban.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/zorak/cogs/admin/admin_ban.py b/src/zorak/cogs/admin/admin_ban.py index ac1b7c5f..e7836076 100644 --- a/src/zorak/cogs/admin/admin_ban.py +++ b/src/zorak/cogs/admin/admin_ban.py @@ -23,7 +23,6 @@ def __init__(self, bot): @commands.slash_command(description="Ban a user.") @commands.has_permissions(ban_members=True) - @commands.has_role("Staff") async def ban_member(self, ctx, target: discord.Member, reason): """ Take in a user mention, and a string reason. @@ -42,7 +41,9 @@ async def ban_member(self, ctx, target: discord.Member, reason): await target.ban(reason=f"{ctx.author.name} - {reason}") logger.info("{%s} banned {%s}. Reason: {%s}", ctx.author.name, target.name, reason) # Then we publicly announce what happened. - await ctx.respond(embed=embed_cant_do_that(f"**{ctx.author.name}** banned **{target.name}**" f"\n**Reason:** {reason}")) + await ctx.respond( + embed=embed_cant_do_that(f"**{ctx.author.name}** banned **{target.name}**" f"\n" + f"**Reason:** {reason}")) else: await ctx.respond(embed=embed_cant_do_that("You can't ban an Admin."), ephemeral=True) From 97ac63264c4d1b9f86406dcfe9e92e2454e9f55f Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:04:15 +0200 Subject: [PATCH 06/38] checking for a staff role is unnecessary when we check for manage_messages, and makes this cog multi-guild acceptable --- .../cogs/admin/admin_delete_user_messages.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/zorak/cogs/admin/admin_delete_user_messages.py b/src/zorak/cogs/admin/admin_delete_user_messages.py index a5eb6c66..317dd58d 100644 --- a/src/zorak/cogs/admin/admin_delete_user_messages.py +++ b/src/zorak/cogs/admin/admin_delete_user_messages.py @@ -1,6 +1,5 @@ """ Admin command for deleting a users historical messages -TODO: Finish this cog. It is currently named with a _ prefix so that it is not loaded. """ import logging import time @@ -26,7 +25,6 @@ def __init__(self, bot): @commands.slash_command(description="Deletes all messages from a user over a timeperiod in minutes.") @commands.has_permissions(manage_messages=True) - @commands.has_role("Staff") async def delete_messages(self, ctx, target: discord.Member, minutes): """ Take in a user, and a timeperiod in minutes. @@ -35,15 +33,15 @@ async def delete_messages(self, ctx, target: discord.Member, minutes): counter = 0 time_ago = datetime.utcnow() - timedelta(minutes=int(minutes)) - for guild in self.bot.guilds: - for channel in guild.text_channels: - async for message in channel.history(limit=300, after=time_ago): - if message.author.id == target.id: - await message.delete() - time.sleep(0.3) - counter += 1 + for channel in ctx.guild.text_channels: + async for message in channel.history(limit=300, after=time_ago): + if message.author.id == target.id: + await message.delete() + time.sleep(0.2) + counter += 1 - await ctx.followup.send(embed=embed_cant_do_that(f"{ctx.author.name} deleted {str(counter)} messages by {target.name}.")) + await ctx.followup.send( + embed=embed_cant_do_that(f"{ctx.author.name} deleted {str(counter)} messages by {target.name}.")) def setup(bot): From e40acd033649f110beff88e31039846f0f5deacb Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:05:51 +0200 Subject: [PATCH 07/38] checking for a staff role is unnecessary when we check for kick_members, and makes this cog multi-guild acceptable --- src/zorak/cogs/admin/admin_kick.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/zorak/cogs/admin/admin_kick.py b/src/zorak/cogs/admin/admin_kick.py index 52dc5e4c..f81cd47d 100644 --- a/src/zorak/cogs/admin/admin_kick.py +++ b/src/zorak/cogs/admin/admin_kick.py @@ -23,7 +23,6 @@ def __init__(self, bot): @commands.slash_command(description="Kick a user.") @commands.has_permissions(kick_members=True) - @commands.has_role("Staff") async def kick_member(self, ctx, target: discord.Member, reason): """ Take in a user mention, and a string reason. @@ -42,7 +41,9 @@ async def kick_member(self, ctx, target: discord.Member, reason): await target.kick(reason=f"{ctx.author.name} - {reason}") logger.info("{%s} kicked {%s}. Reason: {%s}", ctx.author.name, target.name, reason) # Then we publicly announce what happened. - await ctx.respond(embed=embed_cant_do_that(f"**{ctx.author.name}** kicked **{target.name}**" f"\n**Reason:** {reason}")) + await ctx.respond( + embed=embed_cant_do_that(f"**{ctx.author.name}** kicked **{target.name}**" f"\n" + f"**Reason:** {reason}")) else: await ctx.respond(embed=embed_cant_do_that("You can't kick an Admin."), ephemeral=True) From a3835dda731375401e2627a362e1fd335627a981 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:06:22 +0200 Subject: [PATCH 08/38] checking for a staff role is unnecessary when we check for moderate_members, and makes this cog multi-guild acceptable --- src/zorak/cogs/admin/admin_mute.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zorak/cogs/admin/admin_mute.py b/src/zorak/cogs/admin/admin_mute.py index 22a6ef7a..6dfab3e7 100644 --- a/src/zorak/cogs/admin/admin_mute.py +++ b/src/zorak/cogs/admin/admin_mute.py @@ -24,7 +24,6 @@ def __init__(self, bot): @commands.slash_command(description="Mute a user.") @commands.has_permissions(moderate_members=True) - @commands.has_role("Staff") async def mute_member(self, ctx, target: discord.Member, time, reason): """ Take in a user mention, and a string reason. From 4677e42f9dbee56d4ca76df45fed28bda1fa5868 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:08:47 +0200 Subject: [PATCH 09/38] checking for a staff role is unnecessary when we check for moderate_members and manage_messages, and makes this cog multi-guild acceptable --- src/zorak/cogs/admin/admin_purge.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/zorak/cogs/admin/admin_purge.py b/src/zorak/cogs/admin/admin_purge.py index 03857414..e188b6b4 100644 --- a/src/zorak/cogs/admin/admin_purge.py +++ b/src/zorak/cogs/admin/admin_purge.py @@ -2,12 +2,12 @@ Admin command to remove messages in bulk. """ from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings class AdminPurge(commands.Cog): """ We are limited to 100 messages per command by Discord API - TODO: This command should be hidden from non-staff users. """ def __init__(self, bot): @@ -15,17 +15,18 @@ def __init__(self, bot): @commands.slash_command(description="Removes up to 100 messages from channel.") @commands.has_permissions(manage_messages=True) - @commands.has_role("Staff") + @commands.has_permissions(moderate_members=True) async def purge_messages(self, ctx, number_messages): """ We currently have permissions on this command set, which throws an error when the user does not have the correct perms. We handle this with an error_handler block """ + settings = GuildSettings(self.bot.settings.server, ctx.guild) # removes the need for a response await ctx.defer() - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) # Welcome channel + logs_channel = await self.bot.fetch_channel(settings.mod_log) # Welcome channel # Do the purge await ctx.channel.purge(limit=int(number_messages)) From 01262b3d9201e078fef61bf5e1e074f08a159266 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:13:56 +0200 Subject: [PATCH 10/38] Dont know how I feel about this. Might be better to send all logs directly to the "support server" --- src/zorak/cogs/admin/error_handler.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/zorak/cogs/admin/error_handler.py b/src/zorak/cogs/admin/error_handler.py index 3de40f58..1d1e4bda 100644 --- a/src/zorak/cogs/admin/error_handler.py +++ b/src/zorak/cogs/admin/error_handler.py @@ -3,7 +3,7 @@ import discord from discord.ext import commands from datetime import datetime - +from zorak.utilities.cog_helpers.guild_settings import GuildSettings logger = logging.getLogger(__name__) @@ -11,11 +11,12 @@ class error_handler(commands.Cog): def __init__(self, bot): self.bot = bot - self.error_channel = self.bot.settings.channels["zorak_log"] @commands.Cog.listener() async def on_application_command_error(self, ctx, error): - error_log = await self.bot.fetch_channel(self.error_channel) + settings = GuildSettings(self.bot.settings.server, ctx.guild) + + error_log = await self.bot.fetch_channel(settings.error_log) # # This is just an interesting way of handling errors PER ERROR. # # For now, let's just catch all and redirect to logs and channel From d84be892ad50549efe7a90989996e92d303322f1 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:15:56 +0200 Subject: [PATCH 11/38] Added server settings to make this a multi-guild thing --- src/zorak/cogs/admin/moderation_invites.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zorak/cogs/admin/moderation_invites.py b/src/zorak/cogs/admin/moderation_invites.py index b5cab84a..bc8d45a1 100644 --- a/src/zorak/cogs/admin/moderation_invites.py +++ b/src/zorak/cogs/admin/moderation_invites.py @@ -6,6 +6,7 @@ import discord from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings class ModerationInvites(commands.Cog): @@ -23,6 +24,7 @@ async def on_message(self, message): """ txt = message.content current_channel = message.channel + settings = GuildSettings(self.bot.settings.server, message.guild) def is_invite(arg_message): """ @@ -84,14 +86,14 @@ def check_for_admin_override(arg_message): if not message.content.startswith('z.invite '): return False - return any(role.id in self.bot.settings.admin.values() for role in message.author.roles) + return any(role.id in settings.admin_roles.values() for role in message.author.roles) if is_invite(txt): if isinstance(message.channel, discord.DMChannel): return if not check_for_admin_override(txt): - logs_channel = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + logs_channel = await self.bot.fetch_channel(settings.mod_log) await logs_channel.send(embed=log_message(message)) await message.delete() await current_channel.send(embed=embed_warning(message)) From f575b62b519f26ad764e788924423e49aa957443 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:17:54 +0200 Subject: [PATCH 12/38] Added server settings to make this a multi-guild thing --- src/zorak/cogs/admin/verification_on_join.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/zorak/cogs/admin/verification_on_join.py b/src/zorak/cogs/admin/verification_on_join.py index 0a465c7a..1fc3ec1c 100644 --- a/src/zorak/cogs/admin/verification_on_join.py +++ b/src/zorak/cogs/admin/verification_on_join.py @@ -5,6 +5,7 @@ import logging import discord from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings logger = logging.getLogger(__name__) @@ -33,7 +34,9 @@ async def kick_if_not_verified(self, member, time_to_kick, logging_channel): @commands.Cog.listener() async def on_member_join(self, member: discord.Member): guild = member.guild - logs_channel = await self.bot.fetch_channel(self.bot.settings.verification["verification_channel"]) + settings = GuildSettings(self.bot.settings.server, guild) + + logs_channel = await self.bot.fetch_channel(settings.verification_log) await self.log_unverified_join(member, logs_channel) await self.send_welcome_message(guild, member) From 7504e18819d1c62a6b24fda40e2b5e081da087b4 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:15:12 +0200 Subject: [PATCH 13/38] Added settings to verification, however only for the button message so far. 3 todo items here before golive --- .../cogs/admin/verification_on_verified.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/zorak/cogs/admin/verification_on_verified.py b/src/zorak/cogs/admin/verification_on_verified.py index c87bb3be..c88b5eb1 100644 --- a/src/zorak/cogs/admin/verification_on_verified.py +++ b/src/zorak/cogs/admin/verification_on_verified.py @@ -10,6 +10,8 @@ import discord from discord.ext import commands from time import sleep +from zorak.utilities.cog_helpers.guild_settings import GuildSettings + logger = logging.getLogger(__name__) @@ -19,8 +21,9 @@ class VerificationSelector(discord.ui.Select): This is the dropdown selection menu that the user interacts with. """ - def __init__(self, discord_bot, selector_data): + def __init__(self, discord_bot, selector_data, settings): self.bot = discord_bot + self.settings = settings self.name = selector_data["name"] self.single_choice = selector_data["single_choice"] self.description = selector_data["description"] @@ -33,7 +36,7 @@ def __init__(self, discord_bot, selector_data): super().__init__(placeholder=selector_data["description"], options=options) - async def send_wrong_button_message(self, guild, member): + async def send_wrong_button_message(self, member): try: await member.send( f""" @@ -43,7 +46,7 @@ async def send_wrong_button_message(self, guild, member): ** _Make sure you press the "Verify me!" button to verify yourself._ ** Please join the server again and try again. - {self.bot.settings.info['invite']} + {self.settings.info['invite']} """ ) except discord.errors.Forbidden as catch_dat_forbidden: @@ -98,12 +101,12 @@ class SelectView(discord.ui.View): under it. We also define our button timeout here. Consider this the entrypoint for all the other classes defined above. """ - def __init__(self, bot, verification_data, *, timeout=180): + def __init__(self, bot, verification_data, settings, *, timeout=180): super().__init__(timeout=timeout) selectors = verification_data["selectors"] shuffle(selectors) for menu in selectors: - self.add_item(VerificationSelector(bot, selectors[menu])) + self.add_item(VerificationSelector(bot, selectors[menu], settings)) class Verification(commands.Cog): @@ -121,14 +124,15 @@ def __init__(self, bot): @commands.slash_command(description="Verification!") async def verify(self, ctx): """The slash command that initiates the fancy menus.""" - if hasattr(self.bot.settings, "verification_options"): - if "selectors" in self.bot.settings.verification_options: + settings = GuildSettings(self.bot.settings.server, ctx.guild) + if hasattr(self.bot.settings, "verification_options"): # TODO: THIS IS FROM THE OLD SETTINGS + if "selectors" in self.bot.settings.verification_options: # TODO: THIS IS FROM THE OLD SETTINGS if "✅" not in [role.name for role in ctx.author.roles]: await ctx.respond( "# ~ Verification ~ \n" "_Before you can join the server, we need to make sure you are not a robot._\n" "_Please answer the following question._" - , view=SelectView(self.bot, self.bot.settings.verification_options) + , view=SelectView(self.bot, self.bot.settings.verification_options, settings) # TODO: THIS IS FROM THE OLD SETTINGS , ephemeral=True ) else: From be0916e54c046b60b044a154630f92af492e3f81 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:15:25 +0200 Subject: [PATCH 14/38] Added settings to points cog --- src/zorak/cogs/utility/points.py | 34 +++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/zorak/cogs/utility/points.py b/src/zorak/cogs/utility/points.py index 7c705f13..8fa20044 100644 --- a/src/zorak/cogs/utility/points.py +++ b/src/zorak/cogs/utility/points.py @@ -6,6 +6,7 @@ import discord from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_leaderboard @@ -19,6 +20,7 @@ def __init__(self, bot): raise Exception("Database client not found.") self.bot = bot + @commands.Cog.listener() async def on_member_join(self, member: discord.Member): # pylint: disable=E1101 """When a member joins, add them to the DB.""" @@ -40,8 +42,9 @@ async def on_message(self, message: discord.Message): @commands.Cog.listener() async def on_message_delete(self, message: discord.Message): """When a member deletes a message, remove a point.""" + settings = GuildSettings(self.bot.settings.server, message.guild) message_value = len(message.content.split(" ")) - mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + mod_log = await self.bot.fetch_channel(settings.mod_log) await mod_log.send(f"{message_value} Point/s removed from {message.author} for deleting a message.") self.bot.db_client.remove_points_from_user(message.author.id, abs(message_value)) # @@ -64,9 +67,10 @@ async def add_all_members_to_db(self, ctx): @commands.has_any_role("Admin", "Sudo", "Staff", "Project Manager") async def add_points_to_user(self, ctx, mention, points): """Add points to a user.""" + settings = GuildSettings(self.bot.settings.server, ctx.guild) user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.add_points_to_user(user.id, int(points)) - mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + mod_log = await self.bot.fetch_channel(settings.mod_log) await mod_log.send(f"{points} point{('s', '')[abs(int(points)) == 1]} added to {mention} by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(int(points)) == 1]} added to {mention}.") @@ -74,8 +78,9 @@ async def add_points_to_user(self, ctx, mention, points): @commands.has_any_role("Admin", "Sudo", "Staff", "Project Manager") async def add_points_to_all_users(self, ctx, points): """Add points to all users.""" + settings = GuildSettings(self.bot.settings.server, ctx.guild) self.bot.db_client.add_points_to_all_users(int(points)) - mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + mod_log = await self.bot.fetch_channel(settings.mod_log) await mod_log.send(f"{points} point{('s', '')[abs(int(points)) == 1]} added to all users by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(int(points)) == 1]} added to all users.") @@ -85,9 +90,10 @@ async def remove_points_from_user(self, ctx, mention, points): """Remove points from a user.""" mention = str(mention) points = int(points) + settings = GuildSettings(self.bot.settings.server, ctx.guild) user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.remove_points_from_user(user.id, points) - mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + mod_log = await self.bot.fetch_channel(settings.mod_log) await mod_log.send(f"{points} point{('s', '')[abs(points) == 1]} removed from {mention} by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(points) == 1]} removed from {mention}.") @@ -96,8 +102,9 @@ async def remove_points_from_user(self, ctx, mention, points): async def remove_points_from_all_users(self, ctx, points): """Remove points from all users.""" points = int(points) + settings = GuildSettings(self.bot.settings.server, ctx.guild) self.bot.db_client.remove_points_from_all_users(points) - mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + mod_log = await self.bot.fetch_channel(settings.mod_log) await mod_log.send(f"{points} point{('s', '')[abs(points) == 1]} removed from all users by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(points) == 1]} removed from all users.") @@ -106,9 +113,10 @@ async def remove_points_from_all_users(self, ctx, points): async def reset_points_for_user(self, ctx, mention): """Reset points for a user.""" mention = str(mention) + settings = GuildSettings(self.bot.settings.server, ctx.guild) user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.set_user_points(user.id, 0) - mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + mod_log = await self.bot.fetch_channel(settings.mod_log) await mod_log.send(f"Points reset for {mention} by {ctx.author}.") await ctx.respond(f"Points reset for {mention}.") @@ -116,8 +124,9 @@ async def reset_points_for_user(self, ctx, mention): @commands.has_any_role("Admin", "Sudo", "Staff", "Project Manager") async def reset_points_for_all_users(self, ctx): """Reset points for all users.""" + settings = GuildSettings(self.bot.settings.server, ctx.guild) self.bot.db_client.set_all_user_points(0) - mod_log = await self.bot.fetch_channel(self.bot.settings.logging["mod_log"]) + mod_log = await self.bot.fetch_channel(settings.mod_log) await mod_log.send(f"Points reset for all users by {ctx.author}.") await ctx.respond("Points reset for all users.") @@ -132,18 +141,19 @@ async def get_points_for_user(self, ctx, mention): @commands.slash_command() async def leaderboard(self, ctx): """Get your points.""" + settings = GuildSettings(self.bot.settings.server, ctx.guild) def is_staff(member_obj): """ Tells us if the 'member_obj' has an admin role. """ # TODO: .admin_roles no longer exists, find a workaround here. - for role in self.bot.settings.admin: - if self.bot.settings.admin[role] in [y.id for y in member_obj.roles]: + for role in settings.admin_roles: + if settings.admin_roles[role] in [y.id for y in member_obj.roles]: return True return False top10_no_staff = [] points = self.bot.db_client.get_top_10() - guild = self.bot.get_guild(self.bot.settings.info['id']) + guild = self.bot.get_guild(settings.info['id']) for iteration, person in enumerate(points): if len(top10_no_staff) < 10: # should only allow 10 people into the list @@ -153,8 +163,8 @@ def is_staff(member_obj): else: return - embed = embed_leaderboard(top10_no_staff, self.bot.settings.info['name'], - self.bot.settings.info['logo']) + embed = embed_leaderboard(top10_no_staff, settings.info['name'], + settings.info['logo']) await ctx.respond(embed=embed) From aa29be976d03f4af63ce6d58ae7838f8c982e141 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:16:09 +0200 Subject: [PATCH 15/38] fix small bug in moderation_invites.py with the message types being passed into Guild Settings --- src/zorak/cogs/admin/moderation_invites.py | 140 +++++++++++---------- 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/src/zorak/cogs/admin/moderation_invites.py b/src/zorak/cogs/admin/moderation_invites.py index bc8d45a1..31837edf 100644 --- a/src/zorak/cogs/admin/moderation_invites.py +++ b/src/zorak/cogs/admin/moderation_invites.py @@ -22,81 +22,85 @@ async def on_message(self, message): """ Scans every message with the regex below. """ - txt = message.content - current_channel = message.channel - settings = GuildSettings(self.bot.settings.server, message.guild) + if str(message.type) == "MessageType.application_command": + return + else: + txt = message.content + current_channel = message.channel + author = message.author + settings = GuildSettings(self.bot.settings.server, message.guild) - def is_invite(arg_message): - """ - - invitation types - -> Official covers official invites "discord.gg/s7s8df9a" - -> unofficial urls that start with d and end with letter numbers "dxxxx.gg/23bn2u2" - """ - official = re.search( - "(?:https?://)?(?:www\.|ptb\.|canary\.)?(?:discord(?:app)?\.(?:(?:com|gg)" # pylint: disable=W1401 - "/invite/[a-z0-9-_]+)|discord\.gg/[a-z0-9-_]+)", # pylint: disable=W1401 - arg_message, - ) - unofficial = re.search( - "(?:https?://)?(?:www\.)?(?:dsc\.gg|invite\.gg+|discord\.link)" # pylint: disable=W1401 - "/[a-z0-9-_]+", # pylint: disable=W1401 - arg_message, - ) - if official is not None or unofficial is not None: - return True - return False + def is_invite(arg_message): + """ + - invitation types + -> Official covers official invites "discord.gg/s7s8df9a" + -> unofficial urls that start with d and end with letter numbers "dxxxx.gg/23bn2u2" + """ + official = re.search( + "(?:https?://)?(?:www\.|ptb\.|canary\.)?(?:discord(?:app)?\.(?:(?:com|gg)" # pylint: disable=W1401 + "/invite/[a-z0-9-_]+)|discord\.gg/[a-z0-9-_]+)", # pylint: disable=W1401 + arg_message, + ) + unofficial = re.search( + "(?:https?://)?(?:www\.)?(?:dsc\.gg|invite\.gg+|discord\.link)" # pylint: disable=W1401 + "/[a-z0-9-_]+", # pylint: disable=W1401 + arg_message, + ) + if official is not None or unofficial is not None: + return True + return False - def log_message(arg_message): - """ - If it finds something, it logs the message - """ - author = arg_message.author - embed = discord.Embed( - title="<:red_circle:1043616578744357085> Invite removed", - description=f"Posted by {arg_message.author}\nIn {'a DM.' if isinstance(arg_message.channel, discord.DMChannel) else arg_message.channel.mention}", - color=discord.Color.dark_red(), - timestamp=datetime.utcnow(), - ) - embed.set_thumbnail(url=author.avatar) - embed.add_field( - name="Message: ", - value=message.content, # ToDo: This throws an error when deleting an embed. - inline=True, - ) - return embed + def log_message(arg_message): + """ + If it finds something, it logs the message + """ + author = arg_message.author + embed = discord.Embed( + title="<:red_circle:1043616578744357085> Invite removed", + description=f"Posted by {arg_message.author}\nIn {'a DM.' if isinstance(arg_message.channel, discord.DMChannel) else arg_message.channel.mention}", + color=discord.Color.dark_red(), + timestamp=datetime.utcnow(), + ) + embed.set_thumbnail(url=author.avatar) + embed.add_field( + name="Message: ", + value=message.content, # ToDo: This throws an error when deleting an embed. + inline=True, + ) + return embed - def embed_warning(arg_message): - """ - If it finds something, it sends a warning that the user should quit that shit. - """ - embed = discord.Embed( - title="<:x:1055080113336762408> External Invites are not allowed here!", - description=f"{arg_message.author}, your message was removed " - f"because it contained an external invite.\nIf this " - f"was a mistake, contact the @staff", - color=discord.Color.dark_red(), - timestamp=datetime.utcnow(), - ) - return embed + def embed_warning(arg_message): + """ + If it finds something, it sends a warning that the user should quit that shit. + """ + embed = discord.Embed( + title="<:x:1055080113336762408> External Invites are not allowed here!", + description=f"{arg_message.author}, your message was removed " + f"because it contained an external invite.\nIf this " + f"was a mistake, contact the @staff", + color=discord.Color.dark_red(), + timestamp=datetime.utcnow(), + ) + return embed - def check_for_admin_override(arg_message): - """ - Handling for when a MOD user needs to post an invitation - """ - if not message.content.startswith('z.invite '): - return False + def check_for_admin_override(arg_message): + """ + Handling for when a MOD user needs to post an invitation + """ + if not message.content.startswith('z.invite '): + return False - return any(role.id in settings.admin_roles.values() for role in message.author.roles) + return any(role.id in settings.admin_roles.values() for role in message.author.roles) - if is_invite(txt): - if isinstance(message.channel, discord.DMChannel): - return + if is_invite(txt): + if isinstance(message.channel, discord.DMChannel): + return - if not check_for_admin_override(txt): - logs_channel = await self.bot.fetch_channel(settings.mod_log) - await logs_channel.send(embed=log_message(message)) - await message.delete() - await current_channel.send(embed=embed_warning(message)) + if not check_for_admin_override(txt): + logs_channel = await self.bot.fetch_channel(settings.mod_log) + await logs_channel.send(embed=log_message(message)) + await message.delete() + await current_channel.send(embed=embed_warning(message)) def setup(bot): From b0ceb349f10ff008c439cfef2d5607f51bfadc17 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:09:51 +0200 Subject: [PATCH 16/38] Added guild settings to tickets --- src/zorak/cogs/general/general_tickets.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/zorak/cogs/general/general_tickets.py b/src/zorak/cogs/general/general_tickets.py index c54328d8..13af9708 100644 --- a/src/zorak/cogs/general/general_tickets.py +++ b/src/zorak/cogs/general/general_tickets.py @@ -6,6 +6,9 @@ import discord from discord.ext import commands +from zorak.utilities.cog_helpers.guild_settings import GuildSettings + + logger = logging.getLogger(__name__) @@ -22,10 +25,11 @@ async def ticket(self, ctx): """ A simple command with a view. """ + settings = GuildSettings(self.bot.settings.server, ctx.guild) logger.info("%s used the %s command.", ctx.author.name, ctx.command) await ctx.respond( "Do you need help, or do you have a question for the Staff?", - view=MakeATicket(self.bot.settings), + view=MakeATicket(settings), ephemeral=True, ) @@ -35,9 +39,9 @@ class MakeATicket(discord.ui.View): A UI component that sends a button, which does other things. """ - def __init__(self, server_settings, *, timeout=None): + def __init__(self, settings, *, timeout=None): super().__init__(timeout=timeout) - self.server_settings = server_settings + self.settings = settings @discord.ui.button(label="Open a support Ticket", style=discord.ButtonStyle.primary) async def button_callback(self, button, interaction): @@ -49,8 +53,8 @@ async def button_callback(self, button, interaction): button.disabled = True await interaction.edit_original_response(view=self) - support = await interaction.guild.fetch_channel(self.server_settings.support["server_support"]) - staff = interaction.guild.get_role(self.server_settings.admin["staff"]) + support = await interaction.guild.fetch_channel(self.settings.support_channel) + staff = interaction.guild.get_role(self.settings.admin_roles["staff"]) ticket = await support.create_thread( name=f"[Ticket] - {interaction.user}", @@ -60,6 +64,7 @@ async def button_callback(self, button, interaction): reason=None, ) + # TODO: Can just mention the staff role here instead of a for loop for person in interaction.guild.members: if staff in person.roles: await ticket.add_user(person) From 0ea3067598ca606f84b8aacde798d6e282082cb1 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:10:27 +0200 Subject: [PATCH 17/38] Little oopsie passing the guild ID --- src/zorak/cogs/logging/logging_member_ban.py | 2 +- src/zorak/cogs/logging/logging_member_kick.py | 2 +- src/zorak/cogs/logging/logging_member_leaving.py | 2 +- src/zorak/cogs/logging/logging_member_roles.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/zorak/cogs/logging/logging_member_ban.py b/src/zorak/cogs/logging/logging_member_ban.py index 4e109027..f09f3136 100644 --- a/src/zorak/cogs/logging/logging_member_ban.py +++ b/src/zorak/cogs/logging/logging_member_ban.py @@ -26,7 +26,7 @@ async def on_member_remove(self, member): return settings = GuildSettings(self.bot.settings.server, member.guild) - current_guild = self.bot.get_guild(member.guild) + current_guild = self.bot.get_guild(member.guild.id) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] diff --git a/src/zorak/cogs/logging/logging_member_kick.py b/src/zorak/cogs/logging/logging_member_kick.py index 1d3974ac..7888c973 100644 --- a/src/zorak/cogs/logging/logging_member_kick.py +++ b/src/zorak/cogs/logging/logging_member_kick.py @@ -26,7 +26,7 @@ async def on_member_remove(self, member): return settings = GuildSettings(self.bot.settings.server, member.guild) - current_guild = self.bot.get_guild(member.guild) + current_guild = self.bot.get_guild(member.guild.id) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.kick": diff --git a/src/zorak/cogs/logging/logging_member_leaving.py b/src/zorak/cogs/logging/logging_member_leaving.py index 9fafe34a..0fb3b09c 100644 --- a/src/zorak/cogs/logging/logging_member_leaving.py +++ b/src/zorak/cogs/logging/logging_member_leaving.py @@ -26,7 +26,7 @@ async def on_member_remove(self, member): return settings = GuildSettings(self.bot.settings.server, member.guild) - current_guild = self.bot.get_guild(member.guild) + current_guild = self.bot.get_guild(member.guild.id) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) != "AuditLogAction.ban" and str(audit_log.action) != "AuditLogAction.kick": diff --git a/src/zorak/cogs/logging/logging_member_roles.py b/src/zorak/cogs/logging/logging_member_roles.py index 4b063b67..9b617f09 100644 --- a/src/zorak/cogs/logging/logging_member_roles.py +++ b/src/zorak/cogs/logging/logging_member_roles.py @@ -25,7 +25,7 @@ async def on_member_update(self, before, after): Can be quite spammy. """ settings = GuildSettings(self.bot.settings.server, before.guild) - current_guild = self.bot.get_guild(before.guild) + current_guild = self.bot.get_guild(before.guild.id) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.member_role_update": From a3f981d3944b41f45234a0322239bb95f4328ab0 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:10:43 +0200 Subject: [PATCH 18/38] Bug with bot messages being passed --- src/zorak/cogs/logging/logging_message_edit.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/zorak/cogs/logging/logging_message_edit.py b/src/zorak/cogs/logging/logging_message_edit.py index 256bc5cf..8d1991c6 100644 --- a/src/zorak/cogs/logging/logging_message_edit.py +++ b/src/zorak/cogs/logging/logging_message_edit.py @@ -21,8 +21,11 @@ def __init__(self, bot): @commands.Cog.listener() async def on_message_edit(self, message_before, message_after): - settings = GuildSettings(self.bot.settings.server, message_before.guild) + # Ignore any bot messages + if message_before.author.bot or message_after.author.bot: + return + settings = GuildSettings(self.bot.settings.server, message_after.guild) # IGNORE /run, since we will set up an on_message_edit handler there with opposite logic if message_before.content.startswith('/run') or message_after.content.startswith('/run'): return From 07639187761c79551c3da5c243b6bf7470994f2b Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:11:07 +0200 Subject: [PATCH 19/38] Name change logging fix --- src/zorak/cogs/logging/logging_name_changes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zorak/cogs/logging/logging_name_changes.py b/src/zorak/cogs/logging/logging_name_changes.py index 5894659b..c4aa0efb 100644 --- a/src/zorak/cogs/logging/logging_name_changes.py +++ b/src/zorak/cogs/logging/logging_name_changes.py @@ -39,7 +39,7 @@ async def on_member_update(self, before, after): embed = embed_name_change(before, after, username_before, username_after) logs_channel = await self.bot.fetch_channel(settings.mod_log) - await logs_channel.send(f"{username_after.mention}", embed=embed) + await logs_channel.send(f"{after.mention}", embed=embed) def setup(bot): From c2dd4392bb97f23f15b9f55e46ff31a0e68e39d7 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:11:30 +0200 Subject: [PATCH 20/38] Issue with bot user triggering invite spam --- src/zorak/cogs/admin/moderation_invites.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/zorak/cogs/admin/moderation_invites.py b/src/zorak/cogs/admin/moderation_invites.py index 31837edf..f6ddbc75 100644 --- a/src/zorak/cogs/admin/moderation_invites.py +++ b/src/zorak/cogs/admin/moderation_invites.py @@ -22,13 +22,11 @@ async def on_message(self, message): """ Scans every message with the regex below. """ - if str(message.type) == "MessageType.application_command": - return - else: + if not message.author.bot: txt = message.content current_channel = message.channel author = message.author - settings = GuildSettings(self.bot.settings.server, message.guild) + settings = GuildSettings(self.bot.settings.server, author.guild) def is_invite(arg_message): """ From a6b40bb32317db81175923320755436bdfaf1f4a Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:11:40 +0200 Subject: [PATCH 21/38] Forgot the welcome message. --- src/zorak/cogs/admin/verification_on_join.py | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/zorak/cogs/admin/verification_on_join.py b/src/zorak/cogs/admin/verification_on_join.py index 1fc3ec1c..2d04a3f7 100644 --- a/src/zorak/cogs/admin/verification_on_join.py +++ b/src/zorak/cogs/admin/verification_on_join.py @@ -31,6 +31,25 @@ async def kick_if_not_verified(self, member, time_to_kick, logging_channel): f"{member.mention} did not verify after {int((time_to_kick / 3600))} hour/s, auto-removed.") await member.kick(reason="Did not verify.") + async def send_welcome_message(self, guild, member, settings): + welcome_message = f""" + Hi there, {member.mention} + I'm Zorak, the moderator of {guild.name}. + + We are very happy that you have decided to join us. + Before you are allowed to chat, you need to verify that you aren't a bot. + Dont worry, it's easy. Just go to + {self.bot.get_channel(settings.verification_channel).mention} + and click the green button. + + After you do, all of {guild.name} is available to you. Have a great time :-) + """ + # Send Welcome Message + try: + await member.send(welcome_message) + except discord.errors.Forbidden as catch_dat_forbidden: + logger.debug(f'{member.name} cannot be sent a DM.') + @commands.Cog.listener() async def on_member_join(self, member: discord.Member): guild = member.guild @@ -39,7 +58,7 @@ async def on_member_join(self, member: discord.Member): logs_channel = await self.bot.fetch_channel(settings.verification_log) await self.log_unverified_join(member, logs_channel) - await self.send_welcome_message(guild, member) + await self.send_welcome_message(guild, member, settings) await self.kick_if_not_verified(member, 3600, logs_channel) From b64fcb5027aaede481e50a3602d5f218f5b80e2b Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:11:48 +0200 Subject: [PATCH 22/38] Turn DB back on --- src/zorak/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zorak/__main__.py b/src/zorak/__main__.py index 6ed80133..9ed978f0 100644 --- a/src/zorak/__main__.py +++ b/src/zorak/__main__.py @@ -81,7 +81,7 @@ def main(): ) if not args.drop_db: logger.info("Initialising Database...") - #initialise_bot_db(bot) + initialise_bot_db(bot) settings_path = args.server_settings_path if args.server_settings_path else os.environ.get( "SERVER_SETTINGS") From 3dbc6adbf1c13e6615c8ca1fbd63298c20f79d2b Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Fri, 5 Apr 2024 12:14:01 +0200 Subject: [PATCH 23/38] Start working in mongo.py --- Resources/ServerConfig/dev/testing.py | 19 ------ src/zorak/utilities/core/mongo.py | 84 +++++++++++++++------------ 2 files changed, 46 insertions(+), 57 deletions(-) delete mode 100644 Resources/ServerConfig/dev/testing.py diff --git a/Resources/ServerConfig/dev/testing.py b/Resources/ServerConfig/dev/testing.py deleted file mode 100644 index 9c674a2c..00000000 --- a/Resources/ServerConfig/dev/testing.py +++ /dev/null @@ -1,19 +0,0 @@ -import json - -# Function to read data from JSON file -def read_json(file_path, category=None): - with open(file_path, 'r') as f: - if category: - data = json.load(f)["server"][category] - else: - data = json.load(f)["server"] - return data - -# Function to write data to JSON file -def write_json(data, file_path): - with open(file_path, 'w') as json_file: - json.dump(data, json_file, indent=4) - - -x = read_json('FAKE_DB_settings.json', 'info') -print(x) diff --git a/src/zorak/utilities/core/mongo.py b/src/zorak/utilities/core/mongo.py index 27fa3869..19ecbece 100644 --- a/src/zorak/utilities/core/mongo.py +++ b/src/zorak/utilities/core/mongo.py @@ -193,6 +193,8 @@ class CustomMongoDBClient(MongoDBClient): guild, but could be extended to handle multiple guilds by adding a guild_id field to the user table, or adding a new table for each guild.""" + + def initialise_user_table(self): """Initialise the user table. Ensures that the UserID field is unique.""" validator = { @@ -214,43 +216,6 @@ def initialise_user_table(self): self.create_collection("UserPoints", validator_schema=validator) logger.info("User table initialised.") - def initialise_dev_times_table(self): - """Initialise the devtimes table. """ - validator = { - "bsonType": "object", - "title": "Dev Times Collection Validation", - "required": ["Username", "Country", "Timezone"], - "properties": { - "Username": { - "bsonType": "string", - "description": "The Username (Display name not UID) of the user to be displayed.", - }, - "Country": { - "bsonType": "string", - "description": "The country of the user.", - }, - "Timezone": { - "bsonType": "string", - "description": " The time according to pytz.timezone, example: Asia/Kolkata.", - }, - }, - } - self.create_collection("DevTimes", validator_schema=validator) - logger.info("Dev Times table initialised.") - - def add_dev_time_to_table(self, username: str, country: str, timezone: str): - """Add a user to the user table if they are not already in it.""" - if not self.find_one("DevTimes", {"Username": username}): - self.insert_one("DevTimes", {"Username": username, "Country": country, "Timezone": timezone}) - - def remove_dev_time_from_table(self, username: str): - """Remove a user from the user table.""" - self.delete_one("DevTimes", {"Username": username}) - - def get_all_dev_times(self): - """Get all dev times from the table.""" - return self.find("DevTimes", {}) - def add_user_to_table(self, member): """Add a user to the user table if they are not already in it.""" if not self.find_one("UserPoints", {"UserID": member.id}): @@ -309,7 +274,9 @@ def get_top_10(self): top10.append(x) return top10 - # Used for the RSS_feeds cog + ############### + # RSS + ############### def initialise_news_table(self): """Initialise the news table.""" @@ -336,6 +303,47 @@ def get_all_stories(self): """Get all stories from the news table.""" return self.find("News", {}) + ############### + # DevTimes + ############### + def initialise_dev_times_table(self): + """Initialise the devtimes table. """ + validator = { + "bsonType": "object", + "title": "Dev Times Collection Validation", + "required": ["Username", "Country", "Timezone"], + "properties": { + "Username": { + "bsonType": "string", + "description": "The Username (Display name not UID) of the user to be displayed.", + }, + "Country": { + "bsonType": "string", + "description": "The country of the user.", + }, + "Timezone": { + "bsonType": "string", + "description": " The time according to pytz.timezone, example: Asia/Kolkata.", + }, + }, + } + self.create_collection("DevTimes", validator_schema=validator) + logger.info("Dev Times table initialised.") + + def add_dev_time_to_table(self, username: str, country: str, timezone: str): + """Add a user to the user table if they are not already in it.""" + if not self.find_one("DevTimes", {"Username": username}): + self.insert_one("DevTimes", {"Username": username, "Country": country, "Timezone": timezone}) + + def remove_dev_time_from_table(self, username: str): + """Remove a user from the user table.""" + self.delete_one("DevTimes", {"Username": username}) + + def get_all_dev_times(self): + """Get all dev times from the table.""" + return self.find("DevTimes", {}) + + def initialise_bot_db( bot: Bot, From aca5c4bd21e86432824a7ade0f240cdbb458baee Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Sat, 6 Apr 2024 14:19:42 +0200 Subject: [PATCH 24/38] [MAJOR] - Update to mongo.py, added GuildSettings collection --- src/zorak/utilities/core/mongo.py | 307 ++++++++++++++++++++++++++---- 1 file changed, 274 insertions(+), 33 deletions(-) diff --git a/src/zorak/utilities/core/mongo.py b/src/zorak/utilities/core/mongo.py index 19ecbece..43a8a196 100644 --- a/src/zorak/utilities/core/mongo.py +++ b/src/zorak/utilities/core/mongo.py @@ -193,8 +193,249 @@ class CustomMongoDBClient(MongoDBClient): guild, but could be extended to handle multiple guilds by adding a guild_id field to the user table, or adding a new table for each guild.""" + ############### + # Settings + ############### + def initialise_settings_table(self): + """ Initializes a GuildSettings Table """ + validator = { + "validator": { + "$jsonSchema": { + "bsonType": "object", + "title": "GuildSettings Validation", + "required": ["id", "name"], + "properties": { + "id": { + "bsonType": "int", + "description": "'id' must be an int and is required" + }, + "name": { + "bsonType": "string", + "description": "'name' must be a string and is required" + }, + "website": { + "bsonType": "string", + "description": "'website' must be a string and is required" + }, + "email": { + "bsonType": "string", + "description": "'email' must be a string and is required" + }, + "logo": { + "bsonType": "string", + "description": "'logo' must be a string if the field exists" + }, + "verification_channel": { + "bsonType": "int", + "description": "'verification_channel' must be an integer" + }, + "quarantine_channel": { + "bsonType": "int", + "description": "'quarantine_channel' must be an integer if the field exists" + }, + "support_channel": { + "bsonType": "int", + "description": "'support_channel' must be an integer if the field exists" + }, + "role_channel": { + "bsonType": "int", + "description": "'role_channel' must be an integer if the field exists" + }, + "rules_channel": { + "bsonType": "int", + "description": "'rules_channel' must be an integer if the field exists" + }, + "general_channel": { + "bsonType": "int", + "description": "'general_channel' must be an integer if the field exists" + }, + "resources_channel": { + "bsonType": "int", + "description": "'resources_channel' must be an integer if the field exists" + }, + "challenges_channel": { + "bsonType": "int", + "description": "'challenges_channel' must be an integer if the field exists" + }, + "chat_log": { + "bsonType": "int", + "description": "'chat_log' must be an integer if the field exists" + }, + "join_log": { + "bsonType": "int", + "description": "'join_log' must be an integer if the field exists" + }, + "mod_log": { + "bsonType": "int", + "description": "'mod_log' must be an integer if the field exists" + }, + "server_change_log": { + "bsonType": "int", + "description": "'server_change_log' must be an integer if the field exists" + }, + "user_log": { + "bsonType": "int", + "description": "'user_log' must be an integer if the field exists" + }, + "verification_log": { + "bsonType": "int", + "description": "'verification_log' must be an integer if the field exists" + }, + "zorak_log": { + "bsonType": "int", + "description": "'zorak_log' must be an integer if the field exists" + }, + "owner_role": { + "bsonType": "int", + "description": "'owner_role' must be an integer if the field exists" + }, + "admin_role": { + "bsonType": "int", + "description": "'admin_role' must be an integer if the field exists" + }, + "staff_role": { + "bsonType": "int", + "description": "'staff_role' must be an integer if the field exists" + }, + "networking_role": { + "bsonType": "int", + "description": "'networking_role' must be an integer if the field exists" + }, + "bot_role": { + "bsonType": "int", + "description": "'bot_role' must be an integer if the field exists" + }, + "beginner_role": { + "bsonType": "int", + "description": "'beginner_role' must be an integer if the field exists" + }, + "intermediate_role": { + "bsonType": "int", + "description": "'intermediate_role' must be an integer if the field exists" + }, + "professional_role": { + "bsonType": "int", + "description": "'professional_role' must be an integer if the field exists" + }, + "north_america_role": { + "bsonType": "int", + "description": "'north_america_role' must be an integer if the field exists" + }, + "europe_role": { + "bsonType": "int", + "description": "'europe_role' must be an integer if the field exists" + }, + "asia_role": { + "bsonType": "int", + "description": "'asia_role' must be an integer if the field exists" + }, + "africa_role": { + "bsonType": "int", + "description": "'africa_role' must be an integer if the field exists" + }, + "south_america_role": { + "bsonType": "int", + "description": "'south_america_role' must be an integer if the field exists" + }, + "oceana_role": { + "bsonType": "int", + "description": "'oceana_role' must be an integer if the field exists" + }, + "naughty_role": { + "bsonType": "int", + "description": "'naughty_role' must be an integer if the field exists" + }, + "verified_role": { + "bsonType": "int", + "description": "'verified_role' must be an integer if the field exists" + } + } + } + } + } + + self.create_collection("GuildSettings", validator_schema=validator) + logger.info("GuildSettings initialised.") + + def add_guild_to_table(self, guild): + if not self.find_one("GuildSettings", {"id": guild.id}): + logger.info(f" ---- Adding {guild.name} to DB") + self.insert_one("GuildSettings", { + # Guild Info + "id": guild.id + , "name": guild.name + , "logo": guild.icon.url + , "website": None + , "email": None + , "review": None + , "invite": None + , "member_count": guild.member_count + , "premium_guild": False + , "FeatureFlag1": False + , "FeatureFlag2": False + , "FeatureFlag3": False + + # Channel Info + , "verification_channel": None + , "quarantine_channel": None + , "support_channel": None + , "role_channel": None + , "rules_channel": guild.rules_channel # Default: None + , "general_channel": None + , "resources_channel": None + , "challenges_channel": None + + # Logging Channels + , "chat_log": None + , "join_log": None + , "mod_log": None + , "server_change_log": None + , "user_log": None + , "verification_log": None + , "zorak_log": None + + # Roles + , "owner_role": None + , "admin_role": None + , "staff_role": None + , "networking_role": None + , "bot_role": guild.self_role.id # Default: None + , "beginner_role": None + , "intermediate_role": None + , "professional_role": None + , "north_america_role": None + , "europe_role": None + , "asia_role": None + , "africa_role": None + , "south_america_role": None + , "oceana_role": None + , "naughty_role": None + , "verified_role": None + }) + + def get_guild_settings(self, guild): + settings = self.find_one("GuildSettings", {"id": guild.id}) + if settings: + return settings + return None + def update_guild_settings(self, guild, item, value): + """Update the settings of a guild.""" + try: + self.update_one( + "GuildSettings", {"id": guild.id}, {"$set": {item: value}} + ) # The $set operator replaces the value of a field with the specified value. + + except Exception as ohfuck: + logger.critical(f"There was an issue updating {item} with {value}. Error: {ohfuck}") + def remove_guild_from_table(self, guild): + """Remove a guild from the GuildSettings table.""" + self.delete_one("GuildSettings", {"id": guild.id}) + + ############### + # Users + ############### def initialise_user_table(self): """Initialise the user table. Ensures that the UserID field is unique.""" validator = { @@ -274,34 +515,34 @@ def get_top_10(self): top10.append(x) return top10 - ############### - # RSS - ############### - - def initialise_news_table(self): - """Initialise the news table.""" - validator = { - "bsonType": "object", - "title": "News Collection Validation", - "required": ["entryID"], - "properties": { - "entryID": { - "bsonType": "string", - "description": "The ID of the story.", - } - }, - } - self.create_collection("News", validator_schema=validator) - logger.info("News table initialised.") - - def add_story_to_table(self, entry_id: str): - """Add a story to the news table if they are not already in it.""" - if not self.find_one("News", {"entryID": entry_id}): - self.insert_one("News", {"entryID": entry_id}) - - def get_all_stories(self): - """Get all stories from the news table.""" - return self.find("News", {}) + # ############### + # # RSS + # ############### + # + # def initialise_news_table(self): + # """Initialise the news table.""" + # validator = { + # "bsonType": "object", + # "title": "News Collection Validation", + # "required": ["entryID"], + # "properties": { + # "entryID": { + # "bsonType": "string", + # "description": "The ID of the story.", + # } + # }, + # } + # self.create_collection("News", validator_schema=validator) + # logger.info("News table initialised.") + # + # def add_story_to_table(self, entry_id: str): + # """Add a story to the news table if they are not already in it.""" + # if not self.find_one("News", {"entryID": entry_id}): + # self.insert_one("News", {"entryID": entry_id}) + # + # def get_all_stories(self): + # """Get all stories from the news table.""" + # return self.find("News", {}) ############### # DevTimes @@ -344,7 +585,6 @@ def get_all_dev_times(self): return self.find("DevTimes", {}) - def initialise_bot_db( bot: Bot, ): # This is called in the main bot file and is the bit of code that connects to the database. @@ -353,7 +593,8 @@ def initialise_bot_db( attempts = 0 while connected is False and attempts < 5: logger.info("Connecting to database... Attempt %s of 10", str(attempts + 1)) - db_client = CustomMongoDBClient(host="mongo", port=27017) # It creates a new instance of the CustomMongoDBClient class, + db_client = CustomMongoDBClient(host="mongo", + port=27017) # It creates a new instance of the CustomMongoDBClient class, # which abstracts our database interactions. try: time.sleep(10) @@ -369,10 +610,10 @@ def initialise_bot_db( attempts += 1 if connected: logger.info("Connected to database.") + db_client.initialise_user_table() # type: ignore - # This makes the table if it doesn't exist - # and ensures the validation rules. - db_client.initialise_news_table() # type: ignore + db_client.initialise_settings_table() # type: ignore + bot.db_client = db_client # type: ignore # This adds the db_client to the bot # object so that it can be accessed elsewhere. From 87150a8db3c63ab85cf4dc4099c0f85fd2b178bd Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Sat, 6 Apr 2024 15:42:42 +0200 Subject: [PATCH 25/38] [MAJOR] - Update command to update settings. Doesn't feel like final product material --- src/zorak/cogs/admin/update_settings.py | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/zorak/cogs/admin/update_settings.py diff --git a/src/zorak/cogs/admin/update_settings.py b/src/zorak/cogs/admin/update_settings.py new file mode 100644 index 00000000..329d1dcf --- /dev/null +++ b/src/zorak/cogs/admin/update_settings.py @@ -0,0 +1,37 @@ +""" +A simple hello command. +""" +import logging +from random import shuffle +import discord +from discord.ext import commands +from time import sleep + +logger = logging.getLogger(__name__) + + + +class Settings(commands.Cog): + """ + This is the class that defines the actual slash command. + It uses the view above to execute actual logic. + """ + + def __init__(self, bot): + self.bot = bot # Passed in from main.py + + @commands.slash_command(description="Edit the bot settings for your guild!") + async def update_settings(self, ctx, setting: str, value: int): + """The slash command that initiates the fancy menus.""" + self.bot.db_client.update_guild_settings(ctx.guild, setting, int(value)) + + await ctx.respond(f"Updated {setting} in {ctx.guild.name}. New Value: {value}") + + + + +def setup(bot): + """ + Required. + """ + bot.add_cog(Settings(bot)) From 694923233fec271030bde51e36b2e099ab2939ec Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:09:41 +0200 Subject: [PATCH 26/38] minor fix in update_settings.py --- src/zorak/cogs/admin/update_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zorak/cogs/admin/update_settings.py b/src/zorak/cogs/admin/update_settings.py index 329d1dcf..9ec521cb 100644 --- a/src/zorak/cogs/admin/update_settings.py +++ b/src/zorak/cogs/admin/update_settings.py @@ -21,7 +21,7 @@ def __init__(self, bot): self.bot = bot # Passed in from main.py @commands.slash_command(description="Edit the bot settings for your guild!") - async def update_settings(self, ctx, setting: str, value: int): + async def update_settings(self, ctx, setting: str, value: str): """The slash command that initiates the fancy menus.""" self.bot.db_client.update_guild_settings(ctx.guild, setting, int(value)) From f0aba973991bb4781102ab111a0ef0d04f069322 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:10:04 +0200 Subject: [PATCH 27/38] housecleaning mongo.py --- src/zorak/utilities/core/mongo.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/zorak/utilities/core/mongo.py b/src/zorak/utilities/core/mongo.py index 43a8a196..872b02ec 100644 --- a/src/zorak/utilities/core/mongo.py +++ b/src/zorak/utilities/core/mongo.py @@ -357,6 +357,12 @@ def initialise_settings_table(self): self.create_collection("GuildSettings", validator_schema=validator) logger.info("GuildSettings initialised.") + def get_guild_settings(self, guild): + settings = self.find_one("GuildSettings", {"id": guild.id}) + if settings: + return settings + return None + def add_guild_to_table(self, guild): if not self.find_one("GuildSettings", {"id": guild.id}): logger.info(f" ---- Adding {guild.name} to DB") @@ -413,12 +419,6 @@ def add_guild_to_table(self, guild): , "verified_role": None }) - def get_guild_settings(self, guild): - settings = self.find_one("GuildSettings", {"id": guild.id}) - if settings: - return settings - return None - def update_guild_settings(self, guild, item, value): """Update the settings of a guild.""" try: From 9990efe4898c69c19db005abbffc0e999eeb54eb Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:43:51 +0200 Subject: [PATCH 28/38] Update global usage of Settings Toml to Database --- .../cogs/admin/admin_automod_spam_messages.py | 9 +- src/zorak/cogs/admin/admin_purge.py | 5 +- src/zorak/cogs/admin/error_handler.py | 5 +- src/zorak/cogs/admin/moderation_invites.py | 5 +- src/zorak/cogs/admin/verification_on_join.py | 5 +- .../cogs/admin/verification_on_verified.py | 4 +- src/zorak/cogs/general/general_tickets.py | 8 +- src/zorak/cogs/logging/logging_avatars.py | 5 +- src/zorak/cogs/logging/logging_member_ban.py | 9 +- src/zorak/cogs/logging/logging_member_kick.py | 7 +- .../cogs/logging/logging_member_leaving.py | 7 +- .../cogs/logging/logging_member_roles.py | 8 +- .../cogs/logging/logging_member_unban.py | 5 +- .../cogs/logging/logging_message_delete.py | 10 +-- .../cogs/logging/logging_message_edit.py | 6 +- .../cogs/logging/logging_name_changes.py | 7 +- src/zorak/cogs/logging/logging_tickets.py | 17 ++-- src/zorak/cogs/utility/points.py | 35 ++++---- .../utilities/cog_helpers/guild_settings.py | 83 ------------------- 19 files changed, 72 insertions(+), 168 deletions(-) delete mode 100644 src/zorak/utilities/cog_helpers/guild_settings.py diff --git a/src/zorak/cogs/admin/admin_automod_spam_messages.py b/src/zorak/cogs/admin/admin_automod_spam_messages.py index ce7c1457..3d30fd77 100644 --- a/src/zorak/cogs/admin/admin_automod_spam_messages.py +++ b/src/zorak/cogs/admin/admin_automod_spam_messages.py @@ -7,7 +7,6 @@ import discord.errors from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( embed_spammer, # pylint: disable=E0401 embed_spammer_warn # pylint: disable=E0401 @@ -40,7 +39,7 @@ async def on_message(self, message): if isinstance(message.channel, discord.DMChannel): return - settings = GuildSettings(self.bot.settings.server, message.guild) + settings = self.bot.db_client.get_guild_settings(message.guild) # new speaker. Welcome to auto mod. if message.guild.id not in self.records: @@ -101,9 +100,9 @@ async def on_message(self, message): # timeout right away await message.author.timeout(until=datetime.utcnow() + timedelta(seconds=30)) - naughty = message.author.guild.get_role(settings.punishment_role) - verified = message.author.guild.get_role(settings.verified_role) - quarantine = await self.bot.fetch_channel(settings.quarantine_channel) + naughty = message.author.guild.get_role(settings["naughty_role"]) + verified = message.author.guild.get_role(settings["verified_role"]) + quarantine = await self.bot.fetch_channel(settings["quarantine_channel"]) # assign Naughty roll member = message.author diff --git a/src/zorak/cogs/admin/admin_purge.py b/src/zorak/cogs/admin/admin_purge.py index e188b6b4..35fd7711 100644 --- a/src/zorak/cogs/admin/admin_purge.py +++ b/src/zorak/cogs/admin/admin_purge.py @@ -2,7 +2,6 @@ Admin command to remove messages in bulk. """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings class AdminPurge(commands.Cog): @@ -22,11 +21,11 @@ async def purge_messages(self, ctx, number_messages): which throws an error when the user does not have the correct perms. We handle this with an error_handler block """ - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) # removes the need for a response await ctx.defer() - logs_channel = await self.bot.fetch_channel(settings.mod_log) # Welcome channel + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) # Welcome channel # Do the purge await ctx.channel.purge(limit=int(number_messages)) diff --git a/src/zorak/cogs/admin/error_handler.py b/src/zorak/cogs/admin/error_handler.py index 1d1e4bda..b70660fb 100644 --- a/src/zorak/cogs/admin/error_handler.py +++ b/src/zorak/cogs/admin/error_handler.py @@ -3,7 +3,6 @@ import discord from discord.ext import commands from datetime import datetime -from zorak.utilities.cog_helpers.guild_settings import GuildSettings logger = logging.getLogger(__name__) @@ -14,9 +13,9 @@ def __init__(self, bot): @commands.Cog.listener() async def on_application_command_error(self, ctx, error): - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) - error_log = await self.bot.fetch_channel(settings.error_log) + error_log = await self.bot.fetch_channel(settings["zorak_log"]) # # This is just an interesting way of handling errors PER ERROR. # # For now, let's just catch all and redirect to logs and channel diff --git a/src/zorak/cogs/admin/moderation_invites.py b/src/zorak/cogs/admin/moderation_invites.py index f6ddbc75..eab1af52 100644 --- a/src/zorak/cogs/admin/moderation_invites.py +++ b/src/zorak/cogs/admin/moderation_invites.py @@ -6,7 +6,6 @@ import discord from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings class ModerationInvites(commands.Cog): @@ -26,7 +25,7 @@ async def on_message(self, message): txt = message.content current_channel = message.channel author = message.author - settings = GuildSettings(self.bot.settings.server, author.guild) + settings = self.bot.db_client.get_guild_settings(message.guild) def is_invite(arg_message): """ @@ -95,7 +94,7 @@ def check_for_admin_override(arg_message): return if not check_for_admin_override(txt): - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) await logs_channel.send(embed=log_message(message)) await message.delete() await current_channel.send(embed=embed_warning(message)) diff --git a/src/zorak/cogs/admin/verification_on_join.py b/src/zorak/cogs/admin/verification_on_join.py index 2d04a3f7..b7da2697 100644 --- a/src/zorak/cogs/admin/verification_on_join.py +++ b/src/zorak/cogs/admin/verification_on_join.py @@ -5,7 +5,6 @@ import logging import discord from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings logger = logging.getLogger(__name__) @@ -53,9 +52,9 @@ async def send_welcome_message(self, guild, member, settings): @commands.Cog.listener() async def on_member_join(self, member: discord.Member): guild = member.guild - settings = GuildSettings(self.bot.settings.server, guild) + settings = self.bot.db_client.get_guild_settings(member.guild) - logs_channel = await self.bot.fetch_channel(settings.verification_log) + logs_channel = await self.bot.fetch_channel(settings["verification_log"]) await self.log_unverified_join(member, logs_channel) await self.send_welcome_message(guild, member, settings) diff --git a/src/zorak/cogs/admin/verification_on_verified.py b/src/zorak/cogs/admin/verification_on_verified.py index c88b5eb1..5e96a3a8 100644 --- a/src/zorak/cogs/admin/verification_on_verified.py +++ b/src/zorak/cogs/admin/verification_on_verified.py @@ -10,7 +10,7 @@ import discord from discord.ext import commands from time import sleep -from zorak.utilities.cog_helpers.guild_settings import GuildSettings + logger = logging.getLogger(__name__) @@ -124,7 +124,7 @@ def __init__(self, bot): @commands.slash_command(description="Verification!") async def verify(self, ctx): """The slash command that initiates the fancy menus.""" - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) if hasattr(self.bot.settings, "verification_options"): # TODO: THIS IS FROM THE OLD SETTINGS if "selectors" in self.bot.settings.verification_options: # TODO: THIS IS FROM THE OLD SETTINGS if "✅" not in [role.name for role in ctx.author.roles]: diff --git a/src/zorak/cogs/general/general_tickets.py b/src/zorak/cogs/general/general_tickets.py index 13af9708..a576789d 100644 --- a/src/zorak/cogs/general/general_tickets.py +++ b/src/zorak/cogs/general/general_tickets.py @@ -6,7 +6,7 @@ import discord from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings + logger = logging.getLogger(__name__) @@ -25,7 +25,7 @@ async def ticket(self, ctx): """ A simple command with a view. """ - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) logger.info("%s used the %s command.", ctx.author.name, ctx.command) await ctx.respond( "Do you need help, or do you have a question for the Staff?", @@ -53,8 +53,8 @@ async def button_callback(self, button, interaction): button.disabled = True await interaction.edit_original_response(view=self) - support = await interaction.guild.fetch_channel(self.settings.support_channel) - staff = interaction.guild.get_role(self.settings.admin_roles["staff"]) + support = await interaction.guild.fetch_channel(self.settings["support_channel"]) + staff = interaction.guild.get_role(self.settings["staff_role"]) ticket = await support.create_thread( name=f"[Ticket] - {interaction.user}", diff --git a/src/zorak/cogs/logging/logging_avatars.py b/src/zorak/cogs/logging/logging_avatars.py index 9b39b410..6f34dbcd 100644 --- a/src/zorak/cogs/logging/logging_avatars.py +++ b/src/zorak/cogs/logging/logging_avatars.py @@ -4,7 +4,6 @@ """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_avatar # pylint: disable=E0401 @@ -21,12 +20,12 @@ async def on_user_update(self, before, after): """ if the avatar before is != to the avatar after, do stuff. """ - settings = GuildSettings(self.bot.settings.server, before.guild) + settings = self.bot.db_client.get_guild_settings(after.guild) if before.avatar != after.avatar: embed = embed_avatar(before, after) - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_member_ban.py b/src/zorak/cogs/logging/logging_member_ban.py index f09f3136..7c259c51 100644 --- a/src/zorak/cogs/logging/logging_member_ban.py +++ b/src/zorak/cogs/logging/logging_member_ban.py @@ -3,7 +3,6 @@ """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_ban # pylint: disable=E0401 @@ -25,16 +24,16 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - settings = GuildSettings(self.bot.settings.server, member.guild) - current_guild = self.bot.get_guild(member.guild.id) - audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] + settings = self.bot.db_client.get_guild_settings(member.guild) + current_guild = self.bot.get_guild(settings["id"]) + audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.ban": if audit_log.target == member: embed = embed_ban(member, audit_log) - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_member_kick.py b/src/zorak/cogs/logging/logging_member_kick.py index 7888c973..5fd57c9c 100644 --- a/src/zorak/cogs/logging/logging_member_kick.py +++ b/src/zorak/cogs/logging/logging_member_kick.py @@ -3,7 +3,6 @@ """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_kick # pylint: disable=E0401 @@ -25,15 +24,15 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - settings = GuildSettings(self.bot.settings.server, member.guild) - current_guild = self.bot.get_guild(member.guild.id) + settings = self.bot.db_client.get_guild_settings(member.guild) + current_guild = self.bot.get_guild(settings["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.kick": if audit_log.target == member: embed = embed_kick(member, audit_log) - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_member_leaving.py b/src/zorak/cogs/logging/logging_member_leaving.py index 0fb3b09c..c2b9baa5 100644 --- a/src/zorak/cogs/logging/logging_member_leaving.py +++ b/src/zorak/cogs/logging/logging_member_leaving.py @@ -3,7 +3,6 @@ """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_leave # pylint: disable=E0401 @@ -25,14 +24,14 @@ async def on_member_remove(self, member): if "Needs Approval" in [role.name for role in member.roles]: return - settings = GuildSettings(self.bot.settings.server, member.guild) - current_guild = self.bot.get_guild(member.guild.id) + settings = self.bot.db_client.get_guild_settings(member.guild) + current_guild = self.bot.get_guild(settings["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) != "AuditLogAction.ban" and str(audit_log.action) != "AuditLogAction.kick": embed = embed_leave(member) - logs_channel = await self.bot.fetch_channel(settings.join_logs) + logs_channel = await self.bot.fetch_channel(settings["join_log"]) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_member_roles.py b/src/zorak/cogs/logging/logging_member_roles.py index 9b617f09..3c7ffed4 100644 --- a/src/zorak/cogs/logging/logging_member_roles.py +++ b/src/zorak/cogs/logging/logging_member_roles.py @@ -3,7 +3,6 @@ """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( # pylint: disable=E0401 embed_role_add, embed_role_remove, @@ -24,8 +23,9 @@ async def on_member_update(self, before, after): Checks what roles were changed, and logs it in the log channel. Can be quite spammy. """ - settings = GuildSettings(self.bot.settings.server, before.guild) - current_guild = self.bot.get_guild(before.guild.id) + settings = self.bot.db_client.get_guild_settings(after.guild) + + current_guild = self.bot.get_guild(settings["id"]) audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] if str(audit_log.action) == "AuditLogAction.member_role_update": @@ -33,7 +33,7 @@ async def on_member_update(self, before, after): responsible_member = audit_log.user changed_roles = [] - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) if len(before.roles) > len(after.roles): for role in before.roles: if role not in after.roles: diff --git a/src/zorak/cogs/logging/logging_member_unban.py b/src/zorak/cogs/logging/logging_member_unban.py index a6f180c7..b490e4a9 100644 --- a/src/zorak/cogs/logging/logging_member_unban.py +++ b/src/zorak/cogs/logging/logging_member_unban.py @@ -3,7 +3,6 @@ """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_unban # pylint: disable=E0401 @@ -21,9 +20,9 @@ async def on_member_unban(self, member): Just listen for the event, embed it, and send it off. """ embed = embed_unban(member) - settings = GuildSettings(self.bot.settings.server, member.guild) + settings = self.bot.db_client.get_guild_settings(member.guild) - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) await logs_channel.send(embed=embed) diff --git a/src/zorak/cogs/logging/logging_message_delete.py b/src/zorak/cogs/logging/logging_message_delete.py index a8b9c68f..34c1249c 100644 --- a/src/zorak/cogs/logging/logging_message_delete.py +++ b/src/zorak/cogs/logging/logging_message_delete.py @@ -6,7 +6,6 @@ import discord from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_message_delete logger = logging.getLogger(__name__) @@ -26,10 +25,10 @@ async def on_message_delete(self, message): """ If a mod deletes, take the audit log event. If a user deletes, handle it normally. """ - settings = GuildSettings(self.bot.settings.server, message.guild) - current_guild = message.guild + settings = self.bot.db_client.get_guild_settings(message.guild) + current_guild = settings["id"] audit_log = [entry async for entry in current_guild.audit_logs(limit=1)][0] - logs_channel = await self.bot.fetch_channel(settings.chat_log) + logs_channel = await self.bot.fetch_channel(settings["chat_log"]) # If the audit log is triggered, it means someone OTHER than the author deleted the message. # https://discordpy.readthedocs.io/en/stable/api.html @@ -44,8 +43,7 @@ async def on_message_delete(self, message): username = message.author for role in message.author.roles: - # TODO: .admin_roles no longer exists, find a workaround here. - if role.id in settings.admin_roles.values(): + if role.id in [settings['staff_role'], settings["admin_role"], settings["owner_role"]]: await logs_channel.send(embed=embed_message_delete(username, message)) return diff --git a/src/zorak/cogs/logging/logging_message_edit.py b/src/zorak/cogs/logging/logging_message_edit.py index 8d1991c6..80595105 100644 --- a/src/zorak/cogs/logging/logging_message_edit.py +++ b/src/zorak/cogs/logging/logging_message_edit.py @@ -4,7 +4,6 @@ import logging from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( embed_message_edit, # pylint: disable=E0401 ) @@ -25,7 +24,8 @@ async def on_message_edit(self, message_before, message_after): if message_before.author.bot or message_after.author.bot: return - settings = GuildSettings(self.bot.settings.server, message_after.guild) + settings = self.bot.db_client.get_guild_settings(message_before.guild) + # IGNORE /run, since we will set up an on_message_edit handler there with opposite logic if message_before.content.startswith('/run') or message_after.content.startswith('/run'): return @@ -45,7 +45,7 @@ async def on_message_edit(self, message_before, message_after): # This just gets really messy when we are cleaning things up # or doing dodgy business in secret places. embed = embed_message_edit(username, author, message_before, message_after) - logs_channel = await self.bot.fetch_channel(settings.chat_log) + logs_channel = await self.bot.fetch_channel(settings["chat_log"]) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/logging/logging_name_changes.py b/src/zorak/cogs/logging/logging_name_changes.py index c4aa0efb..30a657ce 100644 --- a/src/zorak/cogs/logging/logging_name_changes.py +++ b/src/zorak/cogs/logging/logging_name_changes.py @@ -3,7 +3,6 @@ """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( # pylint: disable=E0401 embed_name_change, embed_verified_success, @@ -23,7 +22,7 @@ async def on_member_update(self, before, after): """ Just checking if the name before is != to the name after. """ - settings = GuildSettings(self.bot.settings.server, before.guild) + if before.nick is None: username_before = before @@ -35,10 +34,12 @@ async def on_member_update(self, before, after): else: username_after = after.nick + settings = self.bot.db_client.get_guild_settings(before.guild if before.guild is not None else after.guild) + if before.nick != after.nick and before.nick is not None: embed = embed_name_change(before, after, username_before, username_after) - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) await logs_channel.send(f"{after.mention}", embed=embed) diff --git a/src/zorak/cogs/logging/logging_tickets.py b/src/zorak/cogs/logging/logging_tickets.py index b2171b7e..43326334 100644 --- a/src/zorak/cogs/logging/logging_tickets.py +++ b/src/zorak/cogs/logging/logging_tickets.py @@ -3,7 +3,6 @@ """ from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import ( # pylint: disable=E0401 embed_ticket_create, embed_ticket_delete, @@ -25,16 +24,16 @@ async def on_thread_create(self, thread): """ When a thread is created """ - settings = GuildSettings(self.bot.settings.server, thread.guild) + settings = self.bot.db_client.get_guild_settings(thread.guild) - current_guild = thread.guild + current_guild = settings["id"] audit_log = [entry async for entry in current_guild.audit_logs(limit=1)] entry = audit_log[0] target = "AuditLogAction.thread_create" if str(entry.action) == target and str(entry.target).startswith("[Ticket]"): - mod_log = await self.bot.fetch_channel(settings.mod_log) + mod_log = await self.bot.fetch_channel(settings["mod_log"]) embed = embed_ticket_create(entry.user, entry.target.mention) await mod_log.send(embed=embed) return @@ -44,8 +43,8 @@ async def on_thread_update(self, before): """ When a thread is updated, deleted or removed. """ - settings = GuildSettings(self.bot.settings.server, before.guild) - current_guild = before.guild + settings = self.bot.db_client.get_guild_settings(before.guild) + current_guild = settings["id"] audit_log = [entry async for entry in current_guild.audit_logs(limit=1)] entry = audit_log[0] @@ -54,19 +53,19 @@ async def on_thread_update(self, before): remove = "AuditLogAction.thread_remove" if str(entry.action) == update and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) embed = embed_ticket_update(entry.user, before.id) await logs_channel.send(embed=embed) return if str(entry.action) == delete and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) embed = embed_ticket_delete(entry.user, before.id) await logs_channel.send(embed=embed) return if str(entry.action) == remove and str(entry.target).startswith("[Ticket]"): - logs_channel = await self.bot.fetch_channel(settings.mod_log) + logs_channel = await self.bot.fetch_channel(settings["mod_log"]) embed = embed_ticket_remove(entry.user, before.id) await logs_channel.send(embed=embed) return diff --git a/src/zorak/cogs/utility/points.py b/src/zorak/cogs/utility/points.py index 8fa20044..66267a29 100644 --- a/src/zorak/cogs/utility/points.py +++ b/src/zorak/cogs/utility/points.py @@ -6,7 +6,6 @@ import discord from discord.ext import commands -from zorak.utilities.cog_helpers.guild_settings import GuildSettings from zorak.utilities.cog_helpers._embeds import embed_leaderboard @@ -20,7 +19,6 @@ def __init__(self, bot): raise Exception("Database client not found.") self.bot = bot - @commands.Cog.listener() async def on_member_join(self, member: discord.Member): # pylint: disable=E1101 """When a member joins, add them to the DB.""" @@ -42,11 +40,12 @@ async def on_message(self, message: discord.Message): @commands.Cog.listener() async def on_message_delete(self, message: discord.Message): """When a member deletes a message, remove a point.""" - settings = GuildSettings(self.bot.settings.server, message.guild) + settings = self.bot.db_client.get_guild_settings(message.guild) message_value = len(message.content.split(" ")) - mod_log = await self.bot.fetch_channel(settings.mod_log) + mod_log = await self.bot.fetch_channel(settings["mod_log"]) await mod_log.send(f"{message_value} Point/s removed from {message.author} for deleting a message.") self.bot.db_client.remove_points_from_user(message.author.id, abs(message_value)) + # # # TODO: Fix the backup command. # # @commands.slash_command() @@ -67,10 +66,10 @@ async def add_all_members_to_db(self, ctx): @commands.has_any_role("Admin", "Sudo", "Staff", "Project Manager") async def add_points_to_user(self, ctx, mention, points): """Add points to a user.""" - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.add_points_to_user(user.id, int(points)) - mod_log = await self.bot.fetch_channel(settings.mod_log) + mod_log = await self.bot.fetch_channel(settings["mod_log"]) await mod_log.send(f"{points} point{('s', '')[abs(int(points)) == 1]} added to {mention} by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(int(points)) == 1]} added to {mention}.") @@ -78,9 +77,9 @@ async def add_points_to_user(self, ctx, mention, points): @commands.has_any_role("Admin", "Sudo", "Staff", "Project Manager") async def add_points_to_all_users(self, ctx, points): """Add points to all users.""" - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) self.bot.db_client.add_points_to_all_users(int(points)) - mod_log = await self.bot.fetch_channel(settings.mod_log) + mod_log = await self.bot.fetch_channel(settings["mod_log"]) await mod_log.send(f"{points} point{('s', '')[abs(int(points)) == 1]} added to all users by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(int(points)) == 1]} added to all users.") @@ -90,10 +89,10 @@ async def remove_points_from_user(self, ctx, mention, points): """Remove points from a user.""" mention = str(mention) points = int(points) - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.remove_points_from_user(user.id, points) - mod_log = await self.bot.fetch_channel(settings.mod_log) + mod_log = await self.bot.fetch_channel(settings["mod_log"]) await mod_log.send(f"{points} point{('s', '')[abs(points) == 1]} removed from {mention} by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(points) == 1]} removed from {mention}.") @@ -102,9 +101,9 @@ async def remove_points_from_user(self, ctx, mention, points): async def remove_points_from_all_users(self, ctx, points): """Remove points from all users.""" points = int(points) - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) self.bot.db_client.remove_points_from_all_users(points) - mod_log = await self.bot.fetch_channel(settings.mod_log) + mod_log = await self.bot.fetch_channel(settings["mod_log"]) await mod_log.send(f"{points} point{('s', '')[abs(points) == 1]} removed from all users by {ctx.author}.") await ctx.respond(f"{points} point{('s', '')[abs(points) == 1]} removed from all users.") @@ -113,10 +112,10 @@ async def remove_points_from_all_users(self, ctx, points): async def reset_points_for_user(self, ctx, mention): """Reset points for a user.""" mention = str(mention) - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) user = self.bot.get_user(int(mention.split("@")[1].split(">")[0])) self.bot.db_client.set_user_points(user.id, 0) - mod_log = await self.bot.fetch_channel(settings.mod_log) + mod_log = await self.bot.fetch_channel(settings["mod_log"]) await mod_log.send(f"Points reset for {mention} by {ctx.author}.") await ctx.respond(f"Points reset for {mention}.") @@ -124,9 +123,9 @@ async def reset_points_for_user(self, ctx, mention): @commands.has_any_role("Admin", "Sudo", "Staff", "Project Manager") async def reset_points_for_all_users(self, ctx): """Reset points for all users.""" - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) self.bot.db_client.set_all_user_points(0) - mod_log = await self.bot.fetch_channel(settings.mod_log) + mod_log = await self.bot.fetch_channel(settings["mod_log"]) await mod_log.send(f"Points reset for all users by {ctx.author}.") await ctx.respond("Points reset for all users.") @@ -141,7 +140,7 @@ async def get_points_for_user(self, ctx, mention): @commands.slash_command() async def leaderboard(self, ctx): """Get your points.""" - settings = GuildSettings(self.bot.settings.server, ctx.guild) + settings = self.bot.db_client.get_guild_settings(ctx.guild) def is_staff(member_obj): """ Tells us if the 'member_obj' has an admin role. """ @@ -153,7 +152,7 @@ def is_staff(member_obj): top10_no_staff = [] points = self.bot.db_client.get_top_10() - guild = self.bot.get_guild(settings.info['id']) + guild = self.bot.get_guild(settings['id']) for iteration, person in enumerate(points): if len(top10_no_staff) < 10: # should only allow 10 people into the list diff --git a/src/zorak/utilities/cog_helpers/guild_settings.py b/src/zorak/utilities/cog_helpers/guild_settings.py deleted file mode 100644 index 02c2aad6..00000000 --- a/src/zorak/utilities/cog_helpers/guild_settings.py +++ /dev/null @@ -1,83 +0,0 @@ -import logging - - -logger = logging.getLogger(__name__) - - -class GuildSettings: - def __init__(self, settings, guild): - self.settings = settings - self.guild_name = guild - self.guild_id = str(guild.id) - self.guild_settings = self.settings[self.guild_id] - - if self.guild_id not in self.settings: - logger.warning(f"No settings found for guild: {self.guild_id}") - if self.guild_settings is None: - logger.warning(f"No settings found for guild: {self.guild_id}") - - # All Channel information for guilds - try: - self.general_channels = self.guild_settings["channels"]["general"] # has sub-channels - self.quarantine_channel = self.guild_settings["channels"]["quarantine"]["quarantine_channel"] # Explicit - self.support_channel = self.guild_settings["channels"]["support"]["server_support"] # Explicit - self.verification_channel = self.guild_settings["channels"]["verification"]["verification_channel"] # Explicit - except Exception as e: - logger.warning(f"Failed to grab channel info. Error: {e}") - self.general_channels = None - self.quarantine_channel = None - self.support_channel = None - self.verification_channel = None - - # All Logging channel information for guilds - try: - self.chat_log = self.guild_settings["channels"]["logging"]["chat_log"] - self.error_log =self.guild_settings["channels"]["logging"]["zorak_log"] - self.join_log = self.guild_settings["channels"]["logging"]["join_log"] - self.mod_log =self.guild_settings["channels"]["logging"]["mod_log"] - self.server_log =self.guild_settings["channels"]["logging"]["server_change_log"] - self.user_log = self.guild_settings["channels"]["logging"]["user_log"] - self.verification_log =self.guild_settings["channels"]["logging"]["verification_log"] - except Exception as e: - logger.warning(f"Failed to grab logging channels. Error: {e}") - self.chat_log = None - self.error_log = None - self.join_log = None - self.mod_log = None - self.server_log = None - self.user_log = None - self.verification_log = None - - # All Role information for guilds - try: - self.admin_roles = self.guild_settings["roles"]["admin"] # has sub-roles - self.reaction_roles = self.guild_settings["roles"]["reaction"] # has sub-roles - self.punishment_role = self.guild_settings["roles"]["punishment"]["naughty"] # explicit - self.verified_role = self.guild_settings["roles"]["verified"]["verified"] # explicit - except Exception as e: - logger.warning(f"Failed to grab role IDs. Error: {e}") - self.admin_roles = None - self.reaction_roles = None - self.punishment_role = None - self.verified_role = None - - # All General information for guilds - try: - self.info = self.guild_settings["info"] - except Exception as e: - logger.warning(f"Failed to grab server info. Error: {e}") - self.info = None - - - - - - - - - - - - - - From 2e1ca16b2f282a2b150f6a4e54f7ea4f60c64ba6 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:46:32 +0200 Subject: [PATCH 29/38] .gitignore update --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e0a77da0..dccf5e1b 100644 --- a/.gitignore +++ b/.gitignore @@ -158,4 +158,6 @@ data/ # ignore db data db/* /deploy -.env \ No newline at end of file +.env +/Pipfile +/Pipfile.lock From 6c4aec6148c796d85c9b724865f5d0452d5850ee Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:56:55 +0200 Subject: [PATCH 30/38] Moving this out of the way --- src/zorak/utilities/cog_utilities/__init__.py => __init__.py | 0 src/__init__.py | 0 src/zorak/_ARCHIVE/__init__.py | 0 src/zorak/{utilities/cog_utilities => _ARCHIVE}/blackjack.py | 0 src/zorak/{utilities/cog_utilities => _ARCHIVE}/card_deck.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/zorak/utilities/cog_utilities/__init__.py => __init__.py (100%) create mode 100644 src/__init__.py create mode 100644 src/zorak/_ARCHIVE/__init__.py rename src/zorak/{utilities/cog_utilities => _ARCHIVE}/blackjack.py (100%) rename src/zorak/{utilities/cog_utilities => _ARCHIVE}/card_deck.py (100%) diff --git a/src/zorak/utilities/cog_utilities/__init__.py b/__init__.py similarity index 100% rename from src/zorak/utilities/cog_utilities/__init__.py rename to __init__.py diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/zorak/_ARCHIVE/__init__.py b/src/zorak/_ARCHIVE/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/zorak/utilities/cog_utilities/blackjack.py b/src/zorak/_ARCHIVE/blackjack.py similarity index 100% rename from src/zorak/utilities/cog_utilities/blackjack.py rename to src/zorak/_ARCHIVE/blackjack.py diff --git a/src/zorak/utilities/cog_utilities/card_deck.py b/src/zorak/_ARCHIVE/card_deck.py similarity index 100% rename from src/zorak/utilities/cog_utilities/card_deck.py rename to src/zorak/_ARCHIVE/card_deck.py From 172f8f8cd9c861fa9e6dfcd9ea0313334c43313a Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:57:11 +0200 Subject: [PATCH 31/38] This too --- src/zorak/{utilities/cog_utilities => _ARCHIVE}/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/zorak/{utilities/cog_utilities => _ARCHIVE}/README.md (100%) diff --git a/src/zorak/utilities/cog_utilities/README.md b/src/zorak/_ARCHIVE/README.md similarity index 100% rename from src/zorak/utilities/cog_utilities/README.md rename to src/zorak/_ARCHIVE/README.md From 32f39b27581a6c51dde283869ffed8e8a91395a7 Mon Sep 17 00:00:00 2001 From: Xarlos89 <57622136+Xarlos89@users.noreply.github.com> Date: Sun, 7 Apr 2024 14:47:25 +0200 Subject: [PATCH 32/38] - Allows us to update MongoDB Guild settings for the current guild. Would not say this is the final iteration --- src/zorak/cogs/admin/update_settings.py | 149 ++++++++++++++++++++++-- 1 file changed, 142 insertions(+), 7 deletions(-) diff --git a/src/zorak/cogs/admin/update_settings.py b/src/zorak/cogs/admin/update_settings.py index 9ec521cb..48aaa3f4 100644 --- a/src/zorak/cogs/admin/update_settings.py +++ b/src/zorak/cogs/admin/update_settings.py @@ -2,15 +2,13 @@ A simple hello command. """ import logging -from random import shuffle import discord +from discord import option from discord.ext import commands -from time import sleep logger = logging.getLogger(__name__) - class Settings(commands.Cog): """ This is the class that defines the actual slash command. @@ -20,14 +18,151 @@ class Settings(commands.Cog): def __init__(self, bot): self.bot = bot # Passed in from main.py - @commands.slash_command(description="Edit the bot settings for your guild!") - async def update_settings(self, ctx, setting: str, value: str): + @commands.slash_command(description="See the bot settings for your guild!") + async def setup_zorak(self, ctx): + self.bot.db_client.add_guild_to_table(ctx.guild) + await ctx.respond(f"Added {ctx.guild.name} to database.") + + #################### + # Roles + #################### + @commands.slash_command(description="See the roles for your guild!") + async def see_roles(self, ctx): + """The slash command that initiates the fancy menus.""" + settings = self.bot.db_client.get_guild_settings(ctx.guild) + pretty_printed_settings = "" + for key, value in settings.items(): + if "_role" in key: + pretty_printed_settings += f"{key}: <@{value}>\n" + + await ctx.respond(f"### Guild Roles for {ctx.guild}\n{pretty_printed_settings}") + + @commands.slash_command() + @option( + "position" + , description="All options for roles." + , choices=[ + "Guild Owner role" + , "Administrator role" + , "Staff/Moderatior role" + , "Networking role" + , "Zorak's Bot role" + , "Punishment/Quarantine role" + , "Verification role" + ]) + async def update_roles( + self + , ctx: discord.ApplicationContext + , position: str + , role: discord.Role + ): + mapper = { + "Guild Owner role": "owner_role", + "Administrator role": "admin_role", + "Staff/Moderator role": "staff_role", + "Networking role": "networking_role", + "Zorak's Bot role": "bot_role", + "Punishment/Quarantine role": "naughty_role", + "Verification role": "verified_role" + } + self.bot.db_client.update_guild_settings(ctx.guild, mapper[position], int(role.id)) + logger.info(f"{ctx.author.name} updated {mapper[position]} in {ctx.guild.name} to {role.id}") + await ctx.respond(f"Updated {position} in {ctx.guild.name}. New Value: {role.mention}") + + #################### + # Normal Channels + #################### + @commands.slash_command(description="See the channels for your guild!") + async def see_channels(self, ctx): """The slash command that initiates the fancy menus.""" - self.bot.db_client.update_guild_settings(ctx.guild, setting, int(value)) + settings = self.bot.db_client.get_guild_settings(ctx.guild) + pretty_printed_settings = "" + for key, value in settings.items(): + if "_channel" in key: + pretty_printed_settings += f"{key}: <#{value}>\n" + + await ctx.respond(f"### Guild channels for {ctx.guild}\n{pretty_printed_settings}") + + @commands.slash_command() + @option( + "option" + , description="All options for Guild channels." + , choices=[ + "Verification Channel" + , "Quarantine Channel" + , "Support/Ticket Channel" + , "Reaction Role Channel" + , "Rules Channel" + , "General Channel" + , "Resources Channel" + , "Challenges Channel" + ]) + async def update_channels( + self + , ctx: discord.ApplicationContext + , option: str + , channel: discord.TextChannel + ): + mapper = { + "Verification Channel": "verification_channel", + "Quarantine Channel": "quarantine_channel", + "Support/Ticket Channel": "support_channel", + "Reaction Role Channel": "role_channel", + "Rules Channel": "rules_channel", + "General Channel": "general_channel", + "Resources Channel": "resources_channel", + "Challenges Channel": "challenges_channel" + } + self.bot.db_client.update_guild_settings(ctx.guild, mapper[option], int(channel.id)) + logger.info(f"{ctx.author.name} updated {mapper[option]} in {ctx.guild.name} to {channel.id}") + await ctx.respond(f"Updated {option} in {ctx.guild.name}. New Value: {channel.mention}") - await ctx.respond(f"Updated {setting} in {ctx.guild.name}. New Value: {value}") + #################### + # Logging Channels + #################### + + @commands.slash_command(description="See the logging channels for your guild!") + async def see_logging_channels(self, ctx): + """The slash command that initiates the fancy menus.""" + settings = self.bot.db_client.get_guild_settings(ctx.guild) + pretty_printed_settings = "" + for key, value in settings.items(): + if "_log" in key: + pretty_printed_settings += f"{key}: <#{value}>\n" + await ctx.respond(f"### Guild logging channels for {ctx.guild}\n{pretty_printed_settings}") + @commands.slash_command() + @option( + "logs" + , description="All options for logging channels." + , choices=[ + "User chat logs" + , "Join/leave logs" + , "Moderation action logs" + , "Server change logs" + , "User change logs" + , "Verification logs" + , "Zorak error logging" + ]) + async def update_logging_channels( + self + , ctx: discord.ApplicationContext + , logs: str + , channel: discord.TextChannel + ): + mapper = { + "User chat logs": "chat_log", + "Join/leave logs": "join_log", + "Moderation action logs": "mod_log", + "Server change logs": "server_change_log", + "User change logs": "user_log", + "Verification logs": "verification_log", + "Zorak error logging": "zorak_log" + } + self.bot.db_client.update_guild_settings(ctx.guild, mapper[logs], int(channel.id)) + logger.info(f"{ctx.author.name} updated {mapper[logs]} in {ctx.guild.name} to {channel.id}") + await ctx.respond(f"Updated {logs} in {ctx.guild.name}. New Value: {channel.mention}") def setup(bot): From 47d4a5573c8d948bef0ef129c00d7b34dbad555e Mon Sep 17 00:00:00 2001 From: Xarlos89 <57622136+Xarlos89@users.noreply.github.com> Date: Sun, 7 Apr 2024 15:20:28 +0200 Subject: [PATCH 33/38] - Need to encode things as a Long. not a String --- src/zorak/utilities/core/mongo.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/zorak/utilities/core/mongo.py b/src/zorak/utilities/core/mongo.py index 872b02ec..b681e048 100644 --- a/src/zorak/utilities/core/mongo.py +++ b/src/zorak/utilities/core/mongo.py @@ -2,6 +2,7 @@ import logging import time from typing import Dict, List +from bson.int64 import Int64 import pymongo from discord.ext.commands import Bot @@ -358,13 +359,18 @@ def initialise_settings_table(self): logger.info("GuildSettings initialised.") def get_guild_settings(self, guild): - settings = self.find_one("GuildSettings", {"id": guild.id}) + settings = self.find_one("GuildSettings", {"id": Int64(guild.id)}) if settings: return settings return None + def guild_exists_in_db(self, guild): + if self.find_one("GuildSettings", {"id": Int64(guild.id)}): + return True + return False + def add_guild_to_table(self, guild): - if not self.find_one("GuildSettings", {"id": guild.id}): + if not self.find_one("GuildSettings", {"id": Int64(guild.id)}): logger.info(f" ---- Adding {guild.name} to DB") self.insert_one("GuildSettings", { # Guild Info @@ -423,7 +429,7 @@ def update_guild_settings(self, guild, item, value): """Update the settings of a guild.""" try: self.update_one( - "GuildSettings", {"id": guild.id}, {"$set": {item: value}} + "GuildSettings", {"id": Int64(guild.id)}, {"$set": {item: value}} ) # The $set operator replaces the value of a field with the specified value. except Exception as ohfuck: From 3c2b6e3b240570d8b86108c75b552db8aa3c4b6c Mon Sep 17 00:00:00 2001 From: Xarlos89 <57622136+Xarlos89@users.noreply.github.com> Date: Sun, 7 Apr 2024 15:20:49 +0200 Subject: [PATCH 34/38] - Entrypoint for Zorak setup --- src/zorak/cogs/admin/update_settings.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/zorak/cogs/admin/update_settings.py b/src/zorak/cogs/admin/update_settings.py index 48aaa3f4..8b69804f 100644 --- a/src/zorak/cogs/admin/update_settings.py +++ b/src/zorak/cogs/admin/update_settings.py @@ -20,8 +20,25 @@ def __init__(self, bot): @commands.slash_command(description="See the bot settings for your guild!") async def setup_zorak(self, ctx): - self.bot.db_client.add_guild_to_table(ctx.guild) - await ctx.respond(f"Added {ctx.guild.name} to database.") + if not self.bot.db_client.guild_exists_in_db(ctx.guild): + self.bot.db_client.add_guild_to_table(ctx.guild) + await ctx.respond( + f"## **Added {ctx.guild.name} to database.**" + f"\n\nPlease use the **/update_roles** command to set Guild roles." + f"\nPlease use the **/update_channels** command to set Guild channels." + f"\nPlease use the **/update_logging_channels** command to set Guild log channels." + f"\n\nTo see roles, use **/see_roles**." + f"\nTo see channels, use **/see_channels**." + f"\nTo see logging channels, use **/see_logging_channels**." + ) + else: + await ctx.respond( + f"Looks like {ctx.guild.name} is already in the database." + f"\n\nTo see roles, use **/see_roles**." + f"\nTo see channels, use **/see_channels**." + f"\nTo see logging channels, use **/see_logging_channels**." + ) + #################### # Roles From 24b669cbddd7b6407e9cace25881c04156ad4067 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Tue, 9 Apr 2024 20:57:32 +0200 Subject: [PATCH 35/38] Start removal of reaction_roles.toml --- .../ServerConfig/dev/reaction_roles.toml | 169 ------------------ 1 file changed, 169 deletions(-) delete mode 100644 Resources/ServerConfig/dev/reaction_roles.toml diff --git a/Resources/ServerConfig/dev/reaction_roles.toml b/Resources/ServerConfig/dev/reaction_roles.toml deleted file mode 100644 index 04a72b29..00000000 --- a/Resources/ServerConfig/dev/reaction_roles.toml +++ /dev/null @@ -1,169 +0,0 @@ -#### PRODUCTION -# -#[reaction_roles.experience] -#beginner = 965926311539388457 -#intermediate = 965926533984288778 -#professional = 965926542481956906 -# -#[reaction_roles.location] -#north_america = 974950715892072488 -#europe = 974950822133776425 -#asia = 974950853452636200 -#africa = 974950895387303977 -#south_america = 974950944586489856 -#oceana = 974951025050025984 -# -#[reaction_roles.employment] -#open_to_work = 1113020825596067850 -#employer = 1113020504148815944 -# -#[reaction_roles.color] -#red = 1148145845770915870 -#orange = 1148145321302560769 -#yellow = 1148145167736520764 -#light_green = 1148144840735981569 -#dark_green = 1148147946068643900 -#light_blue = 1148144625836625961 -#blue = 1148144828631224391 -#pink = 1143109787316396082 -#purple = 1148146380880216065 -# -#[selectors.experience] -#name = "experience" -#single_choice = true -#description = "Select your skill level!" -#options = [ -# { label = "Beginner", emoji = "🟢", description = "Have little to no Python Experience", id = 965926311539388457 }, -# { label = "Intermediate", emoji = "🟡", description = "Can solve issues and diagnose problems", id = 965926533984288778 }, -# { label = "Professional", emoji = "🔴", description = "Using Python in professional life.", id = 965926542481956906 }, -#] -# -#[selectors.location] -#name = "location" -#single_choice = true -#description = "Select your continent!" -#options = [ -# { label = "North America", emoji = "🦅", description = "", id = 974950715892072488 }, -# { label = "Europe", emoji = "🇪🇺", description = "", id = 974950822133776425 }, -# { label = "Asia", emoji = "🐼", description = "", id = 974950853452636200 }, -# { label = "Oceana", emoji = "🐨", description = "", id = 974951025050025984 }, -# { label = "South America", emoji = "💃", description = "", id = 974950944586489856 }, -# { label = "Africa", emoji = "🦒", description = "", id = 974950895387303977 }, -#] -# -#[selectors.employment] -#name = "employment" -#single_choice = false -#description = "Are you open to work / Looking for a developer?!" -#options = [ -# { label = "Open to Work", emoji = "🛠️", description = "You are open to taking Python related jobs.", id = 1113020825596067850 }, -# { label = "Employer", emoji = "💼", description = "You are looking to hiring a Python developer.", id = 1113020504148815944 } -# -#] -# -#[selectors.color] -#name = "color" -#single_choice = true -#description = "Select your color!" -#options = [ -# { label = "Red", emoji = "🔴", description = "", id = 1148145845770915870 }, -# { label = "Orange", emoji = "🟠", description = "", id = 1148145321302560769 }, -# { label = "Yellow", emoji = "🟡", description = "", id = 1148145167736520764 }, -# { label = "Light Green", emoji = "🍐", description = "", id = 1148144840735981569 }, -# { label = "Dark Green", emoji = "🟢", description = "", id = 1148147946068643900 }, -# { label = "Light Blue", emoji = "🧊", description = "", id = 1148144625836625961 }, -# { label = "Blue", emoji = "🔵", description = "", id = 1148144828631224391 }, -# { label = "Pink", emoji = "🌸", description = "", id = 1143109787316396082 }, -# { label = "Purple", emoji = "🟣", description = "", id = 1148146380880216065 }, -#] -# - -### DEVELOPMENT - -[reaction_roles.experience] -beginner = 1064259543250522112 -intermediate = 1064259555497877534 -professional = 1064259557049761863 - -[reaction_roles.location] -north_america = 1064259558819770379 -europe = 1064259561302794361 -asia = 1064259687924637768 -africa = 1064259690948722708 -south_america = 1064259693545013288 -oceana = 1064259760674840666 - -[reaction_roles.employment] -open_to_work = 1113020825596067850 -employer = 1113020504148815944 -ping = 1213857615537250324 - -[reaction_roles.color] -red = 1149951355000201267 -orange = 1149951496872546337 -yellow = 1149951592968241213 -light_green = 1149951635842420809 -dark_green = 1149951734345637888 -light_blue = 1149951815773868092 -blue = 1149951872711528529 -pink = 1149951973513252914 -purple = 1149951930253185084 - -[selectors.notifications] -name = "Server notifications" -single_choice = true -description = "Do you want to receive relevant server pings for news, events and announcements?" -options = [ - { label = "Yes!", emoji = "🟢", description = "I want to receive Pings from the server.", id = 1213857615537250324 }, -] - - -[selectors.experience] -name = "experience" -single_choice = true -description = "Select your skill level!" -options = [ - { label = "Beginner", emoji = "🟢", description = "Have little to no Python Experience", id = 1064259543250522112 }, - { label = "Intermediate", emoji = "🟡", description = "Can solve issues and diagnose problems", id = 1064259555497877534 }, - { label = "Professional", emoji = "🔴", description = "Using Python in professional life.", id = 1064259557049761863 }, -] - - -[selectors.location] -name = "location" -single_choice = true -description = "Select your continent!" -options = [ - { label = "North America", emoji = "🦅", description = "", id = 1064259558819770379 }, - { label = "Europe", emoji = "🇪🇺", description = "", id = 1064259561302794361 }, - { label = "Asia", emoji = "🐼", description = "", id = 1064259687924637768 }, - { label = "Oceana", emoji = "🐨", description = "", id = 1064259760674840666 }, - { label = "South America", emoji = "💃", description = "", id = 1064259693545013288 }, - { label = "Africa", emoji = "🦒", description = "", id = 1064259690948722708 }, -] - -[selectors.employment] -name = "employment" -single_choice = false -description = "Are you open to work / Looking for a developer?!" -options = [ - { label = "Open to Work", emoji = "🛠️", description = "You are open to taking Python related jobs.", id = 1114611004182102218 }, - { label = "Employer", emoji = "💼", description = "You are looking to hiring a Python developer.", id = 1114611092677722113 } - -] - -[selectors.color] -name = "color" -single_choice = true -description = "Select your color!" -options = [ - { label = "Red", emoji = "🔴", description = "", id = 1149951355000201267 }, - { label = "Orange", emoji = "🟠", description = "", id = 1149951496872546337 }, - { label = "Yellow", emoji = "🟡", description = "", id = 1149951592968241213 }, - { label = "Light Green", emoji = "🍐", description = "", id = 1149951635842420809 }, - { label = "Dark Green", emoji = "🟢", description = "", id = 1149951734345637888 }, - { label = "Light Blue", emoji = "🧊", description = "", id = 1149951815773868092 }, - { label = "Blue", emoji = "🔵", description = "", id = 1149951872711528529 }, - { label = "Pink", emoji = "🌸", description = "", id = 1149951973513252914 }, - { label = "Purple", emoji = "🟣", description = "", id = 1149951930253185084 }, -] From 36dd7c3b5e8c9c523f1172b93352c45b299d6f18 Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Tue, 9 Apr 2024 20:57:55 +0200 Subject: [PATCH 36/38] Add ReactionRoles handler to mongo.py --- src/zorak/utilities/core/mongo.py | 108 ++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/src/zorak/utilities/core/mongo.py b/src/zorak/utilities/core/mongo.py index b681e048..6cb3bb45 100644 --- a/src/zorak/utilities/core/mongo.py +++ b/src/zorak/utilities/core/mongo.py @@ -192,6 +192,7 @@ class CustomMongoDBClient(MongoDBClient): """A further extension ontop of the earlier MongoDB class to abstract functions to be able to more easily interact with a custom database design. This is only intended to handle a single guild, but could be extended to handle multiple guilds by adding a guild_id field + guild, but could be extended to handle multiple guilds by adding a guild_id field to the user table, or adding a new table for each guild.""" ############### @@ -439,6 +440,112 @@ def remove_guild_from_table(self, guild): """Remove a guild from the GuildSettings table.""" self.delete_one("GuildSettings", {"id": guild.id}) + + + ############### + # Reaction Roles + ############### + def initialise_reaction_roles_table(self): + """Initialise the reaction roles table.""" + validator = { + "type": "object", + "properties": { + "ReactionRoles": { + "type": "array", + "items": { + "type": "object", + "properties": { + "guildID": {"type": "integer"}, + "name": {"type": "string"}, + "single_choice": {"type": "boolean"}, + "description": {"type": "string"}, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": {"type": "string"}, + "emoji": {"type": "string"}, + "description": {"type": "string"}, + "id": {"type": "integer"} + }, + "required": ["label", "emoji", "id"] + } + } + }, + "required": ["guildID", "name", "single_choice", "description", "options"] + } + } + }, + "required": ["ReactionRoles"] + } + self.create_collection("ReactionRoles", validator_schema=validator) + logger.info("ReactionRoles initialised.") + + def add_reaction_role_to_table(self, guild, reaction_role_data): + """Add a reaction role set to the reaction roles table for the specified guild.""" + if not self.find_one("ReactionRoles", {"guildID": Int64(guild.id), "name": reaction_role_data["name"]}): + self.insert_one("ReactionRoles", reaction_role_data) + + def remove_reaction_role_from_table(self, guild, reaction_role_data): + """Remove a reaction role set from the reaction roles table for the specified guild.""" + if self.find_one("ReactionRoles", {"guildID": Int64(guild.id), "name": reaction_role_data["name"]}): + self.delete_one({"guildID": Int64(guild.id), "name": reaction_role_data["name"]}) + + def update_reaction_role_set(self, guild, reaction_role_id, updated_data): + """Update a reaction role set in the reaction roles table for the specified guild.""" + if self.find_one("ReactionRoles", {"guildID": Int64(guild.id), "name": updated_data["name"]}): + self.update_one( + "ReactionRoles" + , {"guildID": Int64(guild.id), "name": updated_data["name"]} + , {"$set": updated_data} + ) + + def see_all_reaction_role_sets(self, guild): + """See all reaction role sets in the reaction roles table for the specified guild.""" + return self.find("ReactionRoles", {"guildID": Int64(guild.id)}) + + def see_one_reaction_role_set(self, guild, name): + """See one reaction role set from the reaction roles table for the specified guild.""" + return self.find_one("ReactionRoles", {"guildID": Int64(guild.id), "name": name}) + + + ### EXAMPLE + # Assuming you have instantiated your custom MongoDB class as db + + # Define the reaction role data + # reaction_role_id = 1 # Unique identifier for the reaction role set + # reaction_role_data = { + # "name": "Color", + # "single_choice": True, + # "description": "Select your favorite color!", + # "options": [ + # { + # "label": "Red", + # "emoji": "🔴", + # "description": "The color red", + # "id": 1234567 + # }, + # { + # "label": "Blue", + # "emoji": "🔵", + # "description": "The color blue", + # "id": 1234568 + # }, + # { + # "label": "Green", + # "emoji": "🟢", + # "description": "The color green", + # "id": 1234569 + # } + # ] + # } + # + # # Add the reaction role set to the table + # db.add_reaction_role_to_table(reaction_role_id, reaction_role_data) + + + ############### # Users ############### @@ -619,6 +726,7 @@ def initialise_bot_db( db_client.initialise_user_table() # type: ignore db_client.initialise_settings_table() # type: ignore + db_client.initialise_reaction_roles_table() # type: ignore bot.db_client = db_client # type: ignore # This adds the db_client to the bot From 991339de2949894d079684959880ae09d98aaf0a Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Tue, 9 Apr 2024 20:58:08 +0200 Subject: [PATCH 37/38] Remove toml links in settings --- src/zorak/utilities/core/settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/zorak/utilities/core/settings.py b/src/zorak/utilities/core/settings.py index 61bc00c0..34350954 100644 --- a/src/zorak/utilities/core/settings.py +++ b/src/zorak/utilities/core/settings.py @@ -15,15 +15,15 @@ def __init__(self, settings_path, all_guilds): return - self.settings_path = os.path.join(settings_path, "FAKE_DB_settings.json") + # self.settings_path = os.path.join(settings_path, "FAKE_DB_settings.json") self.reactions_path = os.path.join(settings_path, "reaction_roles.toml") self.reactions_path = os.path.join(settings_path, "reaction_roles.toml") self.verification_path = os.path.join(settings_path, "verification_options.toml") - with open(self.settings_path, 'r') as f: - server_settings = json.load(f) - self.server = server_settings + # with open(self.settings_path, 'r') as f: + # server_settings = json.load(f) + # self.server = server_settings # Reaction Roles From b629d50b1f6aab05586f92d76be14c4c7aef21ca Mon Sep 17 00:00:00 2001 From: Xarlos <57622136+Xarlos89@users.noreply.github.com> Date: Tue, 9 Apr 2024 20:58:30 +0200 Subject: [PATCH 38/38] START working on command --- src/zorak/cogs/admin/reaction_roles.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/zorak/cogs/admin/reaction_roles.py b/src/zorak/cogs/admin/reaction_roles.py index 93328bd3..9b725dab 100644 --- a/src/zorak/cogs/admin/reaction_roles.py +++ b/src/zorak/cogs/admin/reaction_roles.py @@ -95,13 +95,13 @@ def __init__(self, bot): @commands.slash_command(description="Get new roles, or change the ones you have!") async def roles(self, ctx): """The slash command that initiates the fancy menus.""" - if hasattr(self.bot.settings.roles, "reaction"): - if "reaction_roles" in self.bot.settings.reaction: - await ctx.respond("Edit Reaction Roles", view=SelectView(self.bot.settings.reaction), ephemeral=True) - else: - await ctx.respond("No reaction roles have been set up!", ephemeral=True) + guild_roles = self.bot.db_client.see_all_reaction_role_sets(ctx.guild) + logger.critical(guild_roles) + if "ReactionRoles" in guild_roles: + await ctx.respond("Edit Reaction Roles", view=SelectView(guild_roles), ephemeral=True) else: - await ctx.respond("No server settings have been set up!", ephemeral=True) + await ctx.respond("No reaction roles have been set up!", ephemeral=True) + def setup(bot):