Debugged membership sign-ups and pitch menu.
Ready for more rigorous testing.
This commit is contained in:
		@@ -1,36 +0,0 @@
 | 
			
		||||
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))
 | 
			
		||||
							
								
								
									
										163
									
								
								app/cogs/events/secondary/pitch_listener.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								app/cogs/events/secondary/pitch_listener.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
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, ComponentContext			# 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, ButtonStyle
 | 
			
		||||
from discord_slash.client import SlashCommand
 | 
			
		||||
from discord_slash.utils.manage_components import create_select, create_select_option, create_actionrow, wait_for_component, create_button, create_actionrow
 | 
			
		||||
 | 
			
		||||
from bot import configFile, yaml_load, yaml_dump, cogsDir, unloadCog, dataFile, lookupFile, gmFile, categoriesFile, pitchesFile, configFile, dataFile, lookupFile, unloadCog
 | 
			
		||||
 | 
			
		||||
#### Pitch Command
 | 
			
		||||
 | 
			
		||||
class PitchListener(commands.Cog, name='Pitch Listener'):
 | 
			
		||||
	def __init__(self, client):
 | 
			
		||||
		self.client = client
 | 
			
		||||
 | 
			
		||||
	@commands.Cog.listener(name='on_component')
 | 
			
		||||
	async def _pitch_listener(self, ctx:ComponentContext):
 | 
			
		||||
		conf = yaml_load(configFile)
 | 
			
		||||
		data = yaml_load(dataFile)
 | 
			
		||||
		lookup = yaml_load(lookupFile)
 | 
			
		||||
		pitches = yaml_load(pitchesFile)
 | 
			
		||||
		guildStr = str(ctx.guild.id)
 | 
			
		||||
		if not pitches.get(guildStr, {}): return	# If no pitches for current guild, ignore.
 | 
			
		||||
		[timeslot] = [*pitches[guildStr]]
 | 
			
		||||
		if ctx.origin_message.id not in pitches[guildStr][timeslot]['messages'] + [pitches[guildStr][timeslot]['control']]: return	# If the context id is not in the pitch menu, ignore
 | 
			
		||||
		newcomer = returning_player = None
 | 
			
		||||
		if 'newcomer' in conf[guildStr]['roles']: newcomer = discord.utils.find(lambda x: x.id == conf[guildStr]['roles']['newcomer'], ctx.guild.roles)
 | 
			
		||||
		if 'returning_player' in conf[guildStr]['roles']: returning_player = discord.utils.find(lambda x: x.id == conf[guildStr]['roles']['returning_player'], ctx.guild.roles)
 | 
			
		||||
		control = await ctx.channel.fetch_message(pitches[guildStr][timeslot]['control'])
 | 
			
		||||
		header_message = await ctx.channel.fetch_message(pitches[guildStr][timeslot]['header_message'])
 | 
			
		||||
		if ctx.origin_message.id == control.id:
 | 
			
		||||
			if not (set(ctx.author.roles) & set([ctx.guild.get_role(x) for x in conf[str(ctx.guild.id)]['roles']['admin']]) or ctx.author == ctx.guild.owner):
 | 
			
		||||
				await ctx.send(f'```Error: You are not authorised to do this. The control panel may only be issued by an administrator.```',hidden=True)
 | 
			
		||||
			else:
 | 
			
		||||
				if ctx.custom_id == 'allow_returning':
 | 
			
		||||
					await ctx.channel.set_permissions(reason=f'/pitch control switch triggered by {ctx.author.display_name}', target=returning_player, read_messages=True)
 | 
			
		||||
					await ctx.send(f'```Returning Players have now been allowed access to the pitch menu.```',  hidden=True)
 | 
			
		||||
				if ctx.custom_id == 'allow_newcomers':
 | 
			
		||||
					await ctx.channel.set_permissions(reason=f'/pitch control switch triggered by {ctx.author.display_name}', target=newcomer, read_messages=True)
 | 
			
		||||
					await ctx.send(f'```Newcomers have now been allowed access to the pitch menu.```',  hidden=True)
 | 
			
		||||
				if ctx.custom_id == 'allow_all':
 | 
			
		||||
					await ctx.channel.set_permissions(reason=f'/pitch control switch triggered by {ctx.author.display_name}', target=ctx.guild.default_role, read_messages= True, send_messages=False)
 | 
			
		||||
					await ctx.send(f'```All members have now been allowed access to the pitch menu.```', hidden=True)
 | 
			
		||||
				if ctx.custom_id == 'close_pitches':
 | 
			
		||||
					await ctx.send(f'```Please wait: closing pitches.```', hidden=True)
 | 
			
		||||
					await header_message.delete()
 | 
			
		||||
					for message in pitches[guildStr][timeslot]['messages']:
 | 
			
		||||
						m = await ctx.channel.fetch_message(message)
 | 
			
		||||
						await m.delete()
 | 
			
		||||
					await control.delete()
 | 
			
		||||
					await ctx.channel.edit(reason=f'/pitch command issued by {ctx.author.display_name}', overwrites={})
 | 
			
		||||
					await ctx.channel.send('```Pitch menu cleared. Pitches have now concluded.```')
 | 
			
		||||
					del pitches[guildStr][timeslot]
 | 
			
		||||
					if not pitches[guildStr]: del pitches[guildStr]
 | 
			
		||||
					yaml_dump(pitches,pitchesFile)
 | 
			
		||||
					if not pitches and self.client.get_cog('Pitch Listener') is not None:
 | 
			
		||||
						unloadCog(f'./{cogsDir}/events/secondary/pitch_listener.py')
 | 
			
		||||
						#### Deactivate global pitch listener
 | 
			
		||||
		else:
 | 
			
		||||
			index = int(ctx.custom_id.split('_',1)[1])
 | 
			
		||||
			if ctx.custom_id.startswith('join_'):
 | 
			
		||||
				if set([x.id for x in ctx.author.roles]) & set(pitches[guildStr][timeslot]['roles'].values()):
 | 
			
		||||
					for r in list(set([x.id for x in ctx.author.roles]) & set(pitches[guildStr][timeslot]['roles'].values())):
 | 
			
		||||
						role = ctx.guild.get_role(r)
 | 
			
		||||
						if role.id != pitches[guildStr][timeslot]['roles'][index]:
 | 
			
		||||
							await ctx.author.remove_roles(role,reason=f'/pitch interaction by {ctx.author.display_name}')
 | 
			
		||||
							i = pitches[guildStr][timeslot]['indices'][role.id]
 | 
			
		||||
							element = pitches[guildStr][timeslot]['entries'][i]
 | 
			
		||||
							gm = await self.client.fetch_user(element['gm'])
 | 
			
		||||
							data[guildStr][timeslot][str(role.id)]['current_players'] -= 1
 | 
			
		||||
							element['current_players'] -= 1
 | 
			
		||||
							o = f'_ _\n***{element["game_title"]}*** (GM: {gm.mention})\n```\n'
 | 
			
		||||
							if element['system'] is not None: o = ''.join([o,f'System: {element["system"]}\n'])
 | 
			
		||||
							if element['min_players'] is not None: o = ''.join([o,f'Minimum Players: {str(element["min_players"])}	'])
 | 
			
		||||
							if element['max_players'] is not None: o = ''.join([o,f'Maximum Players: {str(element["max_players"])}\n'])
 | 
			
		||||
							if element['platform'] is not None: o = ''.join([o,f'Platform: {element["platform"]}\n'])
 | 
			
		||||
							o = ''.join([o,f'```'])
 | 
			
		||||
							spaces_remaining = element["max_players"] - element["current_players"]
 | 
			
		||||
							o = ''.join([o,f'~~Spaces Remaining: {str(0)}~~'])if spaces_remaining <= 0 else ''.join([o,f'Spaces Remaining: {str(spaces_remaining)}'])
 | 
			
		||||
							m = await ctx.channel.fetch_message(pitches[guildStr][timeslot]['messages'][i])
 | 
			
		||||
							await m.edit(content=o)
 | 
			
		||||
							tc = discord.utils.find(lambda x: x.id == lookup[guildStr][str(role.id)]['text_channel'],ctx.guild.text_channels)
 | 
			
		||||
							if tc is None:
 | 
			
		||||
								c = discord.utils.find(lambda x: x.id == lookup[guildStr][str(role.id)]['category'],ctx.guild.categories)
 | 
			
		||||
								if c is not None:
 | 
			
		||||
									tPos = len(ctx.guild.channels)
 | 
			
		||||
									for t in c.text_channels:
 | 
			
		||||
										if t.position <= tPos:
 | 
			
		||||
											tc = t
 | 
			
		||||
											tPos = t.position
 | 
			
		||||
							if tc is not None:
 | 
			
		||||
								await tc.send(f'```{ctx.author.display_name} has left the game.```')
 | 
			
		||||
				role = ctx.guild.get_role(pitches[guildStr][timeslot]['roles'][index])
 | 
			
		||||
				if role in ctx.author.roles:
 | 
			
		||||
					await ctx.send(f'```Error: You are already in the game `{lookup[guildStr][str(role.id)]["game_title"]}`.```', hidden=True)
 | 
			
		||||
				else:
 | 
			
		||||
					await ctx.author.add_roles(role,reason=f'/pitch interaction by {ctx.author.display_name}')
 | 
			
		||||
					element = pitches[guildStr][timeslot]['entries'][index]
 | 
			
		||||
					data[guildStr][timeslot][str(role.id)]['current_players'] += 1
 | 
			
		||||
					element['current_players'] += 1
 | 
			
		||||
					gm = await self.client.fetch_user(element['gm'])
 | 
			
		||||
					o = f'_ _\n***{element["game_title"]}*** (GM: {gm.mention})\n```\n'
 | 
			
		||||
					if element['system'] is not None: o = ''.join([o,f'System: {element["system"]}\n'])
 | 
			
		||||
					if element['min_players'] is not None: o = ''.join([o,f'Minimum Players: {str(element["min_players"])}	'])
 | 
			
		||||
					if element['max_players'] is not None: o = ''.join([o,f'Maximum Players: {str(element["max_players"])}\n'])
 | 
			
		||||
					if element['platform'] is not None: o = ''.join([o,f'Platform: {element["platform"]}\n'])
 | 
			
		||||
					o = ''.join([o,f'```'])
 | 
			
		||||
					spaces_remaining = element["max_players"] - element["current_players"]
 | 
			
		||||
					o = ''.join([o,f'~~Spaces Remaining: {str(0)}~~'])if spaces_remaining <= 0 else ''.join([o,f'Spaces Remaining: {str(spaces_remaining)}'])
 | 
			
		||||
					m = await ctx.channel.fetch_message(pitches[guildStr][timeslot]['messages'][index])
 | 
			
		||||
					await m.edit(content=o)
 | 
			
		||||
					await ctx.send(f'You have joined the game `{lookup[guildStr][str(role.id)]["game_title"]}`.',hidden=True)
 | 
			
		||||
					tc = discord.utils.find(lambda x: x.id == lookup[guildStr][str(role.id)]['text_channel'],ctx.guild.text_channels)
 | 
			
		||||
					if tc is None:
 | 
			
		||||
						c = discord.utils.find(lambda x: x.id == lookup[guildStr][str(role.id)]['category'],ctx.guild.categories)
 | 
			
		||||
						if c is not None:
 | 
			
		||||
							tPos = len(ctx.guild.channels)
 | 
			
		||||
							for t in c.text_channels:
 | 
			
		||||
								if t.position <= tPos:
 | 
			
		||||
									tc = t
 | 
			
		||||
									tPos = t.position
 | 
			
		||||
					if tc is not None:
 | 
			
		||||
						await tc.send(f'```{ctx.author.display_name} has joined the game.```')
 | 
			
		||||
			elif ctx.custom_id.startswith('leave_'):
 | 
			
		||||
				role = ctx.guild.get_role(pitches[guildStr][timeslot]['roles'][index])
 | 
			
		||||
				if role not in ctx.author.roles:
 | 
			
		||||
					await ctx.send(f'```Error: You are not in the game `{lookup[guildStr][str(role.id)]["game_title"]}`.```', hidden=True)
 | 
			
		||||
				else:
 | 
			
		||||
					await ctx.author.remove_roles(role,reason=f'/pitch interaction by {ctx.author.display_name}')
 | 
			
		||||
					data[guildStr][timeslot][str(role.id)]['current_players'] -= 1
 | 
			
		||||
					element = pitches[guildStr][timeslot]['entries'][index]
 | 
			
		||||
					gm = await self.client.fetch_user(element['gm'])
 | 
			
		||||
					o = f'_ _\n***{element["game_title"]}*** (GM: {gm.mention})\n```\n'
 | 
			
		||||
					if element['system'] is not None: o = ''.join([o,f'System: {element["system"]}\n'])
 | 
			
		||||
					if element['min_players'] is not None: o = ''.join([o,f'Minimum Players: {str(element["min_players"])}	'])
 | 
			
		||||
					if element['max_players'] is not None: o = ''.join([o,f'Maximum Players: {str(element["max_players"])}\n'])
 | 
			
		||||
					if element['platform'] is not None: o = ''.join([o,f'Platform: {element["platform"]}\n'])
 | 
			
		||||
					o = ''.join([o,f'```'])
 | 
			
		||||
					spaces_remaining = element["max_players"] - element["current_players"]
 | 
			
		||||
					o = ''.join([o,f'~~Spaces Remaining: {str(0)}~~'])if spaces_remaining <= 0 else ''.join([o,f'Spaces Remaining: {str(spaces_remaining)}'])
 | 
			
		||||
					me = await ctx.channel.fetch_message(pitches[guildStr][timeslot]['messages'][index])
 | 
			
		||||
					await me.edit(content=o)
 | 
			
		||||
					await ctx.send(f'You have left the game `{lookup[guildStr][str(role.id)]["game_title"]}`.',hidden=True)
 | 
			
		||||
					tc = discord.utils.find(lambda x: x.id == lookup[guildStr][str(role.id)]['text_channel'],ctx.guild.text_channels)
 | 
			
		||||
					if tc is None:
 | 
			
		||||
						c = discord.utils.find(lambda x: x.id == lookup[guildStr][str(role.id)]['category'],ctx.guild.categories)
 | 
			
		||||
						if c is not None:
 | 
			
		||||
							tPos = len(ctx.guild.channels)
 | 
			
		||||
							for t in c.text_channels:
 | 
			
		||||
								if t.position <= tPos:
 | 
			
		||||
									tc = t
 | 
			
		||||
									tPos = t.position
 | 
			
		||||
					if tc is not None:
 | 
			
		||||
						await tc.send(f'```{ctx.author.display_name} has left the game.```')
 | 
			
		||||
		yaml_dump(data, dataFile)
 | 
			
		||||
		yaml_dump(pitches, pitchesFile)
 | 
			
		||||
 | 
			
		||||
def setup(client):
 | 
			
		||||
	client.add_cog(PitchListener(client))
 | 
			
		||||
		Reference in New Issue
	
	Block a user