diff --git a/TODO.md b/TODO.md index 641203c..8d10a63 100644 --- a/TODO.md +++ b/TODO.md @@ -62,7 +62,8 @@ - [x] Set up timeslots - [ ] Delete timeslots > - [x] Base command -> - [ ] Delete all games with the timeslot +> - [ ] ~~Delete all games with the timeslot~~ +Do the opposite: block deleting timeslots with existing games. - [x] List timeslots - [ ] Set up command permissions > - [ ] Slash Commands @@ -87,4 +88,5 @@ > - [ ] Finalise README.md > - [ ] CHANGELOG.md > - [ ] COMMANDS.md -> - [ ] resources.md \ No newline at end of file +> - [ ] resources.md +- [ ] Make sure to document **not using discord_components and staying with discord-py-slash-commands library alone**. \ No newline at end of file diff --git a/app/bot.py b/app/bot.py index bffaabc..096a353 100644 --- a/app/bot.py +++ b/app/bot.py @@ -7,7 +7,7 @@ import discord # Main Lib from discord.ext import commands # Commands module from discord_slash import SlashCommand, SlashContext, cog_ext, utils # Slash Command Library from discord_slash.utils.manage_commands import create_choice, create_option # Slash Command features -import discord_components # Additional Discord functions: buttons, menus, etc +# import discord_components # Additional Discord functions: buttons, menus, etc from deepdiff import DeepDiff import logging diff --git a/app/cogs/events/on_ready.py b/app/cogs/events/on_ready.py index 09adf8a..edaec96 100644 --- a/app/cogs/events/on_ready.py +++ b/app/cogs/events/on_ready.py @@ -5,6 +5,7 @@ import discord # Main Lib from discord.ext import commands # Commands module from discord_slash import SlashCommand, SlashContext, cog_ext, utils # Slash Command Library from discord_slash.utils.manage_commands import create_choice, create_option # Slash Command features +# import discord_components import logging # logger and handler from bot import checkConfig, clearConfig, configFile, parseConfigCheck, setConfig, yaml_dump, yaml_load, loadCogs, unloadCogs @@ -17,6 +18,8 @@ class on_ready(commands.Cog, name='On Ready Events'): @commands.Cog.listener() async def on_ready(self): + # discord_components.DiscordComponents(self.client) + #### Create any missing config entries for guilds for guild in self.client.guilds: setConfig(guild) diff --git a/app/cogs/slashcommands/secondary/manipulate_timeslots.py b/app/cogs/slashcommands/secondary/manipulate_timeslots.py index 03c3348..6dcc5cc 100644 --- a/app/cogs/slashcommands/secondary/manipulate_timeslots.py +++ b/app/cogs/slashcommands/secondary/manipulate_timeslots.py @@ -7,8 +7,10 @@ from discord_slash import SlashCommand, SlashContext, cog_ext, utils # Slash C from discord_slash.utils.manage_commands import create_choice, create_option, create_permission # Slash Command features from discord_slash.model import SlashCommandPermissionType from discord_slash.client import SlashCommand +from discord_slash.utils.manage_components import create_select, create_select_option, create_actionrow, wait_for_component +# from discord_components import * -from bot import configFile, yaml_load, yaml_dump, reloadCog, cogsDir, unloadCog +from bot import configFile, yaml_load, yaml_dump, reloadCog, cogsDir, unloadCog, dataFile #### Separate cog to remove and modify timeslots that is reloaded if timeslots are added or removed @@ -39,22 +41,53 @@ class ManipulateTimeslots(commands.Cog, name='Manipulate Timeslots'): # base_permissions=permissions, # subcommand_group_description='Adds a time slot available to the channel for games.', guild_ids=guild_ids, - options=[ - create_option( - name='timeslot', - description='The timeslot you wish to delete.', - option_type=3, - required=True - ) - ] + # options=[ + # create_option( + # name='timeslot', + # description='The timeslot you wish to delete.', + # option_type=3, + # required=True + # ) + # ] ) - async def _config_timeslots_remove(self, ctx:SlashContext, timeslot:str): + async def _config_timeslots_remove(self, ctx:SlashContext,):# timeslot:str): conf = yaml_load(configFile) - if 'timeslots' not in conf[str(ctx.guild.id)]: - conf[str(ctx.guild.id)]['timeslots'] = {} - if timeslot in conf[str(ctx.guild.id)]['timeslots']: - await ctx.send(f'```Timeslot {conf[str(ctx.guild.id)]["timeslots"][timeslot]} with the key `{timeslot}` has been deleted for the guild `{ctx.guild.name}`.```') - conf[str(ctx.guild.id)]['timeslots'].pop(timeslot, None) + data = yaml_load(dataFile) + guildStr = str(ctx.guild.id) + if 'timeslots' not in conf[guildStr]: + conf[guildStr]['timeslots'] = {} + tsDict = conf[guildStr]['timeslots'].copy() + optionsList = [create_select_option(label=tsDict[x], value=x, description=x) for x in tsDict] + try: + m = await ctx.send( + content='```Select which time slot you would like to delete.```', + components=[ + create_actionrow( + create_select( + placeholder='Time Slot', + options= optionsList, + min_values=1, + max_values=1 + ) + ) + ], + delete_after=5, + # hidden=True Can't have hidden responses for menus apparently. + ) + while True: + select_ctx = await wait_for_component(self.client,messages=m, timeout=5) + if select_ctx.author != ctx.author: + await select_ctx.send(f'```Invalid response: you are not the person who issued the command.```', hidden=True) + else: + break + await m.delete() + [timeslot] = select_ctx.selected_options + except asyncio.TimeoutError: + await ctx.send(f'```Error: Command timed out.```', hidden=True) + return + if timeslot not in data[guildStr] or not data[guildStr][timeslot]: + await ctx.send(f'```Timeslot {conf[guildStr]["timeslots"][timeslot]} with the key `{timeslot}` has been deleted for the guild `{ctx.guild.name}`.```') + conf[guildStr]['timeslots'].pop(timeslot, None) yaml_dump(conf, configFile) if not all([x['timeslots'] for x in yaml_load(configFile).values()]): unloadCog(f'./{cogsDir}/slashcommands/secondary/manipulate_timeslots.py') @@ -63,13 +96,8 @@ class ManipulateTimeslots(commands.Cog, name='Manipulate Timeslots'): if self.client.get_cog('Game Setup') is not None: unloadCog(f'./{cogsDir}/slashcommands/secondary/game_setup.py') await self.client.slash.sync_all_commands() - elif len(conf[str(ctx.guild.id)]['timeslots']) > 0: - output = f'```Timeslot `{timeslot}` was not found in the guild `{ctx.guild.name}`. Please enter a valid key.\n\n Available timeslots are:\n(key): (timeslot name)' - for c in conf[str(ctx.guild.id)]['timeslots']: - output = ''.join([output, f'\n {c}: {conf[str(ctx.guild.id)]["timeslots"][c]}']) - await ctx.send(''.join([output,'```'])) else: - await ctx.send(f'```No timeslots have been defined for the guild `{ctx.guild.name}`.```') + await ctx.send('```Error: You cannot delete a timeslot that has existing game entries. Please delete all games first.```') @cog_ext.cog_subcommand( base='config', @@ -98,16 +126,17 @@ class ManipulateTimeslots(commands.Cog, name='Manipulate Timeslots'): ) async def _config_timeslots_modify(self, ctx:SlashContext, key:str, name:str): conf = yaml_load(configFile) - if 'timeslots' not in conf[str(ctx.guild.id)]: - conf[str(ctx.guild.id)]['timeslots'] = {} - if key in conf[str(ctx.guild.id)]['timeslots']: - await ctx.send(f'```Timeslot {conf[str(ctx.guild.id)]["timeslots"][key]} with the key `{key}` has been renamed to {name} for the guild `{ctx.guild.name}`.```') - conf[str(ctx.guild.id)]['timeslots'][key] = name + guildStr = str(ctx.guild.id) + if 'timeslots' not in conf[guildStr]: + conf[guildStr]['timeslots'] = {} + if key in conf[guildStr]['timeslots']: + await ctx.send(f'```Timeslot {conf[guildStr]["timeslots"][key]} with the key `{key}` has been renamed to {name} for the guild `{ctx.guild.name}`.```') + conf[guildStr]['timeslots'][key] = name yaml_dump(conf, configFile) - elif len(conf[str(ctx.guild.id)]['timeslots']) > 0: + elif len(conf[guildStr]['timeslots']) > 0: output = f'```Timeslot `{key}` was not found in the guild `{ctx.guild.name}`. Please enter a valid key.\n\n Available timeslots are:\n(key): (timeslot name)' - for c in conf[str(ctx.guild.id)]['timeslots']: - output = ''.join([output, f'\n {c}: {conf[str(ctx.guild.id)]["timeslots"][c]}']) + for c in conf[guildStr]['timeslots']: + output = ''.join([output, f'\n {c}: {conf[guildStr]["timeslots"][c]}']) await ctx.send(''.join([output,'```'])) else: await ctx.send(f'```No timeslots have been defined for the guild `{ctx.guild.name}`.```') @@ -125,12 +154,13 @@ class ManipulateTimeslots(commands.Cog, name='Manipulate Timeslots'): ) async def _config_timeslots_list(self, ctx:SlashContext): conf = yaml_load(configFile) - if 'timeslots' not in conf[str(ctx.guild.id)]: - conf[str(ctx.guild.id)]['timeslots'] = {} - if len(conf[str(ctx.guild.id)]['timeslots']) > 0: + guildStr = str(ctx.guild.id) + if 'timeslots' not in conf[guildStr]: + conf[guildStr]['timeslots'] = {} + if len(conf[guildStr]['timeslots']) > 0: output = f'```The following timeslots have been configured for the guild {ctx.guild.name}:\n(key): (timeslot name)' - for c in conf[str(ctx.guild.id)]['timeslots']: - output = ''.join([output, f'\n {c}: {conf[str(ctx.guild.id)]["timeslots"][c]}']) + for c in conf[guildStr]['timeslots']: + output = ''.join([output, f'\n {c}: {conf[guildStr]["timeslots"][c]}']) await ctx.send(''.join([output,'```'])) else: await ctx.send(f'```No timeslots have been defined for the guild `{ctx.guild.name}`.```') diff --git a/app/data/config.yml b/app/data/config.yml index 4d49398..113d868 100644 --- a/app/data/config.yml +++ b/app/data/config.yml @@ -21,5 +21,4 @@ returning_player: 866645365524660224 student: 866645394699714570 timeslots: - sunaft: Sunday Afternoon 1 pm suneve: Sunday Evening