geas-bot/app/cogs/slashcommands/secondary/player_commands.py

241 lines
11 KiB
Python

import os # OS Locations
import yaml # YAML parser for Bot config files
import asyncio # Discord Py Dependency
import discord # Main Lib
from discord.ext import commands # Commands module
from discord_slash import SlashCommand, SlashContext, cog_ext, utils # Slash Command Library
from discord_slash.utils.manage_commands import create_choice, create_option, create_permission # Slash Command features
from discord_slash.model import SlashCommandPermissionType
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[str(ctx.guild.id)]['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[str(ctx.guild.id)] if gms[str(ctx.guild.id)][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[guildStr][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 = data[guildStr][t][rStr]['header_message']
tc = discord.utils.find(lambda x: x.id == lookup[guildStr][rStr]['text_channel'],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 = discord.utils.find(lambda x: x.id == categories[guildStr][str(ctx.channel.category.id)], ctx.guild.roles)
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[str(ctx.guild.id)]['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[str(ctx.guild.id)] if gms[str(ctx.guild.id)][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[guildStr][rStr]['time']
if data[guildStr][t][rStr]['current_players'] <= 1: data[guildStr][t][rStr]['current_players'] = None
else: data[guildStr][t][rStr]['current_players'] -= 1
hm = data[guildStr][t][rStr]['header_message']
tc = discord.utils.find(lambda x: x.id == lookup[guildStr][rStr]['text_channel'],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[guildStr][rStr]['time']
if data[guildStr][t][rStr]['current_players'] <= 1: data[guildStr][t][rStr]['current_players'] = None
else: data[guildStr][t][rStr]['current_players'] -= 1
hm = data[guildStr][t][rStr]['header_message']
tc = discord.utils.find(lambda x: x.id == lookup[guildStr][rStr]['text_channel'],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))