geas-bot/app/cogs/slashcommands/config.py

388 lines
15 KiB
Python
Raw Normal View History

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
2021-07-18 23:16:58 +01:00
import re
from bot import configFile, yaml_load, yaml_dump, loadCog, unloadCog, reloadCog, cogsDir, slash, lookupFile
##### Configuration Cog
2021-07-18 23:16:58 +01:00
class Configuration(commands.Cog, name='Configuration Commands'):
def __init__(self, client):
self.client = client
guild_ids=[int(guildKey) for guildKey in yaml_load(configFile)]
permissions = {}
conf = yaml_load(configFile)
for guildStr in conf:
permissions[int(guildStr)] = []
permissions[int(guildStr)].append(create_permission(id=conf[guildStr]['owner'],id_type=SlashCommandPermissionType.USER,permission=True))
for admin in conf[guildStr]['roles']['admin']:
permissions[int(guildStr)].append(create_permission(id=admin,id_type=SlashCommandPermissionType.ROLE,permission=True))
@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.',
guild_ids=guild_ids,
options=[
create_option(
name='key',
description='The name of the role parameter being assigned.',
option_type=3,
required=True,
choices=[
create_choice(
name='`Bot` role',
value='bot'
),
create_choice(
name='`Committee` role',
value='committee'
),
create_choice(
name='`Newcomer` role',
value='newcomer'
),
create_choice(
name='`Returning Player` role',
value='returning_player'
),
create_choice(
name='`Student` role',
value='student'
)
]
),
create_option(
name='role_exists',
description='Whether or not a role for this parameter already exists',
option_type=5,
required=True
),
create_option(
name='role',
description='The role assigned to the parameter.',
option_type=8,
required=False
)
]
)
async def _config_roles(self, ctx:SlashContext, key:str, role_exists:bool, role:discord.Role=None):
if role_exists and role is None:
await ctx.send(f'```If the role you want to assign to `{key}` already exists, you must assign it. If it does not exist, the Bot will create one.```')
return
if not role_exists and role is not None:
await ctx.send(f'```You have specified a role to assign to `{key}` but have also specified it does not exist. If a role already exists, indicate it. If it does not exist, do not assign a role.```')
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(),
hoist=True if key == 'committee' else None,
)
conf = yaml_load(configFile)
if 'roles' not in conf[str(ctx.guild.id)]:
conf[str(ctx.guild.id)]['roles'] = {}
conf[str(ctx.guild.id)]['roles'][key] = int(r.id)
yaml_dump(conf, configFile)
await ctx.send(f'```The `{key}` role for the guild `{ctx.guild.name}` has been set to `{r.name}`.```\n{r.mention}')
if all(['bot' in yaml_load(configFile)[x]['roles'] for x in yaml_load(configFile)]):
if all([len(yaml_load(configFile)[x]['timeslots']) > 0 for x in yaml_load(configFile)]):
if self.client.get_cog('Game Setup') is None:
loadCog(f'./{cogsDir}/slashcommands/secondary/game_setup.py')
if all([x for x in yaml_load(lookupFile).values()]):
if self.client.get_cog('Game Management') is None:
loadCog(f'./{cogsDir}/slashcommands/secondary/game_management.py')
await self.client.slash.sync_all_commands()
@cog_ext.cog_subcommand(
base='config',
# subcommand_group='channel',
name='channels',
description='Designate the various key channels for the Bot to interact with.',
# 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 Bot channels for the guild.',
guild_ids=guild_ids,
options=[
create_option(
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(
name='Signup Channel',
value='signup'
)
]
),
create_option(
name='channel_exists',
description='Does the channel for this parameter already exist?',
option_type=5,
required=True
),
create_option(
name='channel',
description='The channel assigned to the parameter.',
option_type=7,
required=False
)
]
)
async def _config_channels(self, ctx:SlashContext, key:str, channel_exists:bool, channel:discord.TextChannel=None):
if channel_exists and channel is None:
await ctx.send(f'```If the channel you want to assign to `{key}` already exists, you must assign it. If it does not exist, the Bot will create one.```')
return
if not channel_exists and channel is not None:
await ctx.send(f'```You have specified a channel to assign to `{key}` but have also specified it does not exist. If a channel already exists, indicate it. If it does not exist, do not assign a channel.```')
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}'
)
conf = yaml_load(configFile)
if 'channels' not in conf[str(ctx.guild.id)]:
conf[str(ctx.guild.id)]['channels'] = {}
conf[str(ctx.guild.id)]['channels'][key] = int(c.id)
yaml_dump(conf, configFile)
await ctx.send(f'```The `{key}` channel for the guild `{ctx.guild.name}` has been set to `{c.name}`.\n\nAll permission overrides for the channel have been reset. Remember to set the appropriate permissions for your guild.```\n{c.mention}')
@cog_ext.cog_subcommand(
base='config',
# subcommand_group='notifications',
name='notifications',
description='Configure monitoring and notifications to Committee for member query channels.',
# base_description='Commands for configuring the various parameters of the Guild',
# base_default_permission=False,
# base_permissions=permissions,
# subcommand_group_description='Configures whether the bot monitors and responds to posts in key channels.',
guild_ids=guild_ids,
options=[
create_option(
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'
)
]
),
create_option(
name='notifications',
description='Whether or not the bot monitors the channel for posts.',
option_type=5,
required=True
)
]
)
async def _config_notifications(self, ctx:SlashContext, channel:str, notifications:bool):
conf = yaml_load(configFile)
if 'notifications' not in conf[str(ctx.guild.id)]:
conf[str(ctx.guild.id)]['notifications'] = {}
conf[str(ctx.guild.id)]['notifications'][channel] = notifications
yaml_dump(conf, configFile)
await ctx.send(f'```Notifications for posts in the `{channel}` channel for the guild `{ctx.guild.name}` have been set to `{notifications}`.```')
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',
# base_default_permission=False,
# 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='name',
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():
await ctx.send(f'```Key value {key} is not a valid alphanumeric time code. Sanitising to `{sanitisedKey}`.```')
conf = yaml_load(configFile)
if 'timeslots' not in conf[str(ctx.guild.id)]:
conf[str(ctx.guild.id)]['timeslots'] = {}
if sanitisedKey in conf[str(ctx.guild.id)]['timeslots']:
await ctx.send(f'```Key value {sanitisedKey} has already been defined for guild `{ctx.guild.name}` for `{conf[str(ctx.guild.id)]["timeslots"][sanitisedKey]}`. Please use the `remove` or `modify` sub-commands to amend it.```')
return
conf[str(ctx.guild.id)]['timeslots'][sanitisedKey] = name
yaml_dump(conf, configFile)
await ctx.send(f'```Timeslot `{name}` with the key `{sanitisedKey}` has been added for the guild `{ctx.guild.name}`.```')
if all([len(yaml_load(configFile)[x]['timeslots']) > 0 for x in yaml_load(configFile)]):
if self.client.get_cog('Manipulate Timeslots') is None:
loadCog(f'./{cogsDir}/slashcommands/secondary/manipulate_timeslots.py')
if all(['bot' in yaml_load(configFile)[x]['roles'] for x in yaml_load(configFile)]):
if self.client.get_cog('Game Setup') is None:
loadCog(f'./{cogsDir}/slashcommands/secondary/game_setup.py')
if yaml_load(lookupFile):
if all([x for x in yaml_load(lookupFile).values()]):
if self.client.get_cog('Game Management') is None:
loadCog(f'./{cogsDir}/slashcommands/secondary/game_management.py')
2021-07-18 23:16:58 +01:00
await self.client.slash.sync_all_commands()
@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',
# base_default_permission=False,
# 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:
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:
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.```')
return
conf = yaml_load(configFile)
if 'membership' not in conf[str(ctx.guild.id)]:
conf[str(ctx.guild.id)]['membership'] = []
if role is not None:
if role.id in conf[str(ctx.guild.id)]['membership']:
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.```')
return
if any([ctx.guild.get_role(m).name == name for m in conf[str(ctx.guild.id)]['membership']]):
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.```')
return
if not role_exists:
r = await ctx.guild.create_role(
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-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}'
)
conf[str(ctx.guild.id)]['membership'].append(role.id) if role is not None else conf[str(ctx.guild.id)]['membership'].append(r.id)
yaml_dump(conf, configFile)
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}`.```')
if all([len(yaml_load(configFile)[x]['membership']) > 0 for x in yaml_load(configFile)]):
if self.client.get_cog('Edit Membership') is None:
loadCog(f'./{cogsDir}/slashcommands/secondary/edit_membership.py')
await self.client.slash.sync_all_commands()
@cog_ext.cog_slash(
name='test',
description='testing options',
guild_ids=guild_ids,
options=[
create_option(
name='required',
description='This option is mandatory',
option_type=3,
required=True
),
create_option(
name='not_required',
description='This option is not mandatory',
option_type=3,
required=False
),
create_option(
name='optional',
description='This option is optional',
option_type=3,
required=False
)
]
)
async def _test(
self,
ctx:SlashContext,
required:str,
not_required:str=None,
optional:str=None
):
await ctx.send(f'```You entered: name = {required}, not_required = {not_required}, and optional = {optional}```')
def setup(client):
client.add_cog(Configuration(client))