Started writing /commands.
Completed channel group of config subcommands Fixed bugs in config initialisation function
This commit is contained in:
		
							
								
								
									
										26
									
								
								TODO.md
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								TODO.md
									
									
									
									
									
								
							@@ -5,17 +5,21 @@
 | 
				
			|||||||
- [x] Split event listeners into individual cogs.
 | 
					- [x] Split event listeners into individual cogs.
 | 
				
			||||||
- [x] Update with re-organised data and config structure
 | 
					- [x] Update with re-organised data and config structure
 | 
				
			||||||
> - [x] Correct references to data in existing cogs.
 | 
					> - [x] Correct references to data in existing cogs.
 | 
				
			||||||
 | 
					- [x] Setup minimally functioning configs of guild on startup
 | 
				
			||||||
 | 
					- [x] Synchronise core configuration `/commands` on startup
 | 
				
			||||||
 | 
					- [ ] Synchronise secondary `/commands` on complete configuration **(see below)**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Bot Functionality
 | 
					## Bot Functionality and Processes
 | 
				
			||||||
- [ ] 'Delete Commands' Function
 | 
					- [ ] 'Delete Commands' Function
 | 
				
			||||||
- [ ] 'Register Commands' Function
 | 
					- [ ] 'Register Commands' Function
 | 
				
			||||||
- [ ] Infer Permissions from Config
 | 
					- [x] Infer Permissions from Config
 | 
				
			||||||
- [x] Dynamic Command Prefixes
 | 
					- [x] Dynamic Command Prefixes
 | 
				
			||||||
- [ ] Infer Games from Server Structure
 | 
					- [ ] Infer Games from Server Structure
 | 
				
			||||||
- [ ] Re-enable logging
 | 
					- [ ] Re-enable logging
 | 
				
			||||||
- [x] Delete Dev/Test Functions
 | 
					- [x] Delete Dev/Test Functions
 | 
				
			||||||
- [x] Error handlers
 | 
					- [x] Error handlers
 | 
				
			||||||
- [ ] Debug Features
 | 
					- [ ] Debug Features
 | 
				
			||||||
 | 
					> - [ ] Command Installer/Uninstaller
 | 
				
			||||||
- [x] Help Channel Event Listener
 | 
					- [x] Help Channel Event Listener
 | 
				
			||||||
> - [x] Add Config key for Help Channel
 | 
					> - [x] Add Config key for Help Channel
 | 
				
			||||||
- [ ] Slash Command Buttons or
 | 
					- [ ] Slash Command Buttons or
 | 
				
			||||||
@@ -28,7 +32,7 @@
 | 
				
			|||||||
- [ ] Membership Restriction
 | 
					- [ ] Membership Restriction
 | 
				
			||||||
> - [ ] Message Receive Listener
 | 
					> - [ ] Message Receive Listener
 | 
				
			||||||
> - [ ] Membership Validation Listener
 | 
					> - [ ] Membership Validation Listener
 | 
				
			||||||
- [ ] Re-register commands after any relevant config changes
 | 
					- [ ] Re-synchronise commands after any relevant config changes **(see above)**
 | 
				
			||||||
- [x] Flag for checking completeness of configuration for a guild.
 | 
					- [x] Flag for checking completeness of configuration for a guild.
 | 
				
			||||||
> - [x] Function for checking configs for completeness
 | 
					> - [x] Function for checking configs for completeness
 | 
				
			||||||
## Event Listeners
 | 
					## Event Listeners
 | 
				
			||||||
@@ -40,10 +44,24 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Commands
 | 
					## Commands
 | 
				
			||||||
- [ ] Configure Bot function and sub commands
 | 
					- [ ] Configure Bot function and sub commands
 | 
				
			||||||
 | 
					> - [x] botrole (role group)
 | 
				
			||||||
 | 
					> - [ ] committeerole (role group)
 | 
				
			||||||
 | 
					> - [x] modchannel (channel group)
 | 
				
			||||||
 | 
					> - [x] help channel (channel group)
 | 
				
			||||||
 | 
					> - [x] signup channel (channel group)
 | 
				
			||||||
 | 
					> - [ ] newcomer role (role group)
 | 
				
			||||||
 | 
					> - [ ] returning player role (role group)
 | 
				
			||||||
 | 
					> - [ ] student role (role group)
 | 
				
			||||||
 | 
					> - [ ] help notifications (notification group)
 | 
				
			||||||
 | 
					> - [ ] signup notifications (notification group)
 | 
				
			||||||
- [ ] Set up command permissions
 | 
					- [ ] Set up command permissions
 | 
				
			||||||
 | 
					> - [ ] Slash Commands
 | 
				
			||||||
 | 
					>> - [x] Admin Commands
 | 
				
			||||||
 | 
					>> - [ ] Game Management Commands
 | 
				
			||||||
 | 
					> - [x] Native Bot Commands
 | 
				
			||||||
- [ ] Migrate existing bot commands
 | 
					- [ ] Migrate existing bot commands
 | 
				
			||||||
> - [ ] setupgame
 | 
					> - [ ] setupgame
 | 
				
			||||||
> - [ ] ~~definebotrole~~ config
 | 
					> - [x] ~~definebotrole~~ config
 | 
				
			||||||
> - [ ] deletegame
 | 
					> - [ ] deletegame
 | 
				
			||||||
> - [ ] reset
 | 
					> - [ ] reset
 | 
				
			||||||
> - [ ] migrate
 | 
					> - [ ] migrate
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								app/bot.py
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								app/bot.py
									
									
									
									
									
								
							@@ -76,7 +76,7 @@ def setConfig(guild:discord.Guild):
 | 
				
			|||||||
	if guildStr not in conf:
 | 
						if guildStr not in conf:
 | 
				
			||||||
		conf[guildStr] = {}
 | 
							conf[guildStr] = {}
 | 
				
			||||||
	gDict = conf[guildStr]
 | 
						gDict = conf[guildStr]
 | 
				
			||||||
	if 'channels' not in gDict or gDict['channels'] is not dict or None in gDict['channels']:
 | 
						if 'channels' not in gDict or type(gDict['channels']) is not dict or None in gDict['channels']:
 | 
				
			||||||
		gDict['channels'] = {}
 | 
							gDict['channels'] = {}
 | 
				
			||||||
	cDict = gDict['channels']
 | 
						cDict = gDict['channels']
 | 
				
			||||||
	if 'mod' not in cDict:
 | 
						if 'mod' not in cDict:
 | 
				
			||||||
@@ -89,9 +89,9 @@ def setConfig(guild:discord.Guild):
 | 
				
			|||||||
					cDict['mod'] = t.id
 | 
										cDict['mod'] = t.id
 | 
				
			||||||
		else:
 | 
							else:
 | 
				
			||||||
			cDict['mod'] = guild.system_channel.id
 | 
								cDict['mod'] = guild.system_channel.id
 | 
				
			||||||
	if 'configured' not in gDict or gDict['configured'] is not bool:
 | 
						if 'configured' not in gDict or type(gDict['configured']) is not bool:
 | 
				
			||||||
		gDict['configured'] = False
 | 
							gDict['configured'] = False
 | 
				
			||||||
	if 'membership' not in gDict or gDict['membership'] is not dict or None in gDict['membership']:
 | 
						if 'membership' not in gDict or type(gDict['membership']) is not dict or None in gDict['membership']:
 | 
				
			||||||
		gDict['membership'] = {}
 | 
							gDict['membership'] = {}
 | 
				
			||||||
	if 'name' not in gDict or gDict['name'] != guild.name:
 | 
						if 'name' not in gDict or gDict['name'] != guild.name:
 | 
				
			||||||
		gDict['name'] = guild.name
 | 
							gDict['name'] = guild.name
 | 
				
			||||||
@@ -99,7 +99,7 @@ def setConfig(guild:discord.Guild):
 | 
				
			|||||||
		gDict['owner'] = guild.owner_id
 | 
							gDict['owner'] = guild.owner_id
 | 
				
			||||||
	if 'prefix' not in gDict:
 | 
						if 'prefix' not in gDict:
 | 
				
			||||||
		gDict['prefix'] = '-'
 | 
							gDict['prefix'] = '-'
 | 
				
			||||||
	if 'roles' not in gDict or (type(gDict)['roles'] is not dict or None in gDict['roles']):
 | 
						if 'roles' not in gDict or (type(gDict['roles']) is not dict or None in gDict['roles']):
 | 
				
			||||||
		gDict['roles'] = {}
 | 
							gDict['roles'] = {}
 | 
				
			||||||
	rDict = gDict['roles']
 | 
						rDict = gDict['roles']
 | 
				
			||||||
	if 'admin' not in rDict or (type(rDict['admin']) is not list or len(rDict['admin']) == 0 or None in rDict['admin']):
 | 
						if 'admin' not in rDict or (type(rDict['admin']) is not list or len(rDict['admin']) == 0 or None in rDict['admin']):
 | 
				
			||||||
@@ -107,7 +107,7 @@ def setConfig(guild:discord.Guild):
 | 
				
			|||||||
		for role in guild.roles:
 | 
							for role in guild.roles:
 | 
				
			||||||
			if not (role.is_bot_managed() or role.is_integration()) and role.permissions.administrator:
 | 
								if not (role.is_bot_managed() or role.is_integration()) and role.permissions.administrator:
 | 
				
			||||||
				rDict['admin'].append(role.id)
 | 
									rDict['admin'].append(role.id)
 | 
				
			||||||
	if 'timeslots' not in gDict or gDict['timeslots'] is not dict or None in gDict['timeslots']:
 | 
						if 'timeslots' not in gDict or type(gDict['timeslots']) is not dict or None in gDict['timeslots']:
 | 
				
			||||||
		gDict['timeslots'] = []
 | 
							gDict['timeslots'] = []
 | 
				
			||||||
	yaml_dump(conf, configFile)
 | 
						yaml_dump(conf, configFile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,7 +133,8 @@ def checkConfig(guild:discord.Guild):
 | 
				
			|||||||
			for item in list(i.split("'")):
 | 
								for item in list(i.split("'")):
 | 
				
			||||||
				if '[' in item or ']' in item:
 | 
									if '[' in item or ']' in item:
 | 
				
			||||||
					s.remove(item)
 | 
										s.remove(item)
 | 
				
			||||||
			unconfigured.append('.'.join(s))
 | 
								if 'notifications' not in '.'.join(s):
 | 
				
			||||||
 | 
									unconfigured.append('.'.join(s))
 | 
				
			||||||
	if 'type_changes' in diff:
 | 
						if 'type_changes' in diff:
 | 
				
			||||||
		for i in diff['type_changes']:
 | 
							for i in diff['type_changes']:
 | 
				
			||||||
			s = i.split("'")
 | 
								s = i.split("'")
 | 
				
			||||||
@@ -155,6 +156,8 @@ def checkConfig(guild:discord.Guild):
 | 
				
			|||||||
				unconfigured.append(i)
 | 
									unconfigured.append(i)
 | 
				
			||||||
	if 'meta' in unconfigured:
 | 
						if 'meta' in unconfigured:
 | 
				
			||||||
		unconfigured.remove('meta')
 | 
							unconfigured.remove('meta')
 | 
				
			||||||
 | 
						if 'initialised' in unconfigured:
 | 
				
			||||||
 | 
							unconfigured.remove('initialised')
 | 
				
			||||||
	if 'configured' in unconfigured:
 | 
						if 'configured' in unconfigured:
 | 
				
			||||||
		unconfigured.remove('configured')
 | 
							unconfigured.remove('configured')
 | 
				
			||||||
	output = list(set(unconfigured))
 | 
						output = list(set(unconfigured))
 | 
				
			||||||
@@ -228,8 +231,9 @@ def unloadCogs(cogClass:str = 'all'):
 | 
				
			|||||||
				if cogfile.endswith('.py'):
 | 
									if cogfile.endswith('.py'):
 | 
				
			||||||
					unloadCog(f'./{cogsDir}/{category}/{cogfile}')
 | 
										unloadCog(f'./{cogsDir}/{category}/{cogfile}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loadCogs('dev')
 | 
					loadCogs('devcommands')
 | 
				
			||||||
loadCogs('events')
 | 
					loadCogs('events')
 | 
				
			||||||
loadCogs('botcommands')
 | 
					loadCogs('botcommands')
 | 
				
			||||||
 | 
					loadCogs('slashcommands')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
client.run(os.getenv('TEST_3_TOKEN'))
 | 
					client.run(os.getenv('TEST_3_TOKEN'))
 | 
				
			||||||
@@ -9,7 +9,14 @@ from bot import configFile, yaml_load, yaml_dump
 | 
				
			|||||||
class Prefix(commands.Cog, name='Server Command Prefix'):
 | 
					class Prefix(commands.Cog, name='Server Command Prefix'):
 | 
				
			||||||
	def __init__(self, client):
 | 
						def __init__(self, client):
 | 
				
			||||||
		self.client = client
 | 
							self.client = client
 | 
				
			||||||
	
 | 
					
 | 
				
			||||||
 | 
						#### Check if user is an administrator	
 | 
				
			||||||
 | 
						async def cog_check(self, ctx):
 | 
				
			||||||
 | 
							for role in ctx.author.roles:
 | 
				
			||||||
 | 
								if role.permissions.administrator:
 | 
				
			||||||
 | 
									return True
 | 
				
			||||||
 | 
							return ctx.author.guild_permissions.administrator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@commands.command(
 | 
						@commands.command(
 | 
				
			||||||
		name = 'changeprefix',
 | 
							name = 'changeprefix',
 | 
				
			||||||
		aliases = ['prefix'],
 | 
							aliases = ['prefix'],
 | 
				
			||||||
@@ -20,7 +27,7 @@ class Prefix(commands.Cog, name='Server Command Prefix'):
 | 
				
			|||||||
		conf = yaml_load(configFile)
 | 
							conf = yaml_load(configFile)
 | 
				
			||||||
		conf[str(ctx.guild.id)]['prefix'] = prefix.lower()
 | 
							conf[str(ctx.guild.id)]['prefix'] = prefix.lower()
 | 
				
			||||||
		yaml_dump(conf, configFile)
 | 
							yaml_dump(conf, configFile)
 | 
				
			||||||
		await ctx.send(f"`{self.client.user.name}`'s prefix for native bot commands has been changed to `{prefix}` for the guild `{ctx.guild.name}`.\n`Note: This will not affect /commands.`")
 | 
							await ctx.send(f"```{self.client.user.name}'s prefix for native bot commands has been changed to `{prefix}` for the guild `{ctx.guild.name}`.\n\nNote: This will not affect /commands.```")
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
def setup(client):
 | 
					def setup(client):
 | 
				
			||||||
	client.add_cog(Prefix(client))
 | 
						client.add_cog(Prefix(client))
 | 
				
			||||||
@@ -16,6 +16,13 @@ class Dev(commands.Cog, name='Developer Commands'):
 | 
				
			|||||||
	def __init__(self, client):
 | 
						def __init__(self, client):
 | 
				
			||||||
		self.client = client
 | 
							self.client = client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#### Check if user is an administrator	
 | 
				
			||||||
 | 
						async def cog_check(self, ctx):
 | 
				
			||||||
 | 
							for role in ctx.author.roles:
 | 
				
			||||||
 | 
								if role.permissions.administrator:
 | 
				
			||||||
 | 
									return True
 | 
				
			||||||
 | 
							return ctx.author.guild_permissions.administrator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@commands.command(
 | 
						@commands.command(
 | 
				
			||||||
		name='debug',
 | 
							name='debug',
 | 
				
			||||||
		description='Toggles debug feature for the guild. Enter either `on` or `off`.',
 | 
							description='Toggles debug feature for the guild. Enter either `on` or `off`.',
 | 
				
			||||||
@@ -16,7 +16,10 @@ class on_command_error(commands.Cog, name='On Command Error'):
 | 
				
			|||||||
	@commands.Cog.listener()
 | 
						@commands.Cog.listener()
 | 
				
			||||||
	async def on_command_error(self, ctx, error):
 | 
						async def on_command_error(self, ctx, error):
 | 
				
			||||||
		if isinstance(error, discord.DiscordException):
 | 
							if isinstance(error, discord.DiscordException):
 | 
				
			||||||
			if isinstance(error, commands.CheckFailure):
 | 
								if isinstance(error, commands.CommandNotFound):
 | 
				
			||||||
 | 
									print(f'Error: User {ctx.author.name}#{ctx.author.discriminator} / {ctx.author.display_name} entered an invalid command <{ctx.message.clean_content}> in the guild {ctx.guild.name}.')
 | 
				
			||||||
 | 
									await ctx.reply(f'```Error: This is not a valid command.```')
 | 
				
			||||||
 | 
								elif isinstance(error, commands.CheckFailure):
 | 
				
			||||||
				print(f'Error: User {ctx.author.name}#{ctx.author.discriminator} / {ctx.author.display_name} is not authorised to issue the command <{ctx.command.name}> in the guild {ctx.guild.name}.')
 | 
									print(f'Error: User {ctx.author.name}#{ctx.author.discriminator} / {ctx.author.display_name} is not authorised to issue the command <{ctx.command.name}> in the guild {ctx.guild.name}.')
 | 
				
			||||||
				await ctx.reply(f'```Error: You are not authorised to issue this command.```')
 | 
									await ctx.reply(f'```Error: You are not authorised to issue this command.```')
 | 
				
			||||||
			else:
 | 
								else:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ from discord_slash import SlashCommand, SlashContext, cog_ext, utils			# Slash C
 | 
				
			|||||||
from discord_slash.utils.manage_commands import create_choice, create_option	# Slash Command features
 | 
					from discord_slash.utils.manage_commands import create_choice, create_option	# Slash Command features
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
# logger and handler
 | 
					# logger and handler
 | 
				
			||||||
from bot import checkConfig, clearConfig, configFile, parseConfigCheck, setConfig, yaml_dump, yaml_load
 | 
					from bot import checkConfig, clearConfig, configFile, parseConfigCheck, setConfig, yaml_dump, yaml_load, loadCogs, unloadCogs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Actions for the Bot to take once it is ready to interact with commands.
 | 
					#### Actions for the Bot to take once it is ready to interact with commands.
 | 
				
			||||||
class on_ready(commands.Cog, name='On Ready Events'):
 | 
					class on_ready(commands.Cog, name='On Ready Events'):
 | 
				
			||||||
@@ -17,6 +17,9 @@ class on_ready(commands.Cog, name='On Ready Events'):
 | 
				
			|||||||
	@commands.Cog.listener()
 | 
						@commands.Cog.listener()
 | 
				
			||||||
	async def on_ready(self):
 | 
						async def on_ready(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							async def test(self):
 | 
				
			||||||
 | 
								await self.client.get_channel(865348933022515220).send('Foo')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		#### Create any missing config entries for guilds
 | 
							#### Create any missing config entries for guilds
 | 
				
			||||||
		for guild in self.client.guilds:
 | 
							for guild in self.client.guilds:
 | 
				
			||||||
			setConfig(guild)
 | 
								setConfig(guild)
 | 
				
			||||||
@@ -32,6 +35,12 @@ class on_ready(commands.Cog, name='On Ready Events'):
 | 
				
			|||||||
			conf = yaml_load(configFile)
 | 
								conf = yaml_load(configFile)
 | 
				
			||||||
			if not status:
 | 
								if not status:
 | 
				
			||||||
				await guild.get_channel(conf[str(guild.id)]['channels']['mod']).send(f"```The Bot's configurations are incomplete for the guild `{guild.name}`. Some limited functions will still be available, but most features cannot be used until the configurations are complete.\n{parseConfigCheck(output)}\nYou can set these configuration values using the `/config` command.```")
 | 
									await guild.get_channel(conf[str(guild.id)]['channels']['mod']).send(f"```The Bot's configurations are incomplete for the guild `{guild.name}`. Some limited functions will still be available, but most features cannot be used until the configurations are complete.\n{parseConfigCheck(output)}\nYou can set these configuration values using the `/config` command.```")
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							# #### Reload the /commands after the configs have finished loading.
 | 
				
			||||||
 | 
							# unloadCogs('slashcommands')
 | 
				
			||||||
 | 
							# loadCogs('slashcommands')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							await test(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup(client):
 | 
					def setup(client):
 | 
				
			||||||
	client.add_cog(on_ready(client))
 | 
						client.add_cog(on_ready(client))
 | 
				
			||||||
							
								
								
									
										36
									
								
								app/cogs/events/on_slash_command_error.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/cogs/events/on_slash_command_error.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					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	# Slash Command features
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					# logger and handler
 | 
				
			||||||
 | 
					from bot import configFile, yaml_load, yaml_dump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Error Handler Event Listener for Slash Command Errors
 | 
				
			||||||
 | 
					class on_slash_command_error(commands.Cog, name='On Command Error'):
 | 
				
			||||||
 | 
						def __init__(self, client):
 | 
				
			||||||
 | 
							self.client = client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@commands.Cog.listener()
 | 
				
			||||||
 | 
						async def on_slash_command_error(self, ctx:SlashContext, error):
 | 
				
			||||||
 | 
							if isinstance(error, Exception):
 | 
				
			||||||
 | 
								await ctx.send(
 | 
				
			||||||
 | 
									content='```Invalid Command: {error}```',
 | 
				
			||||||
 | 
									tts=True,
 | 
				
			||||||
 | 
									hidden=True,
 | 
				
			||||||
 | 
									delete_after=10,				
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								# if isinstance(error, commands.CommandNotFound):
 | 
				
			||||||
 | 
								# 	print(f'Error: User {ctx.author.name}#{ctx.author.discriminator} / {ctx.author.display_name} entered an invalid command <{ctx.message.clean_content}> in the guild {ctx.guild.name}.')
 | 
				
			||||||
 | 
								# 	await ctx.reply(f'```Error: This is not a valid command.```')
 | 
				
			||||||
 | 
								# elif isinstance(error, commands.CheckFailure):
 | 
				
			||||||
 | 
								# 	print(f'Error: User {ctx.author.name}#{ctx.author.discriminator} / {ctx.author.display_name} is not authorised to issue the command <{ctx.command.name}> in the guild {ctx.guild.name}.')
 | 
				
			||||||
 | 
								# 	await ctx.reply(f'```Error: You are not authorised to issue this command.```')
 | 
				
			||||||
 | 
								# else:
 | 
				
			||||||
 | 
								# 	print(f'User {ctx.author.name}#{ctx.author.discriminator} / {ctx.author.display_name} received error: "{error}" when attempting to issue command <{ctx.command.name}> in the guild {ctx.guild.name}.')
 | 
				
			||||||
 | 
								# 	await ctx.reply(f'```Error: {error}```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup(client):
 | 
				
			||||||
 | 
						client.add_cog(on_slash_command_error(client))
 | 
				
			||||||
@@ -4,32 +4,163 @@ import asyncio							# Discord Py Dependency
 | 
				
			|||||||
import discord							# Main Lib
 | 
					import discord							# Main Lib
 | 
				
			||||||
from discord.ext import commands		# Commands module
 | 
					from discord.ext import commands		# Commands module
 | 
				
			||||||
from discord_slash import SlashCommand, SlashContext, cog_ext, utils			# Slash Command Library
 | 
					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
 | 
					from discord_slash.utils.manage_commands import create_choice, create_option, create_permission	# Slash Command features
 | 
				
			||||||
 | 
					from discord_slash.model import SlashCommandPermissionType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from bot import configFile, yaml_load, yaml_dump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Configuration Cog
 | 
					##### Configuration Cog
 | 
				
			||||||
class Configuration(commands.Cog):
 | 
					class Configuration(commands.Cog):
 | 
				
			||||||
	def __init__(self, client):
 | 
						def __init__(self, client):
 | 
				
			||||||
		self.client = 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_slash(
 | 
						@cog_ext.cog_slash(
 | 
				
			||||||
		# base='botrole',
 | 
							name='hello',
 | 
				
			||||||
		# subcommand_group='configure',
 | 
							description='Test command to see if registration works.',
 | 
				
			||||||
		name='configure',
 | 
							guild_ids=guild_ids,
 | 
				
			||||||
		description='Parameter to define the role assigned to the dice bots.',
 | 
							options=[
 | 
				
			||||||
		# base_description='Command to configure the various guild parameters.',
 | 
								create_option(
 | 
				
			||||||
		# subcommand_group_description='These are configuration commands to set up the various guild parameters.',
 | 
									name='input',
 | 
				
			||||||
		guild_ids=guild_ids
 | 
									description='Choose a phrase that best goes with the opening Hello',
 | 
				
			||||||
		# options=[
 | 
									option_type=3,
 | 
				
			||||||
		# 	create_option(
 | 
									required=True,
 | 
				
			||||||
		# 		name='botrole',
 | 
									choices=[
 | 
				
			||||||
		# 		description='The role that the dice bots are assigned in order to access the text channels.'
 | 
										create_choice(
 | 
				
			||||||
		# 		type=8,
 | 
											name='...there',
 | 
				
			||||||
		# 		required=True
 | 
											value='there'
 | 
				
			||||||
		# 	)
 | 
										),
 | 
				
			||||||
		# ]
 | 
										create_choice(
 | 
				
			||||||
 | 
											name='...world!',
 | 
				
			||||||
 | 
											value='world'
 | 
				
			||||||
 | 
										),
 | 
				
			||||||
 | 
										create_choice(
 | 
				
			||||||
 | 
											name='...beautiful!',
 | 
				
			||||||
 | 
											value='beautiful'
 | 
				
			||||||
 | 
										)
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	async def _configure(self, ctx:SlashContext, option):
 | 
						async def _hello(self, ctx:SlashContext, input):
 | 
				
			||||||
		await ctx.send(f'The `botrole` for the guild `{ctx.guild.name}` has been set to `{option}`.')
 | 
							await ctx.send(f'{input}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@cog_ext.cog_subcommand(
 | 
				
			||||||
 | 
							base='config',
 | 
				
			||||||
 | 
							subcommand_group='role',
 | 
				
			||||||
 | 
							name='bot',
 | 
				
			||||||
 | 
							description='Designate the role on the guild which the dice bots use to access game text channels.',
 | 
				
			||||||
 | 
							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='role',
 | 
				
			||||||
 | 
									description='The role assigned to dice bots to access game channels.',
 | 
				
			||||||
 | 
									option_type=8,
 | 
				
			||||||
 | 
									required=True
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						async def _config_role_bot(self, ctx:SlashContext, role:discord.Role):
 | 
				
			||||||
 | 
							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']['bots'] = int(role.id)
 | 
				
			||||||
 | 
							yaml_dump(conf, configFile)
 | 
				
			||||||
 | 
							await ctx.send(f'```The `botrole` for the guild `{ctx.guild.name}` has been set to `{role.name}`.```')
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						@cog_ext.cog_subcommand(
 | 
				
			||||||
 | 
							base='config',
 | 
				
			||||||
 | 
							subcommand_group='channel',
 | 
				
			||||||
 | 
							name='signup',
 | 
				
			||||||
 | 
							description='Designate the channel where members can post their sign-up confirmation.',
 | 
				
			||||||
 | 
							# 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='channel',
 | 
				
			||||||
 | 
									description='The channel assigned for members to verify their membership.',
 | 
				
			||||||
 | 
									option_type=7,
 | 
				
			||||||
 | 
									required=True
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						async def _config_channel_signup(self, ctx:SlashContext, channel:discord.TextChannel):
 | 
				
			||||||
 | 
							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']['signup'] = int(channel.id)
 | 
				
			||||||
 | 
							yaml_dump(conf, configFile)
 | 
				
			||||||
 | 
							await ctx.send(f'```The `signup` channel for the guild `{ctx.guild.name}` has been set to `{channel.name}`.```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@cog_ext.cog_subcommand(
 | 
				
			||||||
 | 
							base='config',
 | 
				
			||||||
 | 
							subcommand_group='channel',
 | 
				
			||||||
 | 
							name='modlog',
 | 
				
			||||||
 | 
							description='Designate the channel for bot to post notifications for the admins.',
 | 
				
			||||||
 | 
							# 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='channel',
 | 
				
			||||||
 | 
									description='The channel assigned for moderation notifications.',
 | 
				
			||||||
 | 
									option_type=7,
 | 
				
			||||||
 | 
									required=True
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						async def _config_channel_mod(self, ctx:SlashContext, channel:discord.TextChannel):
 | 
				
			||||||
 | 
							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']['mod'] = int(channel.id)
 | 
				
			||||||
 | 
							yaml_dump(conf, configFile)
 | 
				
			||||||
 | 
							await ctx.send(f'```The `moderation log` channel for the guild `{ctx.guild.name}` has been set to `{channel.name}`.```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@cog_ext.cog_subcommand(
 | 
				
			||||||
 | 
							base='config',
 | 
				
			||||||
 | 
							subcommand_group='channel',
 | 
				
			||||||
 | 
							name='help',
 | 
				
			||||||
 | 
							description='Designate the hel channel which the bot will monitor for member queries.',
 | 
				
			||||||
 | 
							# 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='channel',
 | 
				
			||||||
 | 
									description='The channel monitored by the Bot for help queries.',
 | 
				
			||||||
 | 
									option_type=7,
 | 
				
			||||||
 | 
									required=True
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						async def _config_channel_help(self, ctx:SlashContext, channel:discord.TextChannel):
 | 
				
			||||||
 | 
							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']['help'] = int(channel.id)
 | 
				
			||||||
 | 
							yaml_dump(conf, configFile)
 | 
				
			||||||
 | 
							await ctx.send(f'```The `help` channel for the guild `{ctx.guild.name}` has been set to `{channel.name}`.```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup(client):
 | 
					def setup(client):
 | 
				
			||||||
	client.add_cog(Configuration(client))
 | 
						client.add_cog(Configuration(client))
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
'864651943820525609':
 | 
					'864651943820525609':
 | 
				
			||||||
  channels:
 | 
					  channels:
 | 
				
			||||||
    mod: 865348933022515220
 | 
					    mod: 865662560225067018
 | 
				
			||||||
  configured: false
 | 
					  configured: false
 | 
				
			||||||
  membership: {}
 | 
					  membership: {}
 | 
				
			||||||
  name: Test
 | 
					  name: Test
 | 
				
			||||||
@@ -12,4 +12,5 @@
 | 
				
			|||||||
  roles:
 | 
					  roles:
 | 
				
			||||||
    admin:
 | 
					    admin:
 | 
				
			||||||
    - 864661232005939280
 | 
					    - 864661232005939280
 | 
				
			||||||
 | 
					    bots: 864661167297527830
 | 
				
			||||||
  timeslots: []
 | 
					  timeslots: []
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,3 +28,4 @@ guild_id_string:
 | 
				
			|||||||
  notifications:
 | 
					  notifications:
 | 
				
			||||||
    help: true
 | 
					    help: true
 | 
				
			||||||
    signup: true
 | 
					    signup: true
 | 
				
			||||||
 | 
					  initialised: true
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ class Debug(commands.Cog, name='Debug Commands'):
 | 
				
			|||||||
	async def _reload(self, ctx, cog_category: str='all'):
 | 
						async def _reload(self, ctx, cog_category: str='all'):
 | 
				
			||||||
		unloadCogs(cog_category)
 | 
							unloadCogs(cog_category)
 | 
				
			||||||
		loadCogs(cog_category)
 | 
							loadCogs(cog_category)
 | 
				
			||||||
		await ctx.reply(f'`{cog_category}` cogs have been reloaded.')
 | 
							await ctx.reply(f'````{cog_category}` cogs have been reloaded.```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@commands.command(
 | 
						@commands.command(
 | 
				
			||||||
		name='unloadcogs',
 | 
							name='unloadcogs',
 | 
				
			||||||
@@ -36,7 +36,7 @@ class Debug(commands.Cog, name='Debug Commands'):
 | 
				
			|||||||
	async def _unloadcogs(self, ctx, cog_category: str='all'):
 | 
						async def _unloadcogs(self, ctx, cog_category: str='all'):
 | 
				
			||||||
		unloadCogs(cog_category)
 | 
							unloadCogs(cog_category)
 | 
				
			||||||
		loadCogs(cog_category)
 | 
							loadCogs(cog_category)
 | 
				
			||||||
		await ctx.reply(f'`{cog_category}` cogs have been unloaded.')
 | 
							await ctx.reply(f'````{cog_category}` cogs have been unloaded.```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@commands.command(
 | 
						@commands.command(
 | 
				
			||||||
		name='loadcogs',
 | 
							name='loadcogs',
 | 
				
			||||||
@@ -46,11 +46,11 @@ class Debug(commands.Cog, name='Debug Commands'):
 | 
				
			|||||||
	async def _loadcogs(self, ctx, cog_category: str='all'):
 | 
						async def _loadcogs(self, ctx, cog_category: str='all'):
 | 
				
			||||||
		unloadCogs(cog_category)
 | 
							unloadCogs(cog_category)
 | 
				
			||||||
		loadCogs(cog_category)
 | 
							loadCogs(cog_category)
 | 
				
			||||||
		await ctx.reply(f'`{cog_category}` cogs have been loaded.')
 | 
							await ctx.reply(f'````{cog_category}` cogs have been loaded.```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@commands.command(
 | 
						@commands.command(
 | 
				
			||||||
		name='deletecommands',
 | 
							name='deletecommands',
 | 
				
			||||||
		aliases=['delallcommands','deleteslashcommands'],
 | 
							aliases=['delallcommands','deleteslashcommands','clearcommands','clearslashcommands'],
 | 
				
			||||||
		description='Deletes all the public and guild slash commands registered by the bot.',
 | 
							description='Deletes all the public and guild slash commands registered by the bot.',
 | 
				
			||||||
		brief='Delets all slash commands'
 | 
							brief='Delets all slash commands'
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
@@ -65,7 +65,7 @@ class Debug(commands.Cog, name='Debug Commands'):
 | 
				
			|||||||
			bot_token=os.getenv('TEST_3_TOKEN'),
 | 
								bot_token=os.getenv('TEST_3_TOKEN'),
 | 
				
			||||||
			guild_ids=[ int(g) for g in yaml_load(configFile)]
 | 
								guild_ids=[ int(g) for g in yaml_load(configFile)]
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
		await ctx.reply('All slash commands have been deleted.')
 | 
							await ctx.reply('```All slash commands have been deleted.```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@commands.command(
 | 
						@commands.command(
 | 
				
			||||||
		name='retrievecommands',
 | 
							name='retrievecommands',
 | 
				
			||||||
@@ -76,6 +76,7 @@ class Debug(commands.Cog, name='Debug Commands'):
 | 
				
			|||||||
	async def _retrievecommands(self, ctx:commands.Context):
 | 
						async def _retrievecommands(self, ctx:commands.Context):
 | 
				
			||||||
		c = await utils.manage_commands.get_all_commands(self.client.user.id,os.getenv('TEST_3_TOKEN'),guild_id=ctx.guild.id)
 | 
							c = await utils.manage_commands.get_all_commands(self.client.user.id,os.getenv('TEST_3_TOKEN'),guild_id=ctx.guild.id)
 | 
				
			||||||
		print(c)
 | 
							print(c)
 | 
				
			||||||
 | 
							await ctx.reply(f'```All registered `/commands` have been fetched and sent to the Python console.```')
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	@commands.command(
 | 
						@commands.command(
 | 
				
			||||||
		name='clearconfig',
 | 
							name='clearconfig',
 | 
				
			||||||
@@ -87,7 +88,7 @@ class Debug(commands.Cog, name='Debug Commands'):
 | 
				
			|||||||
		conf = yaml_load(configFile)
 | 
							conf = yaml_load(configFile)
 | 
				
			||||||
		for key in list(conf):
 | 
							for key in list(conf):
 | 
				
			||||||
			clearConfig(key)
 | 
								clearConfig(key)
 | 
				
			||||||
		await ctx.reply(f'Config entries have been cleared.')
 | 
							await ctx.reply(f'```Config entries for unknown guilds have been cleared.```')
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	@commands.command(
 | 
						@commands.command(
 | 
				
			||||||
		name='setconfig',
 | 
							name='setconfig',
 | 
				
			||||||
@@ -97,7 +98,7 @@ class Debug(commands.Cog, name='Debug Commands'):
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
	async def _setconfig(self, ctx:commands.Context):
 | 
						async def _setconfig(self, ctx:commands.Context):
 | 
				
			||||||
		setConfig(ctx.guild)
 | 
							setConfig(ctx.guild)
 | 
				
			||||||
		await ctx.reply(f'Config entry has been added for guild `{ctx.guild.name}`.')
 | 
							await ctx.reply(f'```Config entry has been added for guild `{ctx.guild.name}`.```')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup(client):
 | 
					def setup(client):
 | 
				
			||||||
	client.add_cog(Debug(client))
 | 
						client.add_cog(Debug(client))
 | 
				
			||||||
		Reference in New Issue
	
	Block a user