Compare commits

..
9 Commits
7 changed files with 158 additions and 200 deletions
+24 -15
View File
@@ -2,8 +2,8 @@
Bot command for deleting the guild's scores. Bot command for deleting the guild's scores.
""" """
from nextcord import Embed
from nextcord.ext import commands from nextcord.ext import commands
import nextcord
from highscores import highscores_data # pylint: disable=import-error from highscores import highscores_data # pylint: disable=import-error
@@ -14,29 +14,38 @@ class DeleteScores(commands.Cog, name="Delete Scores"):
Deletes this guild's scores. Deletes this guild's scores.
""" """
def __init__(self, bot: commands.Bot): def __init__(self):
self.bot = bot """
Default constructor for DeleteScores class. Does nothing.
"""
@commands.command(name="delete-scores") @nextcord.slash_command(
@commands.has_permissions(administrator=True) description="Deletes all scores for this guild. Used for testing.",
async def delete_scores(self, ctx: commands.Context): default_member_permissions=nextcord.Permissions(administrator=True),
"""A command which deletes all scores for this guild. )
Usage: async def delete_scores(self, interaction: nextcord.Interaction):
``` """
?delete_scores A command which deletes all scores in all tables for this guild.
``` Command limits to admins to prevent devs from usings on non-test servers.
""" """
# only allow AlwaysCompiling to use. # only allow AlwaysCompiling to use.
# If you are a developer and want to use command, can add name to list # If you are a developer and want to use command, can add name to list
if ctx.author.id == 206602713511886849: if interaction.user.id == 206602713511886849:
for table in highscores_data.get_guild(ctx.guild.id).tables: for table in highscores_data.get_guild(interaction.guild_id).tables:
for category in table.categories: for category in table.categories:
category.clear() category.clear()
highscores_data.save_guild_data(highscores_data.get_guild(ctx.guild.id)) highscores_data.save_guild_data(highscores_data.get_guild(interaction.guild_id))
await interaction.response.send_message(
f"Cleared score data for {interaction.guild.name}.", ephemeral=True
)
else:
await interaction.response.send_message(
"You shouldn't be using this message.", ephemeral=True
)
# This function will be called when this extension is loaded. # This function will be called when this extension is loaded.
# It is necessary to add these functions to the bot. # It is necessary to add these functions to the bot.
def setup(bot: commands.Bot): def setup(bot: commands.Bot):
"""Adds function to bot""" """Adds function to bot"""
bot.add_cog(DeleteScores(bot)) bot.add_cog(DeleteScores())
-26
View File
@@ -1,26 +0,0 @@
"""
Help command
"""
from nextcord.ext import commands
from .help_command import NewHelpCommand
class HelpCog(commands.Cog):
"""Help Command"""
def __init__(self, bot: commands.Bot):
self.bot = bot
self._original_help_command = bot.help_command
bot.help_command = NewHelpCommand()
bot.help_command.cog = self
def cog_unload(self):
self.bot.help_command = self._original_help_command
# setup functions for bot
def setup(bot: commands.Bot):
"""Adds function to bot"""
bot.add_cog(HelpCog(bot))
-84
View File
@@ -1,84 +0,0 @@
"""
Help command. Copied from discord-bot-template.
"""
import nextcord
from nextcord.embeds import EmptyEmbed
from nextcord.ext import commands
import config # pylint: disable=import-error
class NewHelpCommand(commands.MinimalHelpCommand):
"""Custom help command override using embeds"""
COLOUR = nextcord.Colour.blurple()
def get_ending_note(self):
"""Returns note to display at the bottom"""
invoked_with = self.invoked_with
return f"Use {config.BOT_PREFIX}{invoked_with} [command] for more info on a command."
def get_command_signature(self, command: commands.core.Command):
"""Retrieves the signature portion of the help page."""
return f"{command.qualified_name} {command.signature}"
async def send_bot_help(self, mapping: dict):
"""implements bot command help page"""
embed = nextcord.Embed(title="Bot Commands", colour=self.COLOUR)
avatar = self.context.bot.user.avatar
avatar_url = avatar.url if avatar else EmptyEmbed
embed.set_author(name=self.context.bot.user.name, icon_url=avatar_url)
description = self.context.bot.description
if description:
embed.description = description
for cog, commands in mapping.items(): # pylint: disable=redefined-outer-name
name = "No Category" if cog is None else cog.qualified_name
filtered = await self.filter_commands(commands, sort=True)
if filtered:
# \u2002 = middle dot
value = "\u2002".join(f"{config.BOT_PREFIX}{c.name}" for c in filtered)
if cog and cog.description:
value = f"{cog.description}\n{value}"
embed.add_field(name=name, value=value)
embed.set_footer(text=self.get_ending_note())
await self.get_destination().send(embed=embed)
async def send_cog_help(self, cog: commands.Cog):
"""implements cog help page"""
embed = nextcord.Embed(title=f"{cog.qualified_name} Commands", colour=self.COLOUR)
if cog.description:
embed.description = cog.description
filtered = await self.filter_commands(cog.get_commands(), sort=True)
for command in filtered:
embed.add_field(
name=self.get_command_signature(command),
value=command.short_doc or "...",
inline=False,
)
embed.set_footer(text=self.get_ending_note())
await self.get_destination().send(embed=embed)
async def send_group_help(self, group: commands.Group):
"""implements group help page and command help page"""
embed = nextcord.Embed(title=group.qualified_name, colour=self.COLOUR)
if group.help:
embed.description = group.help
if isinstance(group, commands.Group):
filtered = await self.filter_commands(group.commands, sort=True)
for command in filtered:
embed.add_field(
name=self.get_command_signature(command),
value=command.short_doc or "...",
inline=False,
)
embed.set_footer(text=self.get_ending_note())
await self.get_destination().send(embed=embed)
# Use the same function as group help for command help
send_command_help = send_group_help # type: ignore
+30 -19
View File
@@ -13,35 +13,44 @@ from utilities.utils import send_highscore_message # pylint: disable=import-err
class PostHighscores(commands.Cog, name="Post Highscores"): class PostHighscores(commands.Cog, name="Post Highscores"):
"""Posts Highscores.""" """Posts Highscores."""
def __init__(self, bot: commands.Bot): def __init__(self, bot: commands.Bot) -> None:
"""
Default constructor for PostHighscores class
Args:
bot (commands.Bot): Bot object. Required to register submission button view.
"""
self.bot = bot self.bot = bot
@commands.command(name="post-scores") @nextcord.slash_command(
@commands.has_permissions(administrator=True) description="Triggers post/update of highscores to registered highscore channel.",
async def post_highscores(self, ctx: commands.Context): default_member_permissions=nextcord.Permissions(administrator=True),
)
async def post_highscore_tables(self, interaction: nextcord.Interaction) -> None:
""" """
A command which posts the highscore in the designated channel. A command which posts the highscore in the registered channel.
Sends warning if no channel has been registered. Sends warning if no channel has been registered.
Usage:
```
?post-scores
```
""" """
guild = highscores_data.get_guild(ctx.guild.id) guild = highscores_data.get_guild(interaction.guild_id)
print(f"Printing out highscores information in channel {guild.highscore_channel}") print(f"Printing out highscores information in channel {guild.highscore_channel}")
channel = ctx.guild.get_channel(guild.highscore_channel) channel = interaction.guild.get_channel(guild.highscore_channel)
# Error checking for registered highscore channel
error_response = "Registered Highscores channel does not exist or was never registered. " error_response = "Registered Highscores channel does not exist or was never registered. "
error_response += 'Register with "?register" command.' error_response += 'Use "/register" to register channels.'
assert channel is not None, await ctx.send(error_response) assert channel is not None, await interaction.response(error_response, ephemeral=True)
if len(highscores_data.get_guild(ctx.guild.id).tables) < 1: # Error checking for tables existing
await channel.send( # TODO fill out response string once functionality created.
"No tables have been created for this guild. Please create some tables." error_response = "No tables have been created for this guild. Please create some tables."
) assert (
return len(highscores_data.get_guild(interaction.guild_id).tables) > 0
), await interaction.response(error_response, ephemeral=True)
for table in highscores_data.get_guild(ctx.guild.id).tables: # awaiting response because posting scores takes a while
await interaction.response.defer(ephemeral=True)
for table in highscores_data.get_guild(interaction.guild_id).tables:
message: nextcord.Message = await send_highscore_message(channel, guild, table) message: nextcord.Message = await send_highscore_message(channel, guild, table)
await message.edit(view=SubmissionCreateButton(self.bot)) await message.edit(view=SubmissionCreateButton(self.bot))
@@ -49,6 +58,8 @@ class PostHighscores(commands.Cog, name="Post Highscores"):
# messages have been sent. # messages have been sent.
highscores_data.save_guild_data(guild) highscores_data.save_guild_data(guild)
await interaction.followup.send(f"Posted all tables to <#{channel.id}>.", ephemeral=True)
# This function will be called when this extension is loaded. # This function will be called when this extension is loaded.
# It is necessary to add these functions to the bot. # It is necessary to add these functions to the bot.
+7 -4
View File
@@ -35,14 +35,17 @@ class BotPresence(commands.Cog, name="Bot Presence"):
async def change_presence(self): async def change_presence(self):
"""Randomly chooses a presence and updates bot's presence.""" """Randomly chooses a presence and updates bot's presence."""
statuses = [ statuses = [
f"?help | {len(self.bot.guilds)} servers", "Now with slash commands!",
f"Vuln Pls. | {len(self.bot.guilds)} servers", "Vuln Pls.",
f"All your base are belong to us. | {len(self.bot.guilds)} servers", "All your base are belong to us.",
f"Double plus good. | {len(self.bot.guilds)} servers", "Double plus good.",
"That's a lot of damage!",
] ]
status = random.choice(statuses) status = random.choice(statuses)
status += f" | {len(self.bot.guilds)} servers"
await self.bot.change_presence(activity=nextcord.Game(status)) await self.bot.change_presence(activity=nextcord.Game(status))
+94 -49
View File
@@ -2,63 +2,108 @@
Bot command for registering various channels to the bot. Bot command for registering various channels to the bot.
""" """
from nextcord import Embed
from nextcord.ext import commands from nextcord.ext import commands
import nextcord
from highscores import highscores_data # pylint: disable=import-error from highscores import highscores_data # pylint: disable=import-error
class RegisterVerificationChannel(commands.Cog, name="Register"): class Register(commands.Cog, name="Register"):
"""Bot command for registering various channels to the bot.""" """
Class holds various register commands.
"""
def __init__(self, bot: commands.Bot) -> None: def __init__(self) -> None:
self.bot = bot """
Default constructor for Register class. Does nothing.
@commands.command(name="register")
@commands.has_permissions(administrator=True)
async def register_highscores(self, ctx: commands.Context, registration_type: str) -> None:
"""A command which registers current channel as for various uses.
Usage:
```
?register verify (Use in channel you want to verify submissions in.)
?register highscore (Use in channel you want to show highscore messages in.)
?register submission (Use in channel you want submission messages to be send it.)
?register help (Shows help message.)
```
""" """
# respond to the message
channel_id = ctx.channel.id
guild = highscores_data.get_guild(ctx.guild.id)
if registration_type == "verify": @nextcord.slash_command(default_member_permissions=nextcord.Permissions(administrator=True))
await ctx.send(f"Registered <#{channel_id}> as channel to post verifications in.") async def register(self):
guild.verification_channel = channel_id """
elif registration_type == "highscore": Parent slash command, never called.
await ctx.send(f"Registered <#{channel_id}> as channel to post highscores in.") """
guild.highscore_channel = channel_id
elif registration_type == "submission":
await ctx.send(f"Registered <#{channel_id}> as channel to post submissions in.")
guild.submission_channel = channel_id
else:
embed = Embed(
title="Register command help", description="How to use the register command."
)
embed.add_field(
name="?register verify", value="Use in channel you want to verify submissions in."
)
embed.add_field(
name="?register highscore",
value="Use in channel you want to show highscore messages in.",
)
embed.add_field(
name="?register submission",
value="Use in channel you want submission messages to be send it.",
)
embed.add_field(name="?register help", value="Use to show this message.")
await ctx.reply(embed=embed)
# return, don't need to save data
return
@register.subcommand(description="Registers the channel for perminent highscores messages.")
async def highscore(
self,
interaction: nextcord.Interaction,
channel: nextcord.abc.GuildChannel = nextcord.SlashOption(
description="Channel to register",
required=False,
channel_types=[nextcord.ChannelType.text],
default=None,
),
) -> None:
"""
Command function to register the highscore printing channel.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command
channel (nextcord.abc.GuildChannel, optional): Channel to register
Is a SlashOption. Limited to text channels, Defaults to None.
"""
if not channel:
channel = interaction.channel
channel_id = channel.id
guild = highscores_data.get_guild(interaction.guild_id)
await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True)
guild.highscore_channel = channel_id
highscores_data.save_guild_data(guild)
@register.subcommand(description="Registers the channel for submission messages.")
async def submission(
self,
interaction: nextcord.Interaction,
channel: nextcord.abc.GuildChannel = nextcord.SlashOption(
description="Channel to register",
required=False,
channel_types=[nextcord.ChannelType.text],
default=None,
),
) -> None:
"""
Command function to register the submission message channel.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command
channel (nextcord.abc.GuildChannel, optional): Channel to register
Is a SlashOption. Limited to text channels, Defaults to None.
"""
if not channel:
channel = interaction.channel
channel_id = channel.id
guild = highscores_data.get_guild(interaction.guild_id)
await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True)
guild.submission_channel = channel_id
highscores_data.save_guild_data(guild)
@register.subcommand(description="Registers the channel for verification messages.")
async def verify(
self,
interaction: nextcord.Interaction,
channel: nextcord.abc.GuildChannel = nextcord.SlashOption(
description="Channel to register",
required=False,
channel_types=[nextcord.ChannelType.text],
default=None,
),
) -> None:
"""
Command function to register the verification message channel.
Args:
interaction (nextcord.Interaction): Interaction that invoked the command
channel (nextcord.abc.GuildChannel, optional): Channel to register
Is a SlashOption. Limited to text channels, Defaults to None.
"""
if not channel:
channel = interaction.channel
channel_id = channel.id
guild = highscores_data.get_guild(interaction.guild_id)
await interaction.send(f"Registered <#{channel_id}>.", ephemeral=True)
guild.verification_channel = channel_id
highscores_data.save_guild_data(guild) highscores_data.save_guild_data(guild)
@@ -66,4 +111,4 @@ class RegisterVerificationChannel(commands.Cog, name="Register"):
# It is necessary to add these functions to the bot. # It is necessary to add these functions to the bot.
def setup(bot: commands.Bot) -> None: def setup(bot: commands.Bot) -> None:
"""Adds function to bot""" """Adds function to bot"""
bot.add_cog(RegisterVerificationChannel(bot)) bot.add_cog(Register())
+3 -3
View File
@@ -6,8 +6,8 @@ import logging
import os import os
import sys import sys
import nextcord
from nextcord.ext import commands from nextcord.ext import commands
import nextcord
import config import config
from classes.highscores_data import HighscoresData from classes.highscores_data import HighscoresData
@@ -33,9 +33,9 @@ submission_objects: SubmissionMap = SubmissionMap()
def main(): def main():
"""Main function for bot.""" """Main function for bot."""
min_python_version = (3, 7) min_python_version = (3, 8)
if sys.version_info < min_python_version: if sys.version_info < min_python_version:
print("ERROR: Python version must be >= 3.7") print("ERROR: Python version must be >= 3.8")
sys.exit() sys.exit()
# Allows privledged intents for monitoring members joining, roles editing, and role assignments # Allows privledged intents for monitoring members joining, roles editing, and role assignments