forked from viveksantayana/geas-bot
Vivek Santayana
94ce0aa31a
Bug fixes for member signup Added live update of game header message during pitches Documentation updates
239 lines
11 KiB
Python
239 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
|
|
|
|
##### Player Add, Remove, and Leave 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 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, item in enumerate(text):
|
|
if 'Current Players: ' in item:
|
|
text[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 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 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 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 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'] = 0
|
|
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 is not None:
|
|
header = discord.utils.find(lambda x: x.id == hm, p)
|
|
if header is not None:
|
|
text = header.content.split('\n')
|
|
for line, item in enumerate(text):
|
|
if 'Current Players: ' in item:
|
|
text[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 the game you are trying to leave.```', 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: You are not in the game {lookup[guildStr][rStr]["game_title"]}.```',hidden=True)
|
|
return
|
|
if player.id == lookup[guildStr][rStr]['gm']:
|
|
await ctx.send(f'```Error: You are the GM of the game {lookup[guildStr][rStr]["game_title"]} and cannot leave until a new GM is assigned.```',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 is not None:
|
|
header = discord.utils.find(lambda x: x.id == hm, p)
|
|
if header is not None:
|
|
text = header.content.split('\n')
|
|
for line, item in enumerate(text):
|
|
if 'Current Players: ' in item:
|
|
text[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)) |