Skip to content

Commit

Permalink
Merge pull request #21 from ClanBadJas/dev
Browse files Browse the repository at this point in the history
Merge Dev to Master for version 2.0
  • Loading branch information
MattsBos authored Sep 3, 2022
2 parents 64d6273 + 05083d9 commit 3196253
Show file tree
Hide file tree
Showing 9 changed files with 599 additions and 408 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ clanbotjas/data/menu.json
.env
clanbotjas/__pycache__/*.pyc
clanbotjas/cogs/__pycache__/*.pyc
clanbotjas/.vscode/launch.json
86 changes: 86 additions & 0 deletions clanbotjas/cogManagerMixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import functools

import discord

import settings


class LogSelect(discord.ui.Select):
valueToLabel = {}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for option in self.options:
self.valueToLabel[option.value] = option.label

async def callback(self, interaction: discord.Interaction):
logChannel = interaction.client.get_channel(settings.DISCORD_LOG_CHANNEL)
opts = ", ".join([self.valueToLabel[value] for value in self.values])

await logChannel.send(
f":ballot_box_with_check: Options selected | {interaction.channel.mention} | {interaction.user} selected: ({opts})."
)


class LogButton(discord.ui.Button):
async def callback(self, interaction: discord.Interaction):
logChannel = interaction.client.get_channel(settings.DISCORD_LOG_CHANNEL)
await logChannel.send(
f":radio_button: Button clicked | {interaction.channel.mention} | {interaction.user} clicked ({self.label})."
)


def commandlogger(func):
"""
Decorator that allows slash commands to be logged
:param func: original function
:return: wrapped function
"""

def slashCommand(ctx, kwargs):
log_string = ":arrow_forward: SlashCommand: "
log_string += (
ctx.channel.mention
if isinstance(ctx.channel, discord.TextChannel)
else "????"
)
log_string += f" | {ctx.author}: /{ctx.command} "

for k, v in kwargs.items():
log_string += f" {k}: {v}"
return log_string

def messageCommand(ctx):
log_string = ":arrow_forward: MessageCommand: "
log_string += (
ctx.channel.mention
if isinstance(ctx.channel, discord.TextChannel)
else "????"
)
log_string += f' | {ctx.author}: "{ctx.command}"'
return log_string

def otherCommand(ctx):
log_string = ":arrow_forward: OtherCommand: "
log_string += (
ctx.channel.mention
if isinstance(ctx.channel, discord.TextChannel)
else "????"
)
log_string += f' | {ctx.author}: "{ctx.command}"'
return log_string

@functools.wraps(func)
async def wrapped(self, ctx, *args, **kwargs):
# Some fancy foo stuff
await func(self, ctx, *args, **kwargs)
if isinstance(ctx.command, discord.MessageCommand):
msg = messageCommand(ctx)
elif isinstance(ctx.command, (discord.SlashCommand, discord.SlashCommandGroup)):
msg = slashCommand(ctx, kwargs)
else:
msg = otherCommand(ctx)
logChannel = self.client.get_channel(settings.DISCORD_LOG_CHANNEL)
await logChannel.send(msg)

return wrapped
283 changes: 145 additions & 138 deletions clanbotjas/cogmanager.py
Original file line number Diff line number Diff line change
@@ -1,148 +1,155 @@
import functools
from dotenv import load_dotenv

import discord
from discord.ext import commands
from discord import option, Permissions
from discord import option

import settings


async def logCommand(channel, ctx, *args, **kwargs):
log_string = ":arrow_forward: Command: "
log_string += ctx.channel.mention if isinstance(ctx.channel, discord.TextChannel) else "????"
log_string += f" | {ctx.author}: /{ctx.command} "

for k, v in kwargs.items():
log_string += f" {k}: {v}"
await channel.send(log_string)


client = commands.Bot(command_prefix=commands.when_mentioned_or("!"), intents=settings.INTENTS)
@client.event
async def on_command_error(ctx: commands.Context, error: commands.CommandError):
"""
Give feedback to the user when user has no perms to use the command
:param ctx: Original command context
:param error: Error
:return:
"""

if isinstance(error, commands.errors.MissingRole):
await ctx.response.send_message(f"{ctx.author.mention}, You do not have permissions to use that command.", ephemeral=True)
else:
raise error

@client.event
async def on_application_command_error(ctx: commands.Context, error: commands.CommandError):
"""
Give feedback to the user when user has no perms to use the command
:param ctx: Original command context
:param error: Error
:return:
"""
await on_command_error(ctx, error)

def slashcommandlogger(func):
"""
Decorator to log slash commands
:param func: wrapped function
:return:
"""
@functools.wraps(func)
async def wrapped(ctx, cog: str):
# Some fancy foo stuff
await logCommand(client.get_channel(settings.DISCORD_LOG_CHANNEL), ctx, cog=cog.lower())
await func(ctx, cog)

return wrapped

@client.slash_command(description="load a cog",
guild_ids=settings.DISCORD_GUILD_IDS,
default_permission=False)
@commands.has_role(settings.DISCORD_COMMAND_PERMISSION_ROLE)
@option(name="cog",
description="Select Cog",
from cogManagerMixin import commandlogger


class CogManager(commands.Cog):
def __init__(self, client):
self.client = client

@commands.Cog.listener()
async def on_ready(self):
await self.client.get_channel(settings.DISCORD_LOG_CHANNEL).send(
':white_check_mark: Cog: "cogmanager" ready'
)

@commands.slash_command(
description="load a cog",
guild_ids=settings.DISCORD_GUILD_IDS,
default_permission=False,
)
@commands.has_role(settings.DISCORD_COMMAND_PERMISSION_ROLE)
@option(
name="cog",
description="Select Cog",
required=True,
choices=settings.DISCORD_COGS
)
@slashcommandlogger
async def load(ctx: discord.ApplicationContext, cog: str):
"""
Load a cog
:param ctx: Original slash command context
:param cog: Name of the cog to load
:return:
"""
cog, className = cog.lower(), cog
try:
client.load_extension(f"cogs.{cog}")
bot = client.get_cog(className)
await bot.on_ready()
await ctx.respond(f"Cog: \"{cog}\" loaded.")
except discord.errors.ExtensionAlreadyLoaded:
await ctx.respond(f"Cog: \"{cog}\" already loaded.")

@client.slash_command(description="unload a cog",
guild_ids=settings.DISCORD_GUILD_IDS,
default_permission=False)
@commands.has_role(settings.DISCORD_COMMAND_PERMISSION_ROLE)
@option(name="cog",
description="Select Cog",
choices=settings.DISCORD_COGS,
)
@commandlogger
async def load(self, ctx: discord.ApplicationContext, cog: str):
"""
Load a cog
:param ctx: Original slash command context
:param cog: Name of the cog to load
:return:
"""
cog, className = cog.lower(), cog
try:
self.client.load_extension(f"cogs.{cog}")
bot = self.client.get_cog(className)
await bot.on_ready()
await ctx.respond(f'Cog: "{cog}" loaded.')
except discord.errors.ExtensionAlreadyLoaded:
await ctx.respond(f'Cog: "{cog}" already loaded.')

@commands.slash_command(
description="unload a cog",
guild_ids=settings.DISCORD_GUILD_IDS,
default_permission=False,
)
@commands.has_role(settings.DISCORD_COMMAND_PERMISSION_ROLE)
@option(
name="cog",
description="Select Cog",
required=True,
choices=settings.DISCORD_COGS
)
@slashcommandlogger
async def unload(ctx, cog: str):
"""
Unload a cog
:param ctx: Original slash command context
:param cog: Name of the cog to unload
:return:
"""
cog = cog.lower()
try:
client.unload_extension(f"cogs.{cog}")
await ctx.respond(f"Cog: \"{cog}\" unloaded.")
await client.get_channel(settings.DISCORD_LOG_CHANNEL).send(f":negative_squared_cross_mark: Cog: \"{cog}\" unloaded.")
except discord.errors.ExtensionNotLoaded:
await ctx.respond(f"Cog: \"{cog}\" not loaded.")

@client.slash_command(description="reload a cog",
guild_ids=settings.DISCORD_GUILD_IDS,
default_permission=False)
@commands.has_role(settings.DISCORD_COMMAND_PERMISSION_ROLE)
@option(name="cog",
description="Select Cog",
choices=settings.DISCORD_COGS,
)
@commandlogger
async def unload(self, ctx: discord.ApplicationContext, cog: str):
"""
Unload a cog
:param ctx: Original slash command context
:param cog: Name of the cog to unload
:return:
"""
cog = cog.lower()
try:
self.client.unload_extension(f"cogs.{cog}")
await ctx.respond(f'Cog: "{cog}" unloaded.')
await self.client.get_channel(settings.DISCORD_LOG_CHANNEL).send(
f':negative_squared_cross_mark: Cog: "{cog}" unloaded.'
)
except discord.errors.ExtensionNotLoaded:
await ctx.respond(f'Cog: "{cog}" not loaded.')

@commands.slash_command(
description="reload a cog",
guild_ids=settings.DISCORD_GUILD_IDS,
default_permission=False,
)
@commands.has_role(settings.DISCORD_COMMAND_PERMISSION_ROLE)
@option(
name="cog",
description="Select Cog",
required=True,
choices=settings.DISCORD_COGS
)
@slashcommandlogger
async def reload(ctx, cog: str):
"""
Reload a cog
:param ctx: Original slash command context
:param cog: Name of the cog to reload
:return:
"""
# Attempt to unload
cog, className = cog.lower(), cog
try:
client.unload_extension(f"cogs.{cog}")
await client.get_channel(settings.DISCORD_LOG_CHANNEL).send(f":negative_squared_cross_mark: Cog: \"{cog}\" unloaded.")
except discord.errors.ExtensionNotLoaded:
pass

# Load the cog
client.load_extension(f"cogs.{cog}")
bot = client.get_cog(className)
await bot.on_ready()
await ctx.send(f"Cog: \"{cog}\" reloaded.")
choices=settings.DISCORD_COGS,
)
@commandlogger
async def reload(self, ctx: discord.ApplicationContext, cog: str):
"""
Reload a cog
:param ctx: Original slash command context
:param cog: Name of the cog to reload
:return:
"""
# Attempt to unload
cog, className = cog.lower(), cog
try:
self.client.unload_extension(f"cogs.{cog}")
await self.client.get_channel(settings.DISCORD_LOG_CHANNEL).send(
f':negative_squared_cross_mark: Cog: "{cog}" unloaded.'
)
except discord.errors.ExtensionNotLoaded:
pass

# Load the cog
self.client.load_extension(f"cogs.{cog}")
bot = self.client.get_cog(className)
await bot.on_ready()
await ctx.respond(f'Cog: "{cog}" reloaded.')


class ClanBotjasClient(commands.Bot):
def __init__(self):
super().__init__(
command_prefix=commands.when_mentioned_or("!"), intents=settings.INTENTS
)
self.add_cog(CogManager(self))
for cog in settings.DISCORD_COGS:
self.load_extension(f"cogs.{cog.name}")

async def on_command_error(
self, ctx: commands.Context, error: commands.CommandError
):
"""
Give feedback to the user when user has no perms to use the command
:param ctx: Original command context
:param error: Error
:return:
"""

if isinstance(error, commands.errors.MissingRole):
await ctx.response.send_message(
f"{ctx.author.mention}, You do not have permissions to use that command.",
ephemeral=True,
)
else:
raise error

async def on_application_command_error(
self, ctx: commands.Context, error: commands.CommandError
):
"""
Give feedback to the user when user has no perms to use the command
:param ctx: Original command context
:param error: Error
:return:
"""
await self.on_command_error(ctx, error)


if __name__ == "__main__":
# Load all cogs
for cog in settings.DISCORD_COGS:
client.load_extension(f'cogs.{cog.name}')

client.run(settings.DISCORD_TOKEN)
ClanBotjasClient().run(settings.DISCORD_TOKEN)
Loading

0 comments on commit 3196253

Please sign in to comment.