2021-07-15 09:03:44 +01:00
import os # OS Locations
import yaml # YAML parser for Bot config files
2021-07-15 22:54:09 +01:00
import asyncio # Discord Py Dependency
2021-07-15 09:03:44 +01:00
import discord # Main Lib
from discord . ext import commands # Commands module
from discord_slash import SlashCommand , SlashContext , cog_ext , utils # Slash Command Library
2021-07-17 13:56:04 +01:00
from discord_slash . utils . manage_commands import create_choice , create_option , create_permission # Slash Command features
from discord_slash . model import SlashCommandPermissionType
2021-07-18 23:16:58 +01:00
import re
2021-07-17 13:56:04 +01:00
2021-07-19 15:30:04 +01:00
from bot import configFile , yaml_load , yaml_dump , loadCog , unloadCog , reloadCog , cogsDir , slash , lookupFile
2021-07-15 09:03:44 +01:00
##### Configuration Cog
2021-07-18 23:16:58 +01:00
class Configuration ( commands . Cog , name = ' Configuration Commands ' ) :
2021-07-15 09:03:44 +01:00
def __init__ ( self , client ) :
self . client = client
2021-07-17 13:56:04 +01:00
guild_ids = [ int ( guildKey ) for guildKey in yaml_load ( configFile ) ]
permissions = { }
conf = yaml_load ( configFile )
2021-07-21 11:49:29 +01:00
for gStr in conf :
permissions [ int ( gStr ) ] = [ ]
permissions [ int ( gStr ) ] . append ( create_permission ( id = conf [ gStr ] [ ' owner ' ] , id_type = SlashCommandPermissionType . USER , permission = True ) )
2021-07-23 00:44:21 +01:00
for admin in conf [ gStr ] [ ' roles ' ] [ ' admin ' ] : permissions [ int ( gStr ) ] . append ( create_permission ( id = admin , id_type = SlashCommandPermissionType . ROLE , permission = True ) )
2021-07-26 21:29:20 +01:00
2021-07-18 01:28:06 +01:00
@cog_ext.cog_subcommand (
base = ' config ' ,
# subcommand_group='role',
name = ' roles ' ,
description = ' Designates the various key roles referenced by the Bot. ' ,
base_description = ' Commands for configuring the various parameters of the Guild. ' ,
base_default_permission = False ,
base_permissions = permissions ,
# subcommand_group_description='Designates the various key command roles for the guild.',
2021-07-17 13:56:04 +01:00
guild_ids = guild_ids ,
options = [
create_option (
2021-07-18 01:28:06 +01:00
name = ' key ' ,
description = ' The name of the role parameter being assigned. ' ,
2021-07-17 13:56:04 +01:00
option_type = 3 ,
required = True ,
choices = [
create_choice (
2021-07-18 01:28:06 +01:00
name = ' `Bot` role ' ,
value = ' bot '
2021-07-17 13:56:04 +01:00
) ,
create_choice (
2021-07-18 01:28:06 +01:00
name = ' `Committee` role ' ,
value = ' committee '
2021-07-17 13:56:04 +01:00
) ,
create_choice (
2021-07-18 01:28:06 +01:00
name = ' `Newcomer` role ' ,
value = ' newcomer '
) ,
create_choice (
name = ' `Returning Player` role ' ,
value = ' returning_player '
) ,
create_choice (
name = ' `Student` role ' ,
value = ' student '
2021-08-04 13:15:18 +01:00
) ,
create_choice (
name = ' `Bot Maintainer` role ' ,
value = ' maintainer '
2021-07-17 13:56:04 +01:00
)
2021-07-18 01:28:06 +01:00
]
) ,
2021-07-19 15:30:04 +01:00
create_option (
name = ' role_exists ' ,
description = ' Whether or not a role for this parameter already exists ' ,
option_type = 5 ,
required = True
) ,
2021-07-18 00:43:44 +01:00
create_option (
name = ' role ' ,
2021-07-18 01:28:06 +01:00
description = ' The role assigned to the parameter. ' ,
2021-07-18 00:43:44 +01:00
option_type = 8 ,
2021-07-19 15:30:04 +01:00
required = False
2021-07-18 00:43:44 +01:00
)
]
)
2021-07-19 15:30:04 +01:00
async def _config_roles ( self , ctx : SlashContext , key : str , role_exists : bool , role : discord . Role = None ) :
if role_exists and role is None :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```If the role you want to assign to ` { key } ` already exists, you must assign it. Please select a role to assign.``` ' , hidden = True )
2021-07-19 15:30:04 +01:00
return
if not role_exists and role is not None :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```You have specified a role to assign to ` { key } ` but have also specified it does not exist. If a role does not exist, do not assign a role.``` ' , hidden = True )
2021-07-19 15:30:04 +01:00
return
r = role
if not role_exists :
r = await ctx . guild . create_role (
name = key ,
permissions = discord . Permissions ( administrator = True ) if key == ' committee ' else discord . Permissions ( ) . none ( ) ,
reason = f ' `/config roles` command issued by { ctx . author . display_name } ' ,
colour = discord . Colour . orange ( ) if key == ' bot ' else discord . Colour . blue ( ) if key == ' committee ' else discord . Colour . default ( ) ,
hoist = True if key == ' committee ' else None ,
)
else :
await r . edit (
permissions = discord . Permissions ( administrator = True ) if key == ' committee ' else discord . Permissions ( ) . none ( ) ,
reason = f ' `/config roles` command issued by { ctx . author . display_name } ' ,
colour = discord . Colour . orange ( ) if key == ' bot ' else discord . Colour . blue ( ) if key == ' committee ' else discord . Colour . default ( ) ,
2021-07-26 18:54:28 +01:00
hoist = True if key == ' committee ' or key == ' bot ' else None ,
2021-07-19 15:30:04 +01:00
)
2021-07-18 00:43:44 +01:00
conf = yaml_load ( configFile )
2021-07-21 11:49:29 +01:00
guildStr = str ( ctx . guild . id )
if ' roles ' not in conf [ guildStr ] :
conf [ guildStr ] [ ' roles ' ] = { }
conf [ guildStr ] [ ' roles ' ] [ key ] = int ( r . id )
2021-07-18 00:43:44 +01:00
yaml_dump ( conf , configFile )
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```The ` { key } ` role for the guild ` { ctx . guild . name } ` has been set to ` { r . name } `.``` \n { r . mention } ' , hidden = True )
2021-07-21 11:49:29 +01:00
if any ( [ ' bot ' in yaml_load ( configFile ) [ x ] [ ' roles ' ] for x in yaml_load ( configFile ) ] ) :
if any ( [ yaml_load ( configFile ) [ x ] [ ' timeslots ' ] for x in yaml_load ( configFile ) ] ) :
flag = False
2021-07-23 00:44:21 +01:00
if self . client . get_cog ( ' Game Create ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/game_create.py ' )
2021-07-21 11:49:29 +01:00
flag = True
if any ( [ x for x in yaml_load ( lookupFile ) . values ( ) ] ) :
2021-07-19 15:30:04 +01:00
if self . client . get_cog ( ' Game Management ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/game_management.py ' )
2021-07-21 11:49:29 +01:00
flag = True
2021-07-23 00:44:21 +01:00
if self . client . get_cog ( ' Player Commands ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/player_commands.py ' )
flag = True
2021-08-04 14:12:14 +01:00
if self . client . get_cog ( ' T-Card Command ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/tcard.py ' )
flag = True
2021-07-24 13:15:01 +01:00
if self . client . get_cog ( ' Pitch Command ' ) is None :
2021-07-23 00:44:21 +01:00
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/pitch.py ' )
flag = True
2021-07-21 11:49:29 +01:00
if flag : await self . client . slash . sync_all_commands ( )
2021-07-18 00:43:44 +01:00
@cog_ext.cog_subcommand (
base = ' config ' ,
2021-07-18 01:28:06 +01:00
# subcommand_group='channel',
name = ' channels ' ,
description = ' Designate the various key channels for the Bot to interact with. ' ,
2021-07-17 13:56:04 +01:00
# base_description='Commands for configuring the various parameters of the Guild',
2021-07-26 21:29:20 +01:00
base_default_permission = False ,
2021-07-17 13:56:04 +01:00
# base_permissions=permissions,
# subcommand_group_description='Designates the various key Bot channels for the guild.',
guild_ids = guild_ids ,
options = [
create_option (
2021-07-18 01:28:06 +01:00
name = ' key ' ,
description = ' The name of the channel parameter being assigned. ' ,
option_type = 3 ,
required = True ,
choices = [
create_choice (
name = ' Help Channel ' ,
value = ' help '
) ,
create_choice (
name = ' Mod Channel ' ,
value = ' mod '
) ,
create_choice (
2021-07-19 15:30:04 +01:00
name = ' Signup Channel ' ,
2021-07-18 01:28:06 +01:00
value = ' signup '
)
]
) ,
2021-07-19 15:30:04 +01:00
create_option (
name = ' channel_exists ' ,
description = ' Does the channel for this parameter already exist? ' ,
option_type = 5 ,
required = True
) ,
2021-07-17 13:56:04 +01:00
create_option (
name = ' channel ' ,
2021-07-18 01:28:06 +01:00
description = ' The channel assigned to the parameter. ' ,
2021-07-17 13:56:04 +01:00
option_type = 7 ,
2021-07-19 15:30:04 +01:00
required = False
2021-07-17 13:56:04 +01:00
)
]
)
2021-07-19 15:30:04 +01:00
async def _config_channels ( self , ctx : SlashContext , key : str , channel_exists : bool , channel : discord . TextChannel = None ) :
if channel_exists and channel is None :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```If the channel you want to assign to ` { key } ` already exists, you must assign it. Please select a role to assign.``` ' , hidden = True )
2021-07-19 15:30:04 +01:00
return
if not channel_exists and channel is not None :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```You have specified a channel to assign to ` { key } ` but have also specified it does not exist. If a channel does not exist, do not assign a channel.``` ' , hidden = True )
2021-07-19 15:30:04 +01:00
return
c = channel
if not channel_exists :
c = await ctx . guild . create_text_channel (
name = key ,
overwrites = { } ,
reason = f ' `/config channels` command issued by { ctx . author . display_name } '
)
else :
await c . edit (
name = key ,
overwrites = { } ,
reason = f ' `/config channels` command issued by { ctx . author . display_name } '
)
2021-07-17 13:56:04 +01:00
conf = yaml_load ( configFile )
2021-07-21 11:49:29 +01:00
guildStr = str ( ctx . guild . id )
if ' channels ' not in conf [ guildStr ] :
conf [ guildStr ] [ ' channels ' ] = { }
conf [ guildStr ] [ ' channels ' ] [ key ] = int ( c . id )
2021-07-17 13:56:04 +01:00
yaml_dump ( conf , configFile )
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```The ` { key } ` channel for the guild ` { ctx . guild . name } ` has been set to ` { c . name } `. \n \n All permission overrides for the channel have been reset. Remember to set the appropriate permissions for your guild.``` \n { c . mention } ' , hidden = True )
2021-07-17 13:56:04 +01:00
2021-07-18 00:43:44 +01:00
@cog_ext.cog_subcommand (
base = ' config ' ,
2021-07-18 01:28:06 +01:00
# subcommand_group='notifications',
name = ' notifications ' ,
description = ' Configure monitoring and notifications to Committee for member query channels. ' ,
2021-07-18 00:43:44 +01:00
# base_description='Commands for configuring the various parameters of the Guild',
2021-07-26 21:29:20 +01:00
base_default_permission = False ,
2021-07-18 00:43:44 +01:00
# base_permissions=permissions,
2021-07-18 01:28:06 +01:00
# subcommand_group_description='Configures whether the bot monitors and responds to posts in key channels.',
2021-07-18 00:43:44 +01:00
guild_ids = guild_ids ,
options = [
create_option (
2021-07-18 01:28:06 +01:00
name = ' channel ' ,
description = ' Select which channel to change notifications for. ' ,
option_type = 3 ,
required = True ,
choices = [
create_choice (
name = ' Help Channel ' ,
value = ' help '
) ,
create_choice (
name = ' Signup Channel ' ,
value = ' signup '
)
]
) ,
2021-07-18 00:43:44 +01:00
create_option (
name = ' notifications ' ,
2021-07-18 01:28:06 +01:00
description = ' Whether or not the bot monitors the channel for posts. ' ,
2021-07-18 00:43:44 +01:00
option_type = 5 ,
required = True
)
]
)
2021-07-18 01:28:06 +01:00
async def _config_notifications ( self , ctx : SlashContext , channel : str , notifications : bool ) :
2021-07-18 00:43:44 +01:00
conf = yaml_load ( configFile )
2021-07-21 11:49:29 +01:00
guildStr = str ( ctx . guild . id )
if ' notifications ' not in conf [ guildStr ] :
conf [ guildStr ] [ ' notifications ' ] = { }
conf [ guildStr ] [ ' notifications ' ] [ channel ] = notifications
2021-07-18 00:43:44 +01:00
yaml_dump ( conf , configFile )
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```Notifications for posts in the ` { channel } ` channel for the guild ` { ctx . guild . name } ` have been set to ` { notifications } `.``` ' , hidden = True )
2021-07-15 09:03:44 +01:00
2021-07-18 23:16:58 +01:00
@cog_ext.cog_subcommand (
base = ' config ' ,
subcommand_group = ' timeslots ' ,
name = ' add ' ,
description = ' Add a timeslot at which the Guild will host games. ' ,
# base_description='Commands for configuring the various parameters of the Guild',
2021-07-26 21:29:20 +01:00
base_default_permission = False ,
2021-07-18 23:16:58 +01:00
# base_permissions=permissions,
subcommand_group_description = ' Manages timeslots available for games on the guild. ' ,
guild_ids = guild_ids ,
options = [
create_option (
name = ' key ' ,
description = ' Alphanumeric time code 10 chars max. ' ,
option_type = 3 ,
required = True ,
) ,
create_option (
name = ' n ame ' ,
description = ' A longer, descriptive name of when the timeslot is ' ,
option_type = 3 ,
required = True
)
]
)
async def _config_timeslots_add ( self , ctx : SlashContext , key : str , name : str ) :
sanitisedKey = re . sub ( r " \ W+ " , ' ' , key [ : 9 ] . lower ( ) )
if not key . isalnum ( ) :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```Key value { key } is not a valid alphanumeric time code. Sanitising to ` { sanitisedKey } `.``` ' , hidden = True )
2021-07-18 23:16:58 +01:00
conf = yaml_load ( configFile )
2021-07-21 11:49:29 +01:00
guildStr = str ( ctx . guild . id )
if ' timeslots ' not in conf [ guildStr ] :
conf [ guildStr ] [ ' timeslots ' ] = { }
if sanitisedKey in conf [ guildStr ] [ ' timeslots ' ] :
await ctx . send ( f ' ```Key value { sanitisedKey } has already been defined for guild ` { ctx . guild . name } ` for ` { conf [ guildStr ] [ " timeslots " ] [ sanitisedKey ] } `. Please use the `remove` or `modify` sub-commands to amend it.``` ' , hidden = True )
2021-07-18 23:16:58 +01:00
return
2021-07-21 11:49:29 +01:00
conf [ guildStr ] [ ' timeslots ' ] [ sanitisedKey ] = name
2021-07-18 23:16:58 +01:00
yaml_dump ( conf , configFile )
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```Timeslot ` { name } ` with the key ` { sanitisedKey } ` has been added for the guild ` { ctx . guild . name } `.``` ' , hidden = True )
2021-07-21 11:49:29 +01:00
if any ( [ yaml_load ( configFile ) [ x ] [ ' timeslots ' ] for x in yaml_load ( configFile ) ] ) :
flag = False
2021-07-18 23:16:58 +01:00
if self . client . get_cog ( ' Manipulate Timeslots ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/manipulate_timeslots.py ' )
2021-07-21 11:49:29 +01:00
flag = True
if any ( [ ' bot ' in yaml_load ( configFile ) [ x ] [ ' roles ' ] for x in yaml_load ( configFile ) ] ) :
2021-07-23 00:44:21 +01:00
if self . client . get_cog ( ' Game Create ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/game_create.py ' )
2021-07-21 11:49:29 +01:00
Flag = True
2021-07-19 15:30:04 +01:00
if yaml_load ( lookupFile ) :
2021-07-21 11:49:29 +01:00
if any ( [ x for x in yaml_load ( lookupFile ) . values ( ) ] ) :
2021-07-19 15:30:04 +01:00
if self . client . get_cog ( ' Game Management ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/game_management.py ' )
2021-07-21 11:49:29 +01:00
Flag = True
2021-07-23 00:44:21 +01:00
if self . client . get_cog ( ' Player Commands ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/player_commands.py ' )
Flag = True
2021-08-04 14:12:14 +01:00
if self . client . get_cog ( ' T-Card Command ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/tcard.py ' )
Flag = True
2021-07-24 13:15:01 +01:00
if self . client . get_cog ( ' Pitch Command ' ) is None :
2021-07-23 00:44:21 +01:00
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/pitch.py ' )
Flag = True
2021-07-21 11:49:29 +01:00
if flag : await self . client . slash . sync_all_commands ( )
2021-07-18 23:16:58 +01:00
@cog_ext.cog_subcommand (
base = ' config ' ,
subcommand_group = ' membership ' ,
name = ' add ' ,
description = ' Add a membership type for the Guild. ' ,
# base_description='Commands for configuring the various parameters of the Guild',
2021-07-26 21:29:20 +01:00
base_default_permission = False ,
2021-07-18 23:16:58 +01:00
# base_permissions=permissions,
subcommand_group_description = ' Manages the different categories of membership available to the Guild. ' ,
guild_ids = guild_ids ,
options = [
create_option (
name = ' name ' ,
description = ' Name of membership type. ' ,
option_type = 3 ,
required = True ,
) ,
create_option (
name = ' role_exists ' ,
description = ' Does the role for this member type already exist? ' ,
option_type = 5 ,
required = True
) ,
create_option (
name = ' role ' ,
description = ' Assign the role if it already exists. ' ,
option_type = 8 ,
required = False
)
]
)
async def _config_membership_add ( self , ctx : SlashContext , name : str , role_exists : bool , role : discord . Role = None ) :
if role_exists and role is None :
2021-07-19 15:30:04 +01:00
await ctx . send ( f ' ```If the role for membership type ` { name } ` already exists, you must assign it. If it does not exist, the Bot will create one.``` ' )
2021-07-18 23:16:58 +01:00
return
if not role_exists and role is not None :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```You have specified a role for ` { name } ` does not already exist but have also specified a role to assign. Please either assign a role if it exists, or leave it blank if does not.``` ' , hidden = True )
2021-07-18 23:16:58 +01:00
return
conf = yaml_load ( configFile )
2021-07-21 11:49:29 +01:00
guildStr = str ( ctx . guild . id )
if ' membership ' not in conf [ guildStr ] :
conf [ guildStr ] [ ' membership ' ] = [ ]
2021-07-18 23:16:58 +01:00
if role is not None :
2021-07-21 11:49:29 +01:00
if role . id in conf [ guildStr ] [ ' membership ' ] :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```The role { name } has already been assigned to a membership type for guild ` { ctx . guild . name } `. Please use the `remove` sub-command to delete it or assign a different role.``` ' , hidden = True )
2021-07-18 23:16:58 +01:00
return
2021-07-21 23:05:13 +01:00
if any ( [ ctx . guild . get_role ( m ) . name == name for m in conf [ str ( ctx . guild . id ) ] [ ' membership ' ] ] ) :
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```The membership type { name } has already been assigned a role for guild ` { ctx . guild . name } `. Please use the `remove` sub-command to delete the role or assign a different membership type.``` ' , hidden = True )
2021-07-18 23:16:58 +01:00
return
if not role_exists :
r = await ctx . guild . create_role (
name = name ,
permissions = discord . Permissions ( read_messages = True , use_slash_commands = True ) ,
2021-07-19 15:30:04 +01:00
mentionable = False ,
reason = f ' `/config membership add` command issued by { ctx . author . display_name } '
2021-07-18 23:16:58 +01:00
)
if role is not None :
await role . edit (
name = name ,
permissions = discord . Permissions ( read_messages = True , use_slash_commands = True ) ,
mentionable = False ,
reason = f ' `/config membership add` command issued by { ctx . author . display_name } '
)
2021-07-21 11:49:29 +01:00
conf [ guildStr ] [ ' membership ' ] . append ( role . id ) if role is not None else conf [ guildStr ] [ ' membership ' ] . append ( r . id )
2021-07-18 23:16:58 +01:00
yaml_dump ( conf , configFile )
2021-07-21 01:41:08 +01:00
await ctx . send ( f ' ```Membership type ` { role . name if role is not None else r . name } ` has been registered for the guild ` { ctx . guild . name } `.``` ' , hidden = True )
2021-07-21 11:49:29 +01:00
if any ( [ yaml_load ( configFile ) [ x ] [ ' membership ' ] for x in yaml_load ( configFile ) ] ) :
2021-07-18 23:16:58 +01:00
if self . client . get_cog ( ' Edit Membership ' ) is None :
loadCog ( f ' ./ { cogsDir } /slashcommands/secondary/edit_membership.py ' )
2021-07-21 11:49:29 +01:00
await self . client . slash . sync_all_commands ( )
2021-07-18 23:16:58 +01:00
2021-07-23 15:55:27 +01:00
@cog_ext.cog_subcommand (
base = ' config ' ,
# subcommand_group='notifications',
name = ' restrict ' ,
description = ' Toggle membership estriction for the guild. ' ,
# base_description='Commands for configuring the various parameters of the Guild',
2021-07-26 21:29:20 +01:00
base_default_permission = False ,
2021-07-23 15:55:27 +01:00
# base_permissions=permissions,
# subcommand_group_description='Configures whether the bot monitors and responds to posts in key channels.',
2021-07-19 15:30:04 +01:00
guild_ids = guild_ids ,
options = [
create_option (
2021-07-23 15:55:27 +01:00
name = ' value ' ,
description = ' Enable membership restrictions for the guild? ' ,
option_type = 5 ,
2021-07-19 15:30:04 +01:00
required = True
)
]
)
2021-07-23 15:55:27 +01:00
async def _restrict (
2021-07-19 15:30:04 +01:00
self ,
ctx : SlashContext ,
2021-07-23 15:55:27 +01:00
value : bool
2021-07-19 15:30:04 +01:00
) :
2021-07-23 15:55:27 +01:00
conf = yaml_load ( configFile )
conf [ str ( ctx . guild . id ) ] [ ' restrict ' ] = value
yaml_dump ( conf , configFile )
await ctx . send ( f ' ```Membership restrictions for the guild ` { ctx . guild . name } ` have been set to ` { value } `.``` ' , hidden = True )
2021-07-19 15:30:04 +01:00
2021-07-15 09:03:44 +01:00
def setup ( client ) :
client . add_cog ( Configuration ( client ) )