From 6bb75ba0a10f49c70292f0f80fd1a021dd8024ad Mon Sep 17 00:00:00 2001 From: Nicholas Smit Date: Sat, 30 Sep 2023 23:02:14 -0400 Subject: [PATCH] Bump version Bump version for release. Use proper semver checking in update manager instead of string matching. Make class of commands for debugging and only register to an internal guild. --- Framework/CommandGroups/Debugging.py | 51 +++++++++++++++++++ Framework/CommandGroups/Fun.py | 38 -------------- .../UpdateManager/UpdateManager.py | 45 ++++++++-------- README.md | 2 +- TitanBot.py | 6 ++- requirements.txt | 3 +- 6 files changed, 83 insertions(+), 62 deletions(-) create mode 100644 Framework/CommandGroups/Debugging.py diff --git a/Framework/CommandGroups/Debugging.py b/Framework/CommandGroups/Debugging.py new file mode 100644 index 0000000..485b331 --- /dev/null +++ b/Framework/CommandGroups/Debugging.py @@ -0,0 +1,51 @@ +import discord +from discord.ext import commands + +from ..GeneralUtilities import PermissionHandler + + +class Debugging(commands.Cog): + """Debug only commands.""" + + debugging = discord.SlashCommandGroup("debugging", description="Debug only commands", guild_ids=[1025825210005475408]) + + def __init__(self, management_portal_handler): + self.mph = management_portal_handler + + @debugging.command() + @commands.guild_only() + async def speak_debug_only(self, ctx: discord.ApplicationContext, message: str, channel: str = None, hide_user: bool = False): + """Make the bot say something in a channel. Debug only, allows any channel ID.""" + + embed = discord.Embed(color=discord.Color.dark_blue(), description='') + embed, failedPermissionCheck = await PermissionHandler.check_permissions(ctx, self.mph, embed, "fun", "speak") + if not failedPermissionCheck: + user = ctx.author + + if channel is None: + channel = ctx.channel + else: + # lookup channel by id + channel = ctx.bot.get_channel(int(channel)) + + try: + send_failed = False + if hide_user: + if user.guild_permissions.administrator or PermissionHandler.is_superuser(self.mph, user.id): + await channel.send(message) + else: + send_failed = True + else: + await channel.send(f"({user.name}) " + message) + + if send_failed: + embed.title = "Failed to speak" + embed.description = "You do not have permission to hide your identity." + else: + embed.title = "Message sent" + embed.description = f"Sent message to {channel.mention}" + except discord.Forbidden: + embed.title = "Failed to speak" + embed.description = "I don't have permission to speak in that channel." + + await ctx.respond(embed=embed) diff --git a/Framework/CommandGroups/Fun.py b/Framework/CommandGroups/Fun.py index 3280b53..6534409 100644 --- a/Framework/CommandGroups/Fun.py +++ b/Framework/CommandGroups/Fun.py @@ -131,44 +131,6 @@ async def speak(self, ctx: discord.ApplicationContext, message: str, channel: di await ctx.respond(embed=embed) await self.mph.update_management_portal_command_used("fun", "speak", ctx.guild.id) - @fun.command(guild_ids=[1025825210005475408]) - @commands.guild_only() - async def speak_debug_only(self, ctx: discord.ApplicationContext, message: str, channel: str = None, hide_user: bool = False): - """Make the bot say something in a channel. Debug only, allows any channel ID.""" - - embed = discord.Embed(color=discord.Color.dark_blue(), description='') - embed, failedPermissionCheck = await PermissionHandler.check_permissions(ctx, self.mph, embed, "fun", "speak") - if not failedPermissionCheck: - user = ctx.author - - if channel is None: - channel = ctx.channel - else: - # lookup channel by id - channel = ctx.bot.get_channel(int(channel)) - - try: - send_failed = False - if hide_user: - if user.guild_permissions.administrator or PermissionHandler.is_superuser(self.mph, user.id): - await channel.send(message) - else: - send_failed = True - else: - await channel.send(f"({user.name}) " + message) - - if send_failed: - embed.title = "Failed to speak" - embed.description = "You do not have permission to hide your identity." - else: - embed.title = "Message sent" - embed.description = f"Sent message to {channel.mention}" - except discord.Forbidden: - embed.title = "Failed to speak" - embed.description = "I don't have permission to speak in that channel." - - await ctx.respond(embed=embed) - @fun.command() @commands.guild_only() async def inspirobot_query(self, ctx: discord.ApplicationContext): diff --git a/Framework/FileSystemAPI/UpdateManager/UpdateManager.py b/Framework/FileSystemAPI/UpdateManager/UpdateManager.py index 597c661..a2a95b5 100644 --- a/Framework/FileSystemAPI/UpdateManager/UpdateManager.py +++ b/Framework/FileSystemAPI/UpdateManager/UpdateManager.py @@ -5,6 +5,7 @@ import aiohttp import discord +import semver from discord.ext.bridge import Bot from Framework.FileSystemAPI import DatabaseObjects @@ -45,31 +46,35 @@ async def check_for_updates(self): if "-indev" in current_release: self.logger.log_warning("Development version detected, skipping update check") return - # If the current release is not the latest release, update is available - if current_release != latest_release: - self.update_available = True - self.logger.log_info("An update is available: " + latest_release) - - # Check if an update has already been downloaded, and is pending installation - if os.path.exists(await DatabaseObjects.get_update_metadata()): - with open(await DatabaseObjects.get_update_metadata(), "r") as file: - update_metadata = json.load(file) - - try: - if update_metadata["version"] == latest_release: - self.logger.log_info("An update has already been downloaded, and is pending installation") - # If it is unscheduled, the bot is just starting up, so install the update - if not self.scheduled: - await self.install_update() - except TypeError: + # Use semver to compare the current release to the latest release (strip the v from the version string) + match semver.compare(current_release[1:], latest_release[1:]): + case -1: + self.update_available = True + self.logger.log_info("An update is available: " + latest_release) + + # Check if an update has already been downloaded, and is pending installation + if os.path.exists(await DatabaseObjects.get_update_metadata()): + with open(await DatabaseObjects.get_update_metadata(), "r") as file: + update_metadata = json.load(file) + try: + if update_metadata["version"] == latest_release: + self.logger.log_info("An update has already been downloaded, and is pending installation") + # If it is unscheduled, the bot is just starting up, so install the update + if not self.scheduled: + await self.install_update() + except TypeError: + await self.download_update(latest_release) + else: await self.download_update(latest_release) - else: - await self.download_update(latest_release) + case 0: + self.logger.log_info("TitanBot is up to date") + case 1: + self.logger.log_info("Running a newer version than the latest release, assuming development version") async def download_update(self, tag_name: str): # Download the latest release from the GitHub repository if self.update_available: - await self.bot.change_presence(activity=discord.Game(name="Downloading updates..."), status=discord.Status.dnd) + await self.bot.change_presence(activity=discord.CustomActivity(name="Downloading updates..."), status=discord.Status.dnd) self.logger.log_info("Preparing for update...") # Create a metadata file for the update diff --git a/README.md b/README.md index 91cdca7..e5be991 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ you will need to provide the server. #### What TitanBot needs: - A folder to operate in -- A Python 3 installation (currently built with `3.11.2`, older versions may work but aren't verified) +- A Python 3 installation (currently built with `3.11.5`, older versions may work but aren't verified) - Some `pip` modules. Those can be installed from the `requirements.txt` file in the repository. You will need to create a `.env` file in the root of the operating folder. This stores environment diff --git a/TitanBot.py b/TitanBot.py index 2213a5a..e941fb7 100644 --- a/TitanBot.py +++ b/TitanBot.py @@ -7,6 +7,7 @@ from Framework.CommandGroups.AccessControl import AccessControl from Framework.CommandGroups.CurseForge import CurseForge from Framework.CommandGroups.CustomCommands import CustomCommands +from Framework.CommandGroups.Debugging import Debugging from Framework.CommandGroups.Fun import Fun from Framework.CommandGroups.Genius import Genius from Framework.CommandGroups.Help import Help @@ -25,7 +26,7 @@ if __name__ == "__main__": database_version = 7 - ConfigurationValues.VERSION = "v2.8.0-indev" + ConfigurationValues.VERSION = "v2.8.0" ConfigurationValues.COMMIT = GeneralUtilities.get_git_revision_short_hash() intents = discord.Intents.all() @@ -55,12 +56,13 @@ bot.add_cog(AccessControl(management_portal_handler)) bot.add_cog(custom_commands_module) bot.add_cog(CurseForge(management_portal_handler)) + bot.add_cog(Debugging(management_portal_handler)) @bot.event async def on_ready(): logger.log_info("TitanBot has connected to Discord") - await bot.change_presence(activity=discord.Game(name="Initializing..."), status=discord.Status.dnd) + await bot.change_presence(activity=discord.CustomActivity(name="Initializing..."), status=discord.Status.dnd) # Perform post-initialization for the management portal await management_portal_handler.post_init() diff --git a/requirements.txt b/requirements.txt index 47243d0..4ca07bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,5 @@ python-dotenv~=1.0.0 lyricsgenius~=3.0.1 py-cord-dev~=2.5.0rc5 nest_asyncio~=1.5.6 -vt-py~=0.17.5 \ No newline at end of file +vt-py~=0.17.5 +semver~=3.0.1 \ No newline at end of file