forked from viveksantayana/geas-bot
Wrote player commands, still not tested.
This commit is contained in:
parent
615e3fa169
commit
ede87e799c
32
TODO.md
32
TODO.md
@ -14,7 +14,8 @@
|
||||
- [ ] ~~'Register Commands' Function~~
|
||||
- [x] Infer Permissions from Config
|
||||
- [x] Dynamic Command Prefixes
|
||||
- [ ] Infer Games from Server Structure
|
||||
- [ ] Infer current games from Server Structure
|
||||
**Create a separate cog to do this instead of having a migrate command, install the cog temporarily and remove the cog once migration is done.**
|
||||
- [ ] Re-enable logging
|
||||
- [x] Delete Dev/Test Functions
|
||||
- [x] Error handlers
|
||||
@ -33,12 +34,13 @@
|
||||
> - [ ] Message Receive Listener
|
||||
> - [ ] Membership Validation Listener
|
||||
- [ ] Re-synchronise commands after any relevant config changes **(see above)**
|
||||
> - [ ] Role Delete (member, admin)
|
||||
> - [ ] Channel delete (notifications, logs)
|
||||
> - [ ] Role Delete (member, admin, game)
|
||||
> - [ ] Channel delete (notifications, logs, game text channel)
|
||||
> - [ ] Category delete (games)
|
||||
- [x] Flag for checking completeness of configuration for a guild.
|
||||
> - [x] Function for checking configs for completeness
|
||||
- [ ] Synchronise roles on game channel updates
|
||||
> - [ ] Exception to event listener to prevent circularity
|
||||
- [ ] Synchronise game channel on role updates
|
||||
> - [ ] Exception to event listener to prevent circularity `unsure what this means`
|
||||
|
||||
## Event Listeners
|
||||
|
||||
@ -60,25 +62,25 @@
|
||||
> - [x] help notifications (notification group)
|
||||
> - [x] signup notifications (notification group)
|
||||
- [x] Set up timeslots
|
||||
- [ ] Delete timeslots
|
||||
- [x] Delete timeslots
|
||||
> - [x] Base command
|
||||
> - [ ] ~~Delete all games with the timeslot~~
|
||||
> - [x] ~~Delete all games with the timeslot~~
|
||||
Do the opposite: block deleting timeslots with existing games.
|
||||
- [x] List timeslots
|
||||
- [ ] Set up command permissions
|
||||
> - [ ] Slash Commands
|
||||
- [x] Set up command permissions
|
||||
> - [x] Slash Commands
|
||||
>> - [x] Admin Commands
|
||||
>> - [ ] Game Management Commands
|
||||
>> - [x] Game Management Commands
|
||||
> - [x] Native Bot Commands
|
||||
- [ ] Migrate existing bot commands
|
||||
> - [x] setupgame
|
||||
> - [x] ~~definebotrole~~ config
|
||||
> - [x] deletegame
|
||||
> - [ ] reset
|
||||
> - [ ] migrate
|
||||
> - [ ] kickplayer
|
||||
> - [ ] addplayer
|
||||
> - [ ] leavegame
|
||||
> - [x] ~~reset~~ purge
|
||||
> - [ ] ~~migrate~~ **See above**
|
||||
> - [x] ~~kickplayer~~ `/player remove`
|
||||
> - [x] ~~addplayer~~ `/player add`
|
||||
> - [x] ~~leavegame~~ `/player leave`
|
||||
> - [ ] Pitch command and sub-commands
|
||||
> > - [ ] run
|
||||
> > - [ ] clear
|
||||
|
@ -267,14 +267,15 @@ loadCogs('events')
|
||||
loadCogs('botcommands')
|
||||
loadCogs('slashcommands')
|
||||
if yaml_load(configFile):
|
||||
if all([len(yaml_load(configFile)[x]['timeslots']) > 0 for x in yaml_load(configFile)]):
|
||||
if any([len(yaml_load(configFile)[x]['timeslots']) > 0 for x in yaml_load(configFile)]):
|
||||
loadCog(f'./{cogsDir}/slashcommands/secondary/manipulate_timeslots.py')
|
||||
if all(['bot' in yaml_load(configFile)[x]['roles'] for x in yaml_load(configFile)]):
|
||||
if any(['bot' in yaml_load(configFile)[x]['roles'] for x in yaml_load(configFile)]):
|
||||
loadCog(f'./{cogsDir}/slashcommands/secondary/game_setup.py')
|
||||
if yaml_load(lookupFile):
|
||||
if all([len(x) > 0 for x in yaml_load(lookupFile).values()]):
|
||||
if any([len(x) > 0 for x in yaml_load(lookupFile).values()]):
|
||||
loadCog(f'./{cogsDir}/slashcommands/secondary/game_management.py')
|
||||
if all([len(yaml_load(configFile)[x]['membership']) > 0 for x in yaml_load(configFile)]):
|
||||
loadCog(f'./{cogsDir}/slashcommands/secondary/player_commands.py')
|
||||
if any([len(yaml_load(configFile)[x]['membership']) > 0 for x in yaml_load(configFile)]):
|
||||
loadCog(f'./{cogsDir}/slashcommands/secondary/edit_membership.py')
|
||||
|
||||
client.run(os.getenv('TEST_3_TOKEN'))
|
@ -18,11 +18,11 @@ class Configuration(commands.Cog, name='Configuration Commands'):
|
||||
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))
|
||||
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',
|
||||
@ -101,19 +101,23 @@ class Configuration(commands.Cog, name='Configuration Commands'):
|
||||
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)
|
||||
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 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 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 Setup') is None:
|
||||
loadCog(f'./{cogsDir}/slashcommands/secondary/game_setup.py')
|
||||
if all([x for x in yaml_load(lookupFile).values()]):
|
||||
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')
|
||||
await self.client.slash.sync_all_commands()
|
||||
flag = True
|
||||
if flag: await self.client.slash.sync_all_commands()
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base='config',
|
||||
@ -181,9 +185,10 @@ class Configuration(commands.Cog, name='Configuration Commands'):
|
||||
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)
|
||||
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)
|
||||
|
||||
@ -224,9 +229,10 @@ class Configuration(commands.Cog, name='Configuration Commands'):
|
||||
)
|
||||
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
|
||||
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)
|
||||
|
||||
@ -260,25 +266,30 @@ class Configuration(commands.Cog, name='Configuration Commands'):
|
||||
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)
|
||||
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.```',hidden=True)
|
||||
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[str(ctx.guild.id)]['timeslots'][sanitisedKey] = name
|
||||
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 all([len(yaml_load(configFile)[x]['timeslots']) > 0 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('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)]):
|
||||
flag = True
|
||||
if any(['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')
|
||||
Flag = True
|
||||
if yaml_load(lookupFile):
|
||||
if all([x for x in yaml_load(lookupFile).values()]):
|
||||
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')
|
||||
await self.client.slash.sync_all_commands()
|
||||
Flag = True
|
||||
if flag: await self.client.slash.sync_all_commands()
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base='config',
|
||||
@ -319,13 +330,14 @@ class Configuration(commands.Cog, name='Configuration Commands'):
|
||||
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)
|
||||
if 'membership' not in conf[str(ctx.guild.id)]:
|
||||
conf[str(ctx.guild.id)]['membership'] = []
|
||||
guildStr = str(ctx.guild.id)
|
||||
if 'membership' not in conf[guildStr]:
|
||||
conf[guildStr]['membership'] = []
|
||||
if role is not None:
|
||||
if role.id in conf[str(ctx.guild.id)]['membership']:
|
||||
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']]):
|
||||
if any([ctx.guild.get_role(m).name == name for m in conf[guildStr]['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:
|
||||
@ -342,13 +354,13 @@ class Configuration(commands.Cog, name='Configuration Commands'):
|
||||
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)
|
||||
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 all([len(yaml_load(configFile)[x]['membership']) > 0 for x in yaml_load(configFile)]):
|
||||
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()
|
||||
await self.client.slash.sync_all_commands()
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
name='test',
|
||||
|
@ -1,18 +0,0 @@
|
||||
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
|
||||
|
||||
from bot import configFile, yaml_load, yaml_dump
|
||||
|
||||
##### Game Management Commands
|
||||
class Game_Management(commands.Cog, name='Game Management Commands'):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Game_Management(client))
|
@ -8,7 +8,7 @@ from discord_slash.utils.manage_commands import create_choice, create_option, cr
|
||||
from discord_slash.model import SlashCommandPermissionType
|
||||
from discord_slash.client import SlashCommand
|
||||
|
||||
from bot import configFile, yaml_load, yaml_dump, reloadCog, cogsDir, unloadCog
|
||||
from bot import configFile, yaml_load, yaml_dump, cogsDir, unloadCog
|
||||
|
||||
#### Separate cog to remove and modify membership registrations that is reloaded if timeslots are added or removed
|
||||
|
||||
@ -20,7 +20,7 @@ class EditMembership(commands.Cog, name='Edit Membership'):
|
||||
#### N.B.: if there are no guilds with any membership types, then this will throw an exception.
|
||||
#### The solution I have implemented is that this will be classed as a 'secondary' cog: it will not be loaded by default, and will only be loaded if at least one guild has a membership role registered.
|
||||
#### If the deletion of membership roles removes memberships from all guilds, it will unload the cog and delete the commands until a new membership role is defined.
|
||||
guild_ids=[int(guildKey) for guildKey in yaml_load(configFile) if len(yaml_load(configFile)[guildKey]['membership']) > 0]
|
||||
guild_ids=[int(guildKey) for guildKey in yaml_load(configFile) if yaml_load(configFile)[guildKey]['membership']]
|
||||
conf = yaml_load(configFile)
|
||||
permissions = {}
|
||||
for guildID in guild_ids:
|
||||
@ -60,7 +60,7 @@ class EditMembership(commands.Cog, name='Edit Membership'):
|
||||
if not any([x['membership'] for x in yaml_load(configFile).values()]):
|
||||
unloadCog(f'./{cogsDir}/slashcommands/secondary/edit_membership.py')
|
||||
await self.client.slash.sync_all_commands()
|
||||
elif len(conf[str(ctx.guild.id)]['membership']) > 0:
|
||||
elif conf[str(ctx.guild.id)]['membership']:
|
||||
output = f'Role `{role.name}` is not a registered membership role in the guild `{ctx.guild.name}`. Please select a valid membership role.\n\n Eligible roles are:\n'
|
||||
for m in conf[str(ctx.guild.id)]['membership']:
|
||||
output = ''.join([output, f'\n{ctx.guild.get_role(m).name}'])
|
||||
@ -83,7 +83,7 @@ class EditMembership(commands.Cog, name='Edit Membership'):
|
||||
conf = yaml_load(configFile)
|
||||
if 'membership' not in conf[str(ctx.guild.id)]:
|
||||
conf[str(ctx.guild.id)]['membership'] = {}
|
||||
if len(conf[str(ctx.guild.id)]['membership']) > 0:
|
||||
if conf[str(ctx.guild.id)]['membership']:
|
||||
output = f'The following membership types have been registered for the guild {ctx.guild.name}:\n'
|
||||
for m in conf[str(ctx.guild.id)]['membership']:
|
||||
output = ''.join([output, f'\n{ctx.guild.get_role(m).name}'])
|
||||
|
@ -11,7 +11,7 @@ from discord_slash.utils.manage_components import create_select, create_select_o
|
||||
|
||||
import re
|
||||
|
||||
from bot import configFile, yaml_load, yaml_dump, reloadCog, cogsDir, unloadCog, dataFile, lookupFile, gmFile, categoriesFile
|
||||
from bot import configFile, yaml_load, yaml_dump, cogsDir, unloadCog, dataFile, lookupFile, gmFile, categoriesFile
|
||||
|
||||
class GameManagement(commands.Cog, name='Game Management'):
|
||||
def __init__(self, client):
|
||||
@ -49,6 +49,7 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
data = yaml_load(dataFile)
|
||||
gms = yaml_load(gmFile)
|
||||
lookup = yaml_load(lookupFile)
|
||||
categories = yaml_load(categoriesFile)
|
||||
guildStr = str(ctx.guild.id)
|
||||
rStr = str(game_role.id)
|
||||
if rStr not in lookup[guildStr]:
|
||||
@ -68,6 +69,7 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
for v in ctx.guild.voice_channels:
|
||||
if v.category == c:
|
||||
await v.delete(reason=f'/game delete command issued by `{ctx.author.display_name}`')
|
||||
del categories[guildStr][c.id]
|
||||
await c.delete(reason=f'/game delete command issued by `{ctx.author.display_name}`')
|
||||
lookup[guildStr].pop(rStr, None)
|
||||
gm_m = await ctx.guild.fetch_member(gm)
|
||||
@ -84,8 +86,10 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
yaml_dump(lookup, lookupFile)
|
||||
yaml_dump(data, dataFile)
|
||||
yaml_dump(gms, gmFile)
|
||||
yaml_dump(categories, categoriesFile)
|
||||
if not any([x for x in yaml_load(lookupFile).values()]):
|
||||
unloadCog(f'./{cogsDir}/slashcommands/secondary/game_management.py')
|
||||
if self.client.get_cog('Player Commands') is not None: unloadCog(f'./{cogsDir}/slashcommands/secondary/player_commands.py')
|
||||
await self.client.slash.sync_all_commands()
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
@ -176,6 +180,7 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
data = yaml_load(dataFile)
|
||||
gms = yaml_load(gmFile)
|
||||
lookup = yaml_load(lookupFile)
|
||||
categories = yaml_load(categoriesFile)
|
||||
guildStr = str(ctx.guild.id)
|
||||
r = game_role
|
||||
rStr = str(r.id)
|
||||
@ -189,7 +194,7 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
data[guildStr][time] = {}
|
||||
# Command Validation Checks
|
||||
if rStr not in lookup[guildStr]:
|
||||
await ctx.send(f'```This is not a valid game role. Please mention a role that is associated with a game.```')
|
||||
await ctx.send(f'```This is not a valid game role. Please mention a role that is associated with a game.```',hidden=True)
|
||||
return
|
||||
if timeslot is not None:
|
||||
if time not in conf[guildStr]['timeslots']:
|
||||
@ -363,14 +368,15 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
'game_title': game_title,
|
||||
'text_channel': t.id
|
||||
}
|
||||
if guildStr not in gms:
|
||||
gms[guildStr] = {}
|
||||
if str(gm.id) not in gms[guildStr]:
|
||||
gms[guildStr][str(gm.id)] = []
|
||||
if guildStr not in gms: gms[guildStr] = {}
|
||||
if str(gm.id) not in gms[guildStr]: gms[guildStr][str(gm.id)] = []
|
||||
gms[guildStr][str(gm.id)].append(r.id)
|
||||
if guildStr not in categories: categories[guildStr] = {}
|
||||
categories[guildStr][str(c.id)] = r.id
|
||||
yaml_dump(data,dataFile)
|
||||
yaml_dump(lookup,lookupFile)
|
||||
yaml_dump(gms,gmFile)
|
||||
yaml_dump(categories, categoriesFile)
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base='game',
|
||||
@ -383,7 +389,7 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
# subcommand_group_description='Adds a time slot available to the channel for games.',
|
||||
guild_ids=guild_ids,
|
||||
)
|
||||
async def _purge(
|
||||
async def _game_purge(
|
||||
self,
|
||||
ctx:SlashContext
|
||||
):
|
||||
@ -401,6 +407,7 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
r = discord.utils.find(lambda x: x.id == g['role'], ctx.guild.roles)
|
||||
for x in c.channels:
|
||||
await x.delete(reason=f'/game purge command issued by `{ctx.author.display_name}`')
|
||||
del categories[guildStr][str(c.id)]
|
||||
await c.delete(reason=f'/game purge command issued by `{ctx.author.display_name}`')
|
||||
await r.delete(reason=f'/game purge command issued by `{ctx.author.display_name}`')
|
||||
gms[guildStr][str(g['gm'])].remove(r.id)
|
||||
@ -478,6 +485,7 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
hidden=True
|
||||
)
|
||||
else:
|
||||
await ctx.channel.trigger_typing()
|
||||
await purgeGames(ctx=ctx, timeslot=timeslot)
|
||||
await ctx.send(
|
||||
content = f'```All games for time slot `{conf[guildStr]["timeslots"][timeslot]}` have been purged.```',
|
||||
@ -487,6 +495,10 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
yaml_dump(lookup,lookupFile)
|
||||
yaml_dump(data,dataFile)
|
||||
yaml_dump(categories,categoriesFile)
|
||||
if not any([x for x in yaml_load(lookupFile).values()]):
|
||||
unloadCog(f'./{cogsDir}/slashcommands/secondary/game_management.py')
|
||||
if self.client.get_cog('Player Commands') is not None: unloadCog(f'./{cogsDir}/slashcommands/secondary/player_commands.py')
|
||||
await self.client.slash.sync_all_commands()
|
||||
|
||||
|
||||
def setup(client):
|
||||
|
@ -10,7 +10,7 @@ from discord_slash.client import SlashCommand
|
||||
import typing
|
||||
import re
|
||||
|
||||
from bot import configFile, yaml_load, yaml_dump, reloadCog, cogsDir, unloadCog, dataFile, lookupFile, gmFile, loadCog
|
||||
from bot import configFile, yaml_load, yaml_dump, cogsDir, unloadCog, dataFile, lookupFile, gmFile, loadCog, categoriesFile
|
||||
|
||||
#### Game Role and Channel Setup Command
|
||||
|
||||
@ -20,7 +20,7 @@ class GameSetup(commands.Cog, name='Game Setup'):
|
||||
|
||||
conf=yaml_load(configFile)
|
||||
permissions={}
|
||||
guild_ids = list(set.union(set([int(guildKey) for guildKey in yaml_load(configFile) if len(yaml_load(configFile)[guildKey]['timeslots']) > 0]),set([int(guildKey) for guildKey in yaml_load(configFile) if type(yaml_load(configFile)[guildKey]['roles']['bot']) is int])))
|
||||
guild_ids = list(set.intersection(set([int(guildKey) for guildKey in yaml_load(configFile) if yaml_load(configFile)[guildKey]['timeslots']]),set([int(guildKey) for guildKey in yaml_load(configFile) if 'bot' in yaml_load(configFile)[guildKey]['roles'] and type(yaml_load(configFile)[guildKey]['roles']['bot']) is int])))
|
||||
for guildID in guild_ids:
|
||||
permissions[guildID] = []
|
||||
permissions[guildID].append(create_permission(id=conf[str(guildID)]['owner'],id_type=SlashCommandPermissionType.USER,permission=True))
|
||||
@ -109,6 +109,7 @@ class GameSetup(commands.Cog, name='Game Setup'):
|
||||
data = yaml_load(dataFile)
|
||||
gms = yaml_load(gmFile)
|
||||
lookup = yaml_load(lookupFile)
|
||||
categories = yaml_load(categoriesFile)
|
||||
guildStr = str(ctx.guild.id)
|
||||
time = re.sub(r"\W+",'', timeslot[:9].lower())
|
||||
if 'roles' not in conf[guildStr]:
|
||||
@ -274,19 +275,26 @@ class GameSetup(commands.Cog, name='Game Setup'):
|
||||
'game_title': game_title,
|
||||
'text_channel': t.id
|
||||
}
|
||||
if guildStr not in gms:
|
||||
gms[guildStr] = {}
|
||||
if str(gm.id) not in gms[guildStr]:
|
||||
gms[guildStr][str(gm.id)] = []
|
||||
if guildStr not in gms: gms[guildStr] = {}
|
||||
if str(gm.id) not in gms[guildStr]: gms[guildStr][str(gm.id)] = []
|
||||
if str(guildStr) not in categories: categories[guildStr] = {}
|
||||
gms[guildStr][str(gm.id)].append(r.id)
|
||||
if guildStr not in categories: categories[guildStr] = {}
|
||||
categores[guildStr][str(c.id)] = r.id
|
||||
yaml_dump(data,dataFile)
|
||||
yaml_dump(lookup,lookupFile)
|
||||
yaml_dump(gms,gmFile)
|
||||
if all([x for x in yaml_load(lookupFile).values()]):
|
||||
yaml_dump(categories,categoriesFile)
|
||||
# Enable the Game Management and Player commands
|
||||
if any([x for x in yaml_load(lookupFile).values()]):
|
||||
flag = False
|
||||
if self.client.get_cog('Game Management') is None:
|
||||
loadCog(f'./{cogsDir}/slashcommands/secondary/game_management.py')
|
||||
await self.client.slash.sync_all_commands()
|
||||
# Enable the Game Management commands
|
||||
flag = True
|
||||
if self.client.get_cog('Player Commands') is None:
|
||||
loadCog(f'./{cogsDir}/slashcommands/secondary/player_commands.py')
|
||||
flag = True
|
||||
if flag: await self.client.slash.sync_all_commands()
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(GameSetup(client))
|
@ -22,7 +22,7 @@ class ManipulateTimeslots(commands.Cog, name='Manipulate Timeslots'):
|
||||
#### N.B.: if there are no guilds with any timeslots, then this will throw an exception.
|
||||
#### The solution I have implemented is that this will be classed as a 'secondary' cog: it will not be loaded by default, and will only be loaded if at least one guild has a timeslot configured.
|
||||
#### If the deletion of timeslots removes timeslots from all guilds, it will unload the cog and delete the commands until a new timeslot is defined.
|
||||
guild_ids=[int(guildKey) for guildKey in yaml_load(configFile) if len(yaml_load(configFile)[guildKey]['timeslots']) > 0]
|
||||
guild_ids=[int(guildKey) for guildKey in yaml_load(configFile) if yaml_load(configFile)[guildKey]['timeslots']]
|
||||
conf = yaml_load(configFile)
|
||||
permissions = {}
|
||||
for guildID in guild_ids:
|
||||
@ -89,7 +89,7 @@ class ManipulateTimeslots(commands.Cog, name='Manipulate Timeslots'):
|
||||
await ctx.send(f'```Timeslot {conf[guildStr]["timeslots"][timeslot]} with the key `{timeslot}` has been deleted for the guild `{ctx.guild.name}`.```',hidden=True)
|
||||
conf[guildStr]['timeslots'].pop(timeslot, None)
|
||||
yaml_dump(conf, configFile)
|
||||
if not all([x['timeslots'] for x in yaml_load(configFile).values()]):
|
||||
if not any([x['timeslots'] for x in yaml_load(configFile).values()]):
|
||||
unloadCog(f'./{cogsDir}/slashcommands/secondary/manipulate_timeslots.py')
|
||||
if self.client.get_cog('Game Management') is not None:
|
||||
unloadCog(f'./{cogsDir}/slashcommands/secondary/game_management.py')
|
||||
@ -133,7 +133,7 @@ class ManipulateTimeslots(commands.Cog, name='Manipulate Timeslots'):
|
||||
await ctx.send(f'```Timeslot {conf[guildStr]["timeslots"][key]} with the key `{key}` has been renamed to {name} for the guild `{ctx.guild.name}`.```',hidden=True)
|
||||
conf[guildStr]['timeslots'][key] = name
|
||||
yaml_dump(conf, configFile)
|
||||
elif len(conf[guildStr]['timeslots']) > 0:
|
||||
elif conf[guildStr]['timeslots']:
|
||||
output = f'```Timeslot `{key}` was not found in the guild `{ctx.guild.name}`. Please enter a valid key.\n\n Available timeslots are:\n(key): (timeslot name)'
|
||||
for c in conf[guildStr]['timeslots']:
|
||||
output = ''.join([output, f'\n {c}: {conf[guildStr]["timeslots"][c]}'])
|
||||
@ -157,7 +157,7 @@ class ManipulateTimeslots(commands.Cog, name='Manipulate Timeslots'):
|
||||
guildStr = str(ctx.guild.id)
|
||||
if 'timeslots' not in conf[guildStr]:
|
||||
conf[guildStr]['timeslots'] = {}
|
||||
if len(conf[guildStr]['timeslots']) > 0:
|
||||
if conf[guildStr]['timeslots']:
|
||||
output = f'```The following timeslots have been configured for the guild {ctx.guild.name}:\n(key): (timeslot name)'
|
||||
for c in conf[guildStr]['timeslots']:
|
||||
output = ''.join([output, f'\n {c}: {conf[guildStr]["timeslots"][c]}'])
|
||||
|
241
app/cogs/slashcommands/secondary/player_commands.py
Normal file
241
app/cogs/slashcommands/secondary/player_commands.py
Normal file
@ -0,0 +1,241 @@
|
||||
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
|
||||
|
||||
from bot import configFile, yaml_load, yaml_dump, lookupFile, dataFile, gmFile, categoriesFile
|
||||
|
||||
##### Game Management Commands
|
||||
class PlayerCommands(commands.Cog, name='Player Commands'):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
conf = yaml_load(configFile)
|
||||
lookup = yaml_load(lookupFile)
|
||||
data = yaml_load(dataFile)
|
||||
gms = yaml_load(gmFile)
|
||||
categories = yaml_load(categoriesFile)
|
||||
guild_ids= [ int(x) for x in list(lookup)]
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base='player',
|
||||
name='add',
|
||||
description='Add a player to a game.',
|
||||
base_description='Commands to manage players in a game.',
|
||||
base_default_permission=True,
|
||||
guild_ids = guild_ids,
|
||||
options = [
|
||||
create_option(
|
||||
name='player',
|
||||
description='The player you want to add to the game.',
|
||||
option_type=6,
|
||||
required=True
|
||||
),
|
||||
create_option(
|
||||
name='game',
|
||||
description='The role of the game you want to add the player to.',
|
||||
option_type=8,
|
||||
required=True
|
||||
)
|
||||
]
|
||||
)
|
||||
async def _player_add(
|
||||
self,
|
||||
ctx:SlashContext,
|
||||
player:discord.User,
|
||||
game:discord.Role
|
||||
):
|
||||
await ctx.channel.trigger_typing()
|
||||
conf = yaml_load(configFile)
|
||||
lookup = yaml_load(lookupFile)
|
||||
data = yaml_load(dataFile)
|
||||
gms = yaml_load(gmFile)
|
||||
guildStr = str(ctx.guild.id)
|
||||
rStr = str(game.id)
|
||||
if rStr not in lookup[guildStr]:
|
||||
await ctx.send(f'```Error: This is not a valid game role. Please mention a role that is associated with a game.```',hidden=True)
|
||||
return
|
||||
if not (set(ctx.author.roles) & set([ctx.guild.get_role(x) for x in conf[guildStr]['roles']['admin']]) or ctx.author == ctx.guild.owner):
|
||||
if not set(ctx.author.roles) & set([ctx.guild.get_role(int(x)) for x in gms[guildStr] if gms[guildStr][x]]):
|
||||
await ctx.send(f'```Error: You are not authorised to issue this command. The command may only be issued by an administrator or by a GM.```',hidden=True)
|
||||
return
|
||||
if ctx.author.id != lookup[guildStr][rStr]['gm']:
|
||||
await ctx.send(f'```Error: You are not authorised to issue this command. A player may only be added to a game by the GM or by an administrator.```',hidden=True)
|
||||
return
|
||||
if game in player.roles:
|
||||
await ctx.send(f'```Error: Player `{player.display_name}` is already in the game {lookup[guildStr][rStr]["game_title"]}.```',hidden=True)
|
||||
return
|
||||
await player.add_roles(game, reason=f'`/player add` command issued by {ctx.author.display_name}`.')
|
||||
t = lookup[rStr]['time']
|
||||
if type(data[guildStr][t][rStr]['current_players']) is not int: data[guildStr][t][rStr]['current_players'] = 1
|
||||
else: data[guildStr][t][rStr]['current_players'] += 1
|
||||
hm = lookup[rStr]['header_message']
|
||||
tc = discord.utils.find(lambda x: x.id == lookup[rStr]['text_message'],ctx.guild.channels)
|
||||
if tc is not None:
|
||||
p = await tc.pins()
|
||||
if p:
|
||||
header = discord.utils.find(lambda x: x.id == hm, p)
|
||||
if header is not None:
|
||||
text = header.content.split('\n')
|
||||
for line in text:
|
||||
if 'Current Players: ' in line:
|
||||
line = f'Current Players: {str(data[guildStr][t][rStr]["current_players"])}'
|
||||
break
|
||||
await header.edit(content='\n'.join(text))
|
||||
else:
|
||||
tPos = len(ctx.guild.channels)
|
||||
cat = discord.utils.find(lambda x: x.id==lookup[guildStr][rStr]['category'], ctx.guild.categories)
|
||||
if cat is not None:
|
||||
for t in cat.text_channels:
|
||||
if t.position <= tPos:
|
||||
tc = t
|
||||
tPos = t.position
|
||||
await tc.send(f'```Player {player.display_name} has been added to the game by `{ctx.author.display_name}`.```\n{player.mention} | {game.mention}')
|
||||
if 'mod' in conf[guildStr]['channels'] and 'committee' in conf[guildStr]['roles']:
|
||||
c = discord.utils.find(lambda x: x.id == conf[guildStr]['channels']['mod'], ctx.guild.channels)
|
||||
r = discord.utils.find(lambda x: x.id == conf[guildStr]['roles']['committee'], ctx.guild.roles)
|
||||
await c.send(f'```Player `{player.display_name}` has been added to the game `{lookup[guildStr][rStr]["game_title"]}` by `{ctx.author.display_name}` via the `/player add` command.```')
|
||||
yaml_dump(data,dataFile)
|
||||
await ctx.send(content=f'```Player `{player.display_name}` has been added to the game `{lookup[guildStr][rStr]["game_title"]}`.```', hidden=True)
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base='player',
|
||||
name='remove',
|
||||
description='Remove a player from a game.',
|
||||
# base_description='Commands to manage players in a game.',
|
||||
base_default_permission=True,
|
||||
guild_ids = guild_ids,
|
||||
options = [
|
||||
create_option(
|
||||
name='player',
|
||||
description='The player you want to remove from the game.',
|
||||
option_type=6,
|
||||
required=True
|
||||
)
|
||||
]
|
||||
)
|
||||
async def _player_remove(
|
||||
self,
|
||||
ctx:SlashContext,
|
||||
player:discord.User
|
||||
):
|
||||
await ctx.channel.trigger_typing()
|
||||
conf = yaml_load(configFile)
|
||||
lookup = yaml_load(lookupFile)
|
||||
data = yaml_load(dataFile)
|
||||
gms = yaml_load(gmFile)
|
||||
categories = yaml_load(categoriesFile)
|
||||
guildStr = str(ctx.guild.id)
|
||||
if str(ctx.channel.category.id) not in categories[guildStr]:
|
||||
await ctx.send(f'```Error: This command can only be issued in a text channel associated with a game.```', hidden=True)
|
||||
return
|
||||
game = categories[guildStr][str(ctx.channel.category.id)]
|
||||
rStr = str(game.id)
|
||||
if game not in player.roles:
|
||||
await ctx.send(f'```Error: Player `{player.display_name}` is not in the game {lookup[guildStr][rStr]["game_title"]}.```',hidden=True)
|
||||
return
|
||||
if not (set(ctx.author.roles) & set([ctx.guild.get_role(x) for x in conf[guildStr]['roles']['admin']]) or ctx.author == ctx.guild.owner):
|
||||
if not set(ctx.author.roles) & set([ctx.guild.get_role(int(x)) for x in gms[guildStr] if gms[guildStr][x]]):
|
||||
await ctx.send(f'```Error: You are not authorised to issue this command. The command may only be issued by an administrator or by a GM.```',hidden=True)
|
||||
return
|
||||
if ctx.author.id != lookup[guildStr][rStr]['gm']:
|
||||
await ctx.send(f'```Error: You are not authorised to issue this command. A player may only be added to a game by the GM or by an administrator.```',hidden=True)
|
||||
return
|
||||
await player.remove_roles(game, reason=f'`/player remove` command issued by {ctx.author.display_name}`.')
|
||||
t = lookup[rStr]['time']
|
||||
if type(data[guildStr][t][rStr]['current_players']) <= 1: data[guildStr][t][rStr]['current_players'] = None
|
||||
else: data[guildStr][t][rStr]['current_players'] -= 1
|
||||
hm = lookup[rStr]['header_message']
|
||||
tc = discord.utils.find(lambda x: x.id == lookup[rStr]['text_message'],ctx.guild.channels)
|
||||
if tc is not None:
|
||||
p = await tc.pins()
|
||||
if p:
|
||||
header = discord.utils.find(lambda x: x.id == hm, p)
|
||||
if header is not None:
|
||||
text = header.content.split('\n')
|
||||
for line in text:
|
||||
if 'Current Players: ' in line:
|
||||
line = f'Current Players: {str(data[guildStr][t][rStr]["current_players"]) if data[guildStr][t][rStr]["current_players"] is not None else str(0)}'
|
||||
break
|
||||
await header.edit(content='\n'.join(text))
|
||||
else:
|
||||
tPos = len(ctx.guild.channels)
|
||||
cat = ctx.channel.category
|
||||
for t in cat.text_channels:
|
||||
if t.position <= tPos:
|
||||
tc = t
|
||||
tPos = t.position
|
||||
await tc.send(f'```Player {player.display_name} has been removed from the game by `{ctx.author.display_name}`.```\n{game.mention}')
|
||||
if 'mod' in conf[guildStr]['channels'] and 'committee' in conf[guildStr]['roles']:
|
||||
c = discord.utils.find(lambda x: x.id == conf[guildStr]['channels']['mod'], ctx.guild.channels)
|
||||
r = discord.utils.find(lambda x: x.id == conf[guildStr]['roles']['committee'], ctx.guild.roles)
|
||||
await c.send(f'```Player `{player.display_name}` has been removed from the game `{lookup[guildStr][rStr]["game_title"]}` by `{ctx.author.display_name}` via the `/player remove` command.```')
|
||||
yaml_dump(data,dataFile)
|
||||
await ctx.send(content=f'```Player `{player.display_name}` has been removed from the game `{lookup[guildStr][rStr]["game_title"]}`.```', hidden=True)
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base='player',
|
||||
name='leave',
|
||||
description='Leave a game.',
|
||||
# base_description='Commands to manage players in a game.',
|
||||
base_default_permission=True,
|
||||
guild_ids = guild_ids
|
||||
)
|
||||
async def _player_leave(
|
||||
self,
|
||||
ctx:SlashContext
|
||||
):
|
||||
await ctx.channel.trigger_typing()
|
||||
conf = yaml_load(configFile)
|
||||
lookup = yaml_load(lookupFile)
|
||||
data = yaml_load(dataFile)
|
||||
gms = yaml_load(gmFile)
|
||||
categories = yaml_load(categoriesFile)
|
||||
guildStr = str(ctx.guild.id)
|
||||
player = ctx.author
|
||||
if str(ctx.channel.category.id) not in categories[guildStr]:
|
||||
await ctx.send(f'```Error: This command can only be issued in a text channel associated with a game.```', hidden=True)
|
||||
return
|
||||
game = categories[guildStr][str(ctx.channel.category.id)]
|
||||
rStr = str(game.id)
|
||||
if game not in player.roles:
|
||||
await ctx.send(f'```Error: Player `{player.display_name}` is not in the game {lookup[guildStr][rStr]["game_title"]}.```',hidden=True)
|
||||
return
|
||||
await player.remove_roles(game, reason=f'`/player leave` command issued by {ctx.author.display_name}`.')
|
||||
t = lookup[rStr]['time']
|
||||
if type(data[guildStr][t][rStr]['current_players']) <= 1: data[guildStr][t][rStr]['current_players'] = None
|
||||
else: data[guildStr][t][rStr]['current_players'] -= 1
|
||||
hm = lookup[rStr]['header_message']
|
||||
tc = discord.utils.find(lambda x: x.id == lookup[rStr]['text_message'],ctx.guild.channels)
|
||||
if tc is not None:
|
||||
p = await tc.pins()
|
||||
if p:
|
||||
header = discord.utils.find(lambda x: x.id == hm, p)
|
||||
if header is not None:
|
||||
text = header.content.split('\n')
|
||||
for line in text:
|
||||
if 'Current Players: ' in line:
|
||||
line = f'Current Players: {str(data[guildStr][t][rStr]["current_players"]) if data[guildStr][t][rStr]["current_players"] is not None else str(0)}'
|
||||
break
|
||||
await header.edit(content='\n'.join(text))
|
||||
else:
|
||||
tPos = len(ctx.guild.channels)
|
||||
cat = ctx.channel.category
|
||||
for t in cat.text_channels:
|
||||
if t.position <= tPos:
|
||||
tc = t
|
||||
tPos = t.position
|
||||
await tc.send(f'```Player {player.display_name} has left the game.```\n{game.mention}')
|
||||
if 'mod' in conf[guildStr]['channels'] and 'committee' in conf[guildStr]['roles']:
|
||||
c = discord.utils.find(lambda x: x.id == conf[guildStr]['channels']['mod'], ctx.guild.channels)
|
||||
r = discord.utils.find(lambda x: x.id == conf[guildStr]['roles']['committee'], ctx.guild.roles)
|
||||
await c.send(f'```Player `{player.display_name}` has left the game `{lookup[guildStr][rStr]["game_title"]}` via the `/player leave` command.```')
|
||||
yaml_dump(data,dataFile)
|
||||
await ctx.send(content=f'```You have left the game `{lookup[guildStr][rStr]["game_title"]}`.```', hidden=True)
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(PlayerCommands(client))
|
@ -1 +1,2 @@
|
||||
{}
|
||||
'864651943820525609':
|
||||
'866788661026488352': 866788659839238164
|
||||
|
Loading…
Reference in New Issue
Block a user