Updated bot.
Bugfix: player count on GM leaving Added /tcard command with audio Updated debug commands
This commit is contained in:
BIN
app/assets/tcard.wav
Normal file
BIN
app/assets/tcard.wav
Normal file
Binary file not shown.
@ -1,58 +0,0 @@
|
||||
import os
|
||||
from dotenv import load_dotenv # Import OS variables from Dotenv file.
|
||||
load_dotenv() # Load Dotenv. Delete this for production
|
||||
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
|
||||
from deepdiff import DeepDiff
|
||||
from pprint import pprint
|
||||
|
||||
from bot import loadCog, unloadCog, cogsDir, checkConfig, parseConfigCheck, yaml_load, configFile
|
||||
|
||||
##### Control Cog
|
||||
class Control(commands.Cog, name='Cog Control Commands'):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
#### Check if user is an administrator
|
||||
async def cog_check(self, ctx:commands.Context):
|
||||
for role in ctx.author.roles:
|
||||
if role.permissions.administrator:
|
||||
return True
|
||||
return ctx.author.guild_permissions.administrator
|
||||
|
||||
@commands.command(
|
||||
name='debug',
|
||||
description='Toggles debug feature for the guild. Enter either `on` or `off`.',
|
||||
brief='Toggle debug features.'
|
||||
)
|
||||
async def _debug(self, ctx:commands.Context, toggle:str):
|
||||
if toggle.lower() == 'on':
|
||||
loadCog(f'./debug/debug.py')
|
||||
await ctx.reply(f'```Debug commands enabled. Use them carefully.```')
|
||||
elif toggle.lower() == 'off':
|
||||
unloadCog(f'./debug/debug.py')
|
||||
await ctx.reply(f'```Debug commands disabled.```')
|
||||
else:
|
||||
raise commands.CommandError(message='Invalid argument.')
|
||||
# await ctx.reply(f'```Invalid argument.```')
|
||||
|
||||
@commands.command(
|
||||
name='testconfig',
|
||||
description='Tests the completeness of the configuration values of the current guild by comparing it to a configuration blueprint.',
|
||||
brief='Tests config values for current guild.',
|
||||
aliases=['configtest']
|
||||
)
|
||||
async def _testconfig(self, ctx:commands.Context):
|
||||
checkConfig(ctx.guild)
|
||||
status, output = checkConfig(ctx.guild)
|
||||
conf = yaml_load(configFile)
|
||||
if not status:
|
||||
await ctx.reply(f"```The Bot's configurations are incomplete for the guild {ctx.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.```")
|
||||
elif status:
|
||||
await ctx.reply(f"```The Bot's configurations for the guild {ctx.guild.name} are in order. The Bot is ready to interact with the guild.```")
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Control(client))
|
@ -8,7 +8,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 pprint import pprint
|
||||
|
||||
from bot import clearConfig, configFile, loadCog, loadCogs, setConfig, unloadCog, unloadCogs, yaml_dump, yaml_load, reloadCog, reloadCogs, pitchesFile, cogsDir
|
||||
from bot import clearConfig, configFile, checkConfig, loadCog, loadCogs, setConfig, unloadCog, unloadCogs, yaml_dump, yaml_load, reloadCog, reloadCogs, pitchesFile, cogsDir, parseConfigCheck
|
||||
|
||||
##### Debug Cog
|
||||
class Debug(commands.Cog, name='Debug Commands'):
|
||||
@ -16,9 +16,32 @@ class Debug(commands.Cog, name='Debug Commands'):
|
||||
self.client = client
|
||||
|
||||
#### Permission Check: Only available to the bot's maintainer.
|
||||
|
||||
async def cog_check(self, ctx:commands.Context):
|
||||
conf = yaml_load(configFile)
|
||||
for role in ctx.author.roles:
|
||||
if 'maintainer' in conf[str(ctx.guild.id)]['roles']:
|
||||
if role.id == conf[str(ctx.guild.id)]['roles']['maintainer']: return True
|
||||
return ctx.author.id == ctx.guild.owner_id
|
||||
|
||||
async def cog_check(self, ctx):
|
||||
return ctx.author.id == int(os.getenv('BOT_MAINTAINER_ID'))
|
||||
|
||||
@commands.command(
|
||||
name='testconfig',
|
||||
description='Tests the completeness of the configuration values of the current guild by comparing it to a configuration blueprint.',
|
||||
brief='Tests config values for current guild.',
|
||||
aliases=['configtest']
|
||||
)
|
||||
async def _testconfig(self, ctx:commands.Context):
|
||||
checkConfig(ctx.guild)
|
||||
status, output = checkConfig(ctx.guild)
|
||||
conf = yaml_load(configFile)
|
||||
if not status:
|
||||
await ctx.reply(f"```The Bot's configurations are incomplete for the guild {ctx.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.```")
|
||||
elif status:
|
||||
await ctx.reply(f"```The Bot's configurations for the guild {ctx.guild.name} are in order. The Bot is ready to interact with the guild.```")
|
||||
|
||||
@commands.command(
|
||||
name='reloadcogs',
|
||||
description='Reloads cogs within the specified category, or provide `all` for all cogs. Default: `all`.',
|
@ -71,8 +71,9 @@ class PitchListener(commands.Cog, name='Pitch Listener'):
|
||||
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
|
||||
if ctx.author.id != lookup[guildStr][str(role.id)]['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"])} '])
|
||||
@ -131,8 +132,10 @@ class PitchListener(commands.Cog, name='Pitch Listener'):
|
||||
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]
|
||||
if ctx.author.id != lookup[guildStr][str(role.id)]['gm']:
|
||||
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'])
|
||||
|
@ -59,6 +59,10 @@ class Configuration(commands.Cog, name='Configuration Commands'):
|
||||
create_choice(
|
||||
name='`Student` role',
|
||||
value='student'
|
||||
),
|
||||
create_choice(
|
||||
name='`Bot Maintainer` role',
|
||||
value='maintainer'
|
||||
)
|
||||
]
|
||||
),
|
||||
|
@ -345,7 +345,7 @@ class GameManagement(commands.Cog, name='Game Management'):
|
||||
|
||||
result = ''.join(['```',result,f"The game has been configured with space for {max_players} players (with {current_players if current_players else '0'} currently occupied).",'```'])
|
||||
|
||||
output = f'```Hello {gm.display_name}! Your game channels for `{game_title}` has been updated.\nYou can ping your players or edit the game settings by interacting with the game role through the Bot commands. Have fun!```\n'
|
||||
output = f'```Hello {gm.display_name}! Your game channels for `{game_title}` have been updated.\nYou can ping your players or edit the game settings by interacting with the game role through the Bot commands. Have fun!```\n'
|
||||
output = ''.join([output,f'```Game Title: {game_title}\n'])
|
||||
output = ''.join([output,f'GM: {gm.display_name}\n'])
|
||||
output = ''.join([output,f'Time: {conf[guildStr]["timeslots"][time]}\n'])
|
||||
|
@ -200,6 +200,9 @@ class PlayerCommands(commands.Cog, name='Player Commands'):
|
||||
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
|
||||
|
84
app/cogs/slashcommands/secondary/tcard.py
Normal file
84
app/cogs/slashcommands/secondary/tcard.py
Normal file
@ -0,0 +1,84 @@
|
||||
import os # OS Locations
|
||||
import yaml # YAML parser for Bot config files
|
||||
import asyncio # Discord Py Dependency
|
||||
import discord # Main Lib
|
||||
from datetime import datetime
|
||||
import time
|
||||
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
|
||||
|
||||
#### T Card Command
|
||||
|
||||
class TCardCommand(commands.Cog, name='T-Card Command'):
|
||||
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_slash(
|
||||
name='tcard',
|
||||
description='Invokes a T-Card in the current game.',
|
||||
default_permission=True,
|
||||
guild_ids=guild_ids,
|
||||
)
|
||||
async def _tcard(self, ctx:SlashContext):
|
||||
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)
|
||||
# rStr = str(game.id)
|
||||
embed = discord.Embed(
|
||||
title='T-Card',
|
||||
description='A T-Card Has Been Played',
|
||||
colour=discord.Color.dark_red,
|
||||
)
|
||||
embed.set_footer(text=datetime.now().strftime('%a %-d %b %y, %-I:%M %p'))
|
||||
embed.set_image(url='http://geas.org.uk/wp-content/uploads/2020/08/tcard-1-e1597167776966.png')
|
||||
|
||||
"""If this was called in a game channel"""
|
||||
if str(ctx.channel.category.id) in categories[guildStr]:
|
||||
|
||||
"""Send a T-Card graphic to the channel, tagging the role."""
|
||||
role = ctx.guild.get_role(categories[guildStr][str(ctx.channel.category.id)])
|
||||
await ctx.channel.send(f'{role.mention}', embed=embed)
|
||||
|
||||
if ctx.author_id == lookup[guildStr][str(role.id)]["gm"]:
|
||||
|
||||
"""Behaviour for when the GM issues T-Card command."""
|
||||
await ctx.send(content=f'```You have invoked the T-Card in the game {lookup[guildStr][str(role.id)]["game_title"]} as the GM.```', hidden=True)
|
||||
else:
|
||||
"""Default behaviour for when someone who is not the GM issues the command."""
|
||||
|
||||
"""Privately message the GM."""
|
||||
gm = await ctx.guild.fetch_member(lookup[guildStr][str(role.id)]["gm"])
|
||||
await gm.send(f'**Important**\n```Player {ctx.author.display_name} has invoked a T-Card in your game {lookup[guildStr][str(role.id)]["game_title"]}. Please check in with them and make sure everything is okay. If you need any further help, please feel free to contact a member of the Committee.```')
|
||||
|
||||
"""Notify the issuer of the command privately via hidden reply."""
|
||||
await ctx.send(content=f'```You have invoked the T-Card in the game {lookup[guildStr][str(role.id)]["game_title"]}. The GM has been notified privately.```', hidden=True)
|
||||
|
||||
"""Do the audio thing."""
|
||||
for vc in ctx.channel.category.voice_channels:
|
||||
v = await vc.connect()
|
||||
tcardaudio = discord.PCMAudio(open("./assets/tcard.wav", "rb"))
|
||||
v.play(tcardaudio)
|
||||
while v.is_playing():
|
||||
time.sleep(1)
|
||||
await v.disconnect()
|
||||
else:
|
||||
"""Send a T-Card to the immediate channel if this is a generic channel."""
|
||||
await ctx.channel.send(embed=embed)
|
||||
await ctx.send(content=f'```You have invoked the T-Card in the channel {ctx.channel.name}.```', hidden=True)
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(TCardCommand(client))
|
Reference in New Issue
Block a user