forked from viveksantayana/geas-bot
Vivek Santayana
5bb9af12c9
Wrote up documentation. Readme needs finishing. Future development needs to use global listeners for processes.
406 lines
16 KiB
Python
406 lines
16 KiB
Python
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
|
|
import re
|
|
|
|
from bot import configFile, yaml_load, yaml_dump, loadCog, unloadCog, reloadCog, cogsDir, slash, lookupFile
|
|
|
|
##### Configuration Cog
|
|
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 gStr in conf:
|
|
permissions[int(gStr)] = []
|
|
permissions[int(gStr)].append(create_permission(id=conf[gStr]['owner'],id_type=SlashCommandPermissionType.USER,permission=True))
|
|
for admin in conf[gStr]['roles']['admin']: permissions[int(gStr)].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. Please select a role to assign.```',hidden=True)
|
|
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 does not exist, do not assign a role.```',hidden=True)
|
|
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)
|
|
guildStr = str(ctx.guild.id)
|
|
if 'roles' not in conf[guildStr]:
|
|
conf[guildStr]['roles'] = {}
|
|
conf[guildStr]['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}',hidden=True)
|
|
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
|
|
if self.client.get_cog('Game Create') is None:
|
|
loadCog(f'./{cogsDir}/slashcommands/secondary/game_create.py')
|
|
flag = True
|
|
if any([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')
|
|
flag = True
|
|
if self.client.get_cog('Player Commands') is None:
|
|
loadCog(f'./{cogsDir}/slashcommands/secondary/player_commands.py')
|
|
flag = True
|
|
if self.client.get_cog('Pitch') is None:
|
|
loadCog(f'./{cogsDir}/slashcommands/secondary/pitch.py')
|
|
flag = True
|
|
if flag: 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. Please select a role to assign.```',hidden=True)
|
|
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 does not exist, do not assign a channel.```',hidden=True)
|
|
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)
|
|
guildStr = str(ctx.guild.id)
|
|
if 'channels' not in conf[guildStr]:
|
|
conf[guildStr]['channels'] = {}
|
|
conf[guildStr]['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}',hidden=True)
|
|
|
|
@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)
|
|
guildStr = str(ctx.guild.id)
|
|
if 'notifications' not in conf[guildStr]:
|
|
conf[guildStr]['notifications'] = {}
|
|
conf[guildStr]['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}`.```',hidden=True)
|
|
|
|
@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}`.```',hidden=True)
|
|
conf = yaml_load(configFile)
|
|
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)
|
|
return
|
|
conf[guildStr]['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}`.```',hidden=True)
|
|
if any([yaml_load(configFile)[x]['timeslots'] for x in yaml_load(configFile)]):
|
|
flag = False
|
|
if self.client.get_cog('Manipulate Timeslots') is None:
|
|
loadCog(f'./{cogsDir}/slashcommands/secondary/manipulate_timeslots.py')
|
|
flag = True
|
|
if any(['bot' in yaml_load(configFile)[x]['roles'] for x in yaml_load(configFile)]):
|
|
if self.client.get_cog('Game Create') is None:
|
|
loadCog(f'./{cogsDir}/slashcommands/secondary/game_create.py')
|
|
Flag = True
|
|
if yaml_load(lookupFile):
|
|
if any([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')
|
|
Flag = True
|
|
if self.client.get_cog('Player Commands') is None:
|
|
loadCog(f'./{cogsDir}/slashcommands/secondary/player_commands.py')
|
|
Flag = True
|
|
if self.client.get_cog('Pitch') is None:
|
|
loadCog(f'./{cogsDir}/slashcommands/secondary/pitch.py')
|
|
Flag = True
|
|
if flag: 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.```')
|
|
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.```',hidden=True)
|
|
return
|
|
conf = yaml_load(configFile)
|
|
guildStr = str(ctx.guild.id)
|
|
if 'membership' not in conf[guildStr]:
|
|
conf[guildStr]['membership'] = []
|
|
if role is not None:
|
|
if role.id in conf[guildStr]['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.```',hidden=True)
|
|
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.```',hidden=True)
|
|
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}'
|
|
)
|
|
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[guildStr]['membership'].append(role.id) if role is not None else conf[guildStr]['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}`.```',hidden=True)
|
|
if any([yaml_load(configFile)[x]['membership'] 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_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',
|
|
# 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='value',
|
|
description='Enable membership restrictions for the guild?',
|
|
option_type=5,
|
|
required=True
|
|
)
|
|
]
|
|
)
|
|
async def _restrict(
|
|
self,
|
|
ctx:SlashContext,
|
|
value:bool
|
|
):
|
|
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)
|
|
|
|
def setup(client):
|
|
client.add_cog(Configuration(client)) |