2021-07-18 23:16:58 +01:00
import os # OS Locations
import yaml # YAML parser for Bot config files
import asyncio # Discord Py Dependency
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 , create_permission # Slash Command features
from discord_slash . model import SlashCommandPermissionType
from discord_slash . client import SlashCommand
2021-07-20 21:43:22 +01:00
from discord_slash . utils . manage_components import create_select , create_select_option , create_actionrow , wait_for_component
# from discord_components import *
2021-07-18 23:16:58 +01:00
2021-07-20 21:43:22 +01:00
from bot import configFile , yaml_load , yaml_dump , reloadCog , cogsDir , unloadCog , dataFile
2021-07-18 23:16:58 +01:00
#### Separate cog to remove and modify timeslots that is reloaded if timeslots are added or removed
class ManipulateTimeslots ( commands . Cog , name = ' Manipulate Timeslots ' ) :
def __init__ ( self , client ) :
self . client = client
#### Only emable for guilds with timeslots
#### N.B.: if there are no guilds with any timeslots, then this will throw an exception.
#### The solution I have implemented is that this will be classed as a 'secondary' cog: it will not be loaded by default, and will only be loaded if at least one guild has a timeslot configured.
#### If the deletion of timeslots removes timeslots from all guilds, it will unload the cog and delete the commands until a new timeslot is defined.
2021-07-21 11:49:29 +01:00
guild_ids = [ int ( guildKey ) for guildKey in yaml_load ( configFile ) if yaml_load ( configFile ) [ guildKey ] [ ' timeslots ' ] ]
2021-07-18 23:16:58 +01:00
conf = yaml_load ( configFile )
permissions = { }
for guildID in guild_ids :
permissions [ guildID ] = [ ]
permissions [ guildID ] . append ( create_permission ( id = conf [ str ( guildID ) ] [ ' owner ' ] , id_type = SlashCommandPermissionType . USER , permission = True ) )
for admin in conf [ str ( guildID ) ] [ ' roles ' ] [ ' admin ' ] :
permissions [ guildID ] . append ( create_permission ( id = admin , id_type = SlashCommandPermissionType . ROLE , permission = True ) )
@cog_ext.cog_subcommand (
base = ' config ' ,
subcommand_group = ' timeslots ' ,
name = ' remove ' ,
description = ' Remove a configured game timeslot. ' ,
# base_description='Commands for configuring the various parameters of the Guild',
# base_default_permission=False,
# base_permissions=permissions,
# subcommand_group_description='Adds a time slot available to the channel for games.',
guild_ids = guild_ids ,
2021-07-20 21:43:22 +01:00
# options=[
# create_option(
# name='timeslot',
# description='The timeslot you wish to delete.',
# option_type=3,
# required=True
# )
# ]
2021-07-18 23:16:58 +01:00
)
2021-07-20 21:43:22 +01:00
async def _config_timeslots_remove ( self , ctx : SlashContext , ) : # timeslot:str):
2021-07-18 23:16:58 +01:00
conf = yaml_load ( configFile )
2021-07-20 21:43:22 +01:00
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 ] :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```Timeslot { conf [ guildStr ] [ " timeslots " ] [ timeslot ] } with the key ` { timeslot } ` has been deleted for the guild ` { ctx . guild . name } `.``` ' , hidden = True )
2021-07-20 21:43:22 +01:00
conf [ guildStr ] [ ' timeslots ' ] . pop ( timeslot , None )
2021-07-18 23:16:58 +01:00
yaml_dump ( conf , configFile )
2021-07-21 11:49:29 +01:00
if not any ( [ x [ ' timeslots ' ] for x in yaml_load ( configFile ) . values ( ) ] ) :
2021-07-18 23:16:58 +01:00
unloadCog ( f ' ./ { cogsDir } /slashcommands/secondary/manipulate_timeslots.py ' )
2021-07-19 15:30:04 +01:00
if self . client . get_cog ( ' Game Management ' ) is not None :
unloadCog ( f ' ./ { cogsDir } /slashcommands/secondary/game_management.py ' )
if self . client . get_cog ( ' Game Setup ' ) is not None :
unloadCog ( f ' ./ { cogsDir } /slashcommands/secondary/game_setup.py ' )
2021-07-18 23:16:58 +01:00
await self . client . slash . sync_all_commands ( )
else :
2021-07-21 01:41:08 +01:00
await ctx . send ( ' ```Error: You cannot delete a timeslot that has existing game entries. Please delete all games first.``` ' , hidden = True )
2021-07-18 23:16:58 +01:00
@cog_ext.cog_subcommand (
base = ' config ' ,
subcommand_group = ' timeslots ' ,
name = ' modify ' ,
description = ' Modify the value of a configured gametime slot. ' ,
# base_description='Commands for configuring the various parameters of the Guild',
# base_default_permission=False,
# base_permissions=permissions,
# subcommand_group_description='Adds a time slot available to the channel for games.',
guild_ids = guild_ids ,
options = [
create_option (
name = ' key ' ,
description = ' Key of timeslot being modified ' ,
option_type = 3 ,
required = True ,
) ,
create_option (
name = ' name ' ,
description = ' New value for timeslot name ' ,
option_type = 3 ,
required = True
)
]
)
async def _config_timeslots_modify ( self , ctx : SlashContext , key : str , name : str ) :
conf = yaml_load ( configFile )
2021-07-20 21:43:22 +01:00
guildStr = str ( ctx . guild . id )
if ' timeslots ' not in conf [ guildStr ] :
conf [ guildStr ] [ ' timeslots ' ] = { }
if key in conf [ guildStr ] [ ' timeslots ' ] :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```Timeslot { conf [ guildStr ] [ " timeslots " ] [ key ] } with the key ` { key } ` has been renamed to { name } for the guild ` { ctx . guild . name } `.``` ' , hidden = True )
2021-07-20 21:43:22 +01:00
conf [ guildStr ] [ ' timeslots ' ] [ key ] = name
2021-07-18 23:16:58 +01:00
yaml_dump ( conf , configFile )
2021-07-21 11:49:29 +01:00
elif conf [ guildStr ] [ ' timeslots ' ] :
2021-07-18 23:16:58 +01:00
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) '
2021-07-20 21:43:22 +01:00
for c in conf [ guildStr ] [ ' timeslots ' ] :
output = ' ' . join ( [ output , f ' \n { c } : { conf [ guildStr ] [ " timeslots " ] [ c ] } ' ] )
2021-07-21 01:41:08 +01:00
await ctx . send ( ' ' . join ( [ output , ' ``` ' ] ) , hidden = True )
2021-07-18 23:16:58 +01:00
else :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```No timeslots have been defined for the guild ` { ctx . guild . name } `.``` ' , hidden = True )
2021-07-18 23:16:58 +01:00
@cog_ext.cog_subcommand (
base = ' config ' ,
subcommand_group = ' timeslots ' ,
name = ' list ' ,
description = ' List the existing game timeslots on the server. ' ,
# base_description='Commands for configuring the various parameters of the Guild',
# base_default_permission=False,
# base_permissions=permissions,
# subcommand_group_description='Adds a time slot available to the channel for games.',
guild_ids = guild_ids ,
)
async def _config_timeslots_list ( self , ctx : SlashContext ) :
conf = yaml_load ( configFile )
2021-07-20 21:43:22 +01:00
guildStr = str ( ctx . guild . id )
if ' timeslots ' not in conf [ guildStr ] :
conf [ guildStr ] [ ' timeslots ' ] = { }
2021-07-21 11:49:29 +01:00
if conf [ guildStr ] [ ' timeslots ' ] :
2021-07-18 23:16:58 +01:00
output = f ' ```The following timeslots have been configured for the guild { ctx . guild . name } : \n (key): (timeslot name) '
2021-07-20 21:43:22 +01:00
for c in conf [ guildStr ] [ ' timeslots ' ] :
output = ' ' . join ( [ output , f ' \n { c } : { conf [ guildStr ] [ " timeslots " ] [ c ] } ' ] )
2021-07-18 23:16:58 +01:00
await ctx . send ( ' ' . join ( [ output , ' ``` ' ] ) )
else :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```No timeslots have been defined for the guild ` { ctx . guild . name } `.``` ' , hidden = True )
2021-07-18 23:16:58 +01:00
def setup ( client ) :
client . add_cog ( ManipulateTimeslots ( client ) )