diff --git a/cogs/events.py b/cogs/events.py index 76dbae2..9069c3b 100644 --- a/cogs/events.py +++ b/cogs/events.py @@ -1,11 +1,9 @@ -from dislash import SlashInteraction - from data import constants from data.snipe import Snipe, Action, should_snipe import datetime import discord from discord.ext import commands -from functions import checks, easterEggResponses, stringFormatters +from functions import checks, easterEggResponses from functions.database import stats, muttn, custom_commands, commands as command_stats import pytz from settings import READY_MESSAGE, SANDBOX, STATUS_MESSAGE @@ -89,9 +87,12 @@ class Events(commands.Cog): Logs commands in your terminal. :param ctx: Discord Context """ - print(stringFormatters.format_command_usage(ctx)) + DM = ctx.guild is None + print("{} in {}: {}".format(ctx.author.display_name, + "DM" if DM else "{} ({})".format(ctx.channel.name, ctx.guild.name), + ctx.message.content)) - command_stats.invoked(command_stats.InvocationType.TextCommand) + command_stats.invoked() @commands.Cog.listener() async def on_command_error(self, ctx, err): @@ -100,8 +101,8 @@ class Events(commands.Cog): :param ctx: Discord Context :param err: the error thrown """ - # Debugging Didier shouldn't spam the error logs - if self.client.user.id != int(constants.didierId): + # Zandbak Didier shouldn't spam the error logs + if self.client.user.id == int(constants.coolerDidierId): raise err # Don't handle commands that have their own custom error handler @@ -122,26 +123,14 @@ class Events(commands.Cog): elif isinstance(err, (commands.BadArgument, commands.MissingRequiredArgument, commands.UnexpectedQuoteError)): await ctx.send("Controleer je argumenten.") else: - usage = stringFormatters.format_command_usage(ctx) - await self.sendErrorEmbed(err, "Command", usage) - - @commands.Cog.listener() - async def on_slash_command(self, interaction: SlashInteraction): - """ - Function called whenever someone uses a slash command - """ - print(stringFormatters.format_slash_command_usage(interaction)) - - command_stats.invoked(command_stats.InvocationType.SlashCommand) - - @commands.Cog.listener() - async def on_slash_command_error(self, interaction, err): - # Debugging Didier shouldn't spam the error logs - if self.client.user.id != int(constants.didierId): - raise err - - usage = stringFormatters.format_slash_command_usage(interaction) - await self.sendErrorEmbed(err, "Slash Command", usage) + # Remove the InvokeCommandError because it's useless information + x = traceback.format_exception(type(err), err, err.__traceback__) + errorString = "" + for line in x: + if "direct cause of the following" in line: + break + errorString += line.replace("*", "") + "\n" if line.strip() != "" else "" + await self.sendErrorEmbed(ctx, err, errorString) @commands.Cog.listener() async def on_raw_reaction_add(self, react): @@ -297,15 +286,19 @@ class Events(commands.Cog): self.client.snipe[message.channel.id] = Snipe(message.author.id, message.channel.id, message.guild.id, Action.Remove, message.content) - async def sendErrorEmbed(self, error: Exception, error_type: str, usage: str): + async def sendErrorEmbed(self, ctx, error: Exception, trace): """ Function that sends an error embed in #ErrorLogs. + :param ctx: Discord Context + :param error: the error thrown + :param trace: the stacktrace of the error """ - trace = stringFormatters.format_error_tb(error) - embed = discord.Embed(colour=discord.Colour.red()) embed.set_author(name="Error") - embed.add_field(name=f"{error_type}:", value=usage, inline=False) + embed.add_field(name="Command:", value="{} in {}: {}".format(ctx.author.display_name, + ctx.channel.name if str( + ctx.channel.type) != "private" else "DM", + ctx.message.content), inline=False) embed.add_field(name="Error:", value=str(error)[:1024], inline=False) embed.add_field(name="Message:", value=str(trace)[:1024], inline=False) diff --git a/cogs/football.py b/cogs/football.py index d02ec15..1f77c85 100644 --- a/cogs/football.py +++ b/cogs/football.py @@ -2,7 +2,7 @@ from decorators import help from discord.ext import commands from enums.help_categories import Category from functions import checks, config -from functions.football import get_matches, get_table, get_jpl_code +from functions.football import getMatches, getTable, get_jpl_code class Football(commands.Cog): @@ -20,16 +20,21 @@ class Football(commands.Cog): pass @jpl.command(name="Matches", aliases=["M"], usage="[Week]*") - async def matches(self, ctx, day: int = None): - # Default is current day - if day is None: - day = int(config.get("jpl_day")) + async def matches(self, ctx, *args): + args = list(args) - await ctx.send(get_matches(day)) + # Default is current day + if not args: + args = [str(config.get("jpl_day"))] + + if all(letter.isdigit() for letter in args[0]): + await ctx.send(getMatches(int(args[0]))) + else: + return await ctx.send("Dit is geen geldige speeldag.") @jpl.command(name="Table", aliases=["Ranking", "Rankings", "Ranks", "T"]) - async def table(self, ctx): - await ctx.send(get_table()) + async def table(self, ctx, *args): + await ctx.send(getTable()) @commands.check(checks.isMe) @jpl.command(name="Update") diff --git a/cogs/google.py b/cogs/google.py index 204075e..429b4f4 100644 --- a/cogs/google.py +++ b/cogs/google.py @@ -1,3 +1,4 @@ +import discord from discord.ext import commands from decorators import help from enums.help_categories import Category diff --git a/cogs/school.py b/cogs/school.py index a206e64..94b3fb7 100644 --- a/cogs/school.py +++ b/cogs/school.py @@ -42,7 +42,7 @@ class School(commands.Cog): embed.set_footer(text="Omwille van de coronamaatregelen is er een beperkter aanbod, en kan je enkel nog eten afhalen. Ter plaatse eten is niet meer mogelijk.") await ctx.send(embed=embed) - # @commands.command(name="Les", aliases=["Class", "Classes", "Sched", "Schedule"], usage="[Dag]*") + # @commands.command(name="Les", aliases=["Class", "Classes", "Sched", "Schedule"], usage="[Jaargang]* [Dag]*") # @commands.check(checks.allowedChannels) # @help.Category(category=Category.School) async def les(self, ctx, day=None): diff --git a/cogs/slash/define_slash.py b/cogs/slash/define_slash.py index b291bb9..55899d8 100644 --- a/cogs/slash/define_slash.py +++ b/cogs/slash/define_slash.py @@ -13,7 +13,8 @@ class DefineSlash(commands.Cog): description="Urban Dictionary", options=[ Option("query", "Search query", OptionType.STRING, required=True) - ] + ], + guild_ids=[728361030404538488, 880175869841277008] ) async def _define_slash(self, interaction: SlashInteraction, query): embed = Definition(query).to_embed() diff --git a/cogs/slash/football_slash.py b/cogs/slash/football_slash.py deleted file mode 100644 index d5a7283..0000000 --- a/cogs/slash/football_slash.py +++ /dev/null @@ -1,44 +0,0 @@ -from discord.ext import commands -from dislash import SlashInteraction, slash_command, Option, OptionType -from functions import config, checks -from functions.football import get_matches, get_table, get_jpl_code -from startup.didier import Didier - - -class FootballSlash(commands.Cog): - def __init__(self, client: Didier): - self.client: Didier = client - - @slash_command(name="jpl", description="Jupiler Pro League commands") - async def _jpl_group(self, interaction: SlashInteraction): - pass - - @_jpl_group.sub_command(name="matches", - description="Schema voor een bepaalde speeldag", - options=[ - Option("day", "Speeldag (default huidige)", OptionType.INTEGER) - ] - ) - async def _jpl_matches_slash(self, interaction: SlashInteraction, day: int = None): - # Default is current day - if day is None: - day = int(config.get("jpl_day")) - - await interaction.reply(get_matches(day)) - - @_jpl_group.sub_command(name="table", description="Huidige rangschikking") - async def _jpl_table_slash(self, interaction: SlashInteraction): - await interaction.reply(get_table()) - - @_jpl_group.sub_command(name="update", description="Update de code voor deze competitie (owner-only)") - async def _jpl_update_slash(self, interaction: SlashInteraction): - if not await checks.isMe(interaction): - return await interaction.reply(f"Je hebt geen toegang tot dit commando.") - - code = get_jpl_code() - config.config("jpl", code) - await interaction.reply(f"Done (code: {code})") - - -def setup(client: Didier): - client.add_cog(FootballSlash(client)) diff --git a/cogs/slash/google_slash.py b/cogs/slash/google_slash.py index 6978492..fe9ba61 100644 --- a/cogs/slash/google_slash.py +++ b/cogs/slash/google_slash.py @@ -12,7 +12,8 @@ class GoogleSlash(commands.Cog): description="Google search", options=[ Option("query", "Search query", OptionType.STRING, required=True) - ] + ], + guild_ids=[728361030404538488, 880175869841277008] ) async def _google_slash(self, interaction: SlashInteraction, query: str): result = google_search(query) diff --git a/cogs/slash/translate_slash.py b/cogs/slash/translate_slash.py index 6ee293d..226aa0d 100644 --- a/cogs/slash/translate_slash.py +++ b/cogs/slash/translate_slash.py @@ -14,12 +14,11 @@ class TranslateSlash(commands.Cog): description="Google Translate", options=[ Option("text", "Tekst om te vertalen", OptionType.STRING, required=True), - Option("from_lang", "Taal om van te vertalen (default auto-detect)", OptionType.STRING), - Option("to_lang", "Taal om naar te vertalen (default NL)", OptionType.STRING) + Option("to", "Taal om naar te vertalen (default NL)", OptionType.STRING) ] ) - async def _translate_slash(self, interaction: SlashInteraction, text: str, from_lang: str = "auto", to_lang: str = "nl"): - translation = Translation(text=text, fr=from_lang.lower(), to=to_lang.lower()) + async def _translate_slash(self, interaction: SlashInteraction, text: str, to: str = "nl"): + translation = Translation(text=text, to=to.lower()) await interaction.reply(embed=translation.to_embed()) diff --git a/data/embeds/translate.py b/data/embeds/translate.py index 32f4853..86ade0e 100644 --- a/data/embeds/translate.py +++ b/data/embeds/translate.py @@ -5,32 +5,26 @@ from typing import Optional class Translation: - def __init__(self, text: str, fr: str, to: str): + def __init__(self, text: str, to: str): self.text = text - self.fr = fr self.to = to self.embed: Optional[discord.Embed] = None self.translation = None - self.translate(text, fr, to) + self.translate(text, to) - def translate(self, query: str, fr: str, to: str): + def translate(self, query: str, to: str): """ Translate [query] into [to] """ try: translator = Translator() - self.translation = translator.translate(query, to, fr) + self.translation = translator.translate(query, to, "auto") except ValueError as e: message = str(e) if "destination" in message: self._create_error_embed(f"{title_case(to)} is geen geldige taal.") - return - - if "source" in message: - self._create_error_embed(f"{title_case(fr)} is geen geldige taal.") - return raise e @@ -48,9 +42,8 @@ class Translation: embed = discord.Embed(colour=discord.Colour.blue()) embed.set_author(name="Didier Translate") - if self.fr == "auto": - language = self.translation.src - embed.add_field(name="Gedetecteerde taal", value=title_case(LANGUAGES[language])) + language = self.translation.src + embed.add_field(name="Gedetecteerde taal", value=title_case(LANGUAGES[language])) if self.translation.extra_data["confidence"] is not None: embed.add_field(name="Zekerheid", value="{}%".format(self.translation.extra_data["confidence"] * 100)) diff --git a/files/help.json b/files/help.json index 5738649..d6112ac 100644 --- a/files/help.json +++ b/files/help.json @@ -58,7 +58,7 @@ "jpl table": "De huidige stand van het klassement.", "jpl update": "Haalt de nieuwe code voor de competitie van dit jaar op.", "leaderboard": "Bekijk de Top 10 van [Categorie].\nIndien je geen categorie opgeeft krijg je een lijst van categorieën.", - "les": "Bekijk het lessenrooster voor [Dag].\nIndien je geen dag opgeeft, is dit standaard vandaag.\nLes Morgen/Overmorgen werkt ook.", + "les": "Bekijk het lessenrooster voor [Dag] in het [Jaargang]-de jaar.\nIndien je geen dag opgeeft, is dit standaard vandaag. De jaargang is standaard 2.\nLes Morgen/Overmorgen werkt ook.", "lmgtfy": "Stuur iemand een LMGTFY link wanneer ze je een domme vraag stellen in plaats van het zelf op te zoeken.\nQueries met spaties moeten **niet** tussen aanhalingstekens staan.", "load": "Laadt [Cog] in.", "load all": "Laadt alle cogs in.", diff --git a/functions/checks.py b/functions/checks.py index 6d18dfe..0cbb042 100644 --- a/functions/checks.py +++ b/functions/checks.py @@ -1,4 +1,8 @@ +import math + import discord +from discord import utils, Member, User +from discord.ext import commands from data import constants import requests from functions.database import currency diff --git a/functions/database/commands.py b/functions/database/commands.py index f1bf35c..fda1d11 100644 --- a/functions/database/commands.py +++ b/functions/database/commands.py @@ -1,20 +1,23 @@ -from enum import IntEnum - from functions.database import utils -from functions.stringFormatters import leading_zero as lz import time -class InvocationType(IntEnum): - TextCommand = 0 - SlashCommand = 1 - ContextMenu = 2 - - -def invoked(inv: InvocationType): +def invoked(): t = time.localtime() - day_string: str = f"{t.tm_year}-{lz(t.tm_mon)}-{lz(t.tm_mday)}" - _update(day_string, inv) + day_string: str = f"{t.tm_year}-{_lz(t.tm_mon)}-{_lz(t.tm_mday)}" + _update(day_string) + + +def _lz(arg: int) -> str: + """ + Add leading zeroes if necessary (YYYY-MM-DD) + """ + arg = str(arg) + + if len(arg) == 1: + return f"0{arg}" + + return arg def _is_present(date: str) -> bool: @@ -40,27 +43,25 @@ def _add_date(date: str): connection = utils.connect() cursor = connection.cursor() - cursor.execute("INSERT INTO command_stats(day, commands, slash_commands, context_menus) VALUES (%s, 0, 0, 0)", (date,)) + cursor.execute("INSERT INTO command_stats(day, amount) VALUES (%s, 1)", (date,)) connection.commit() -def _update(date: str, inv: InvocationType): +def _update(date: str): """ Increase the counter for a given day """ - # Date wasn't present yet, add it + # Date wasn't present yet, add it with a value of 1 if not _is_present(date): _add_date(date) + return connection = utils.connect() cursor = connection.cursor() - column_name = ["commands", "slash_commands", "context_menus"][inv.value] - - # String formatting is safe here because the input comes from above ^ - cursor.execute(f""" + cursor.execute(""" UPDATE command_stats - SET {column_name} = {column_name} + 1 + SET amount = amount + 1 WHERE day = %s """, (date,)) connection.commit() diff --git a/functions/football.py b/functions/football.py index ffe2a20..59edf45 100644 --- a/functions/football.py +++ b/functions/football.py @@ -39,11 +39,11 @@ class Match: Parse class attributes out of a dictionary returned from an API request """ # The API isn't public, so every single game state is differently formatted - self.status = self._get_status(self.matchDict[Navigation.Status.value]) + self.status = self._getStatus(self.matchDict[Navigation.Status.value]) self.home = self.matchDict[Navigation.HomeTeam.value][Navigation.Name.value] self.away = self.matchDict[Navigation.AwayTeam.value][Navigation.Name.value] - if self._has_started(): + if self._hasStarted(): self.homeScore = self.matchDict[Navigation.HomeScore.value] self.awayScore = self.matchDict[Navigation.AwayScore.value] @@ -53,9 +53,9 @@ class Match: self.start = None self.date = self.start.strftime("%d/%m") if self.start is not None else "Uitgesteld" - self.weekDay = self._get_weekday() if self.start is not None else "??" + self.weekDay = self._getWeekday() if self.start is not None else "??" - def _get_status(self, status: str): + def _getStatus(self, status: str): """ Gets the string representation for the status of this match """ @@ -80,7 +80,7 @@ class Match: return statusses[status.lower()] - def _get_weekday(self): + def _getWeekday(self): """ Gets the day of the week this match is played on """ @@ -88,13 +88,13 @@ class Match: days = ["Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"] return days[day] - def get_info(self): + def getInfo(self): """ Returns a list of all the info of this class in order to create a table """ - return [self.weekDay, self.date, self.home, self._get_score(), self.away, self.status] + return [self.weekDay, self.date, self.home, self._getScore(), self.away, self.status] - def _get_score(self): + def _getScore(self): """ Returns a string representing the scoreboard """ @@ -102,12 +102,12 @@ class Match: return "??" # No score to show yet, show time when the match starts - if not self._has_started(): + if not self._hasStarted(): return "{}:{}".format(leading_zero(str(self.start.hour)), leading_zero(str(self.start.minute))) return "{} - {}".format(self.homeScore, self.awayScore) - def _has_started(self): + def _hasStarted(self): return self.status not in [Status.AfterToday.value, Status.NotStarted.value, Status.Postponed.value] @@ -128,7 +128,7 @@ class Navigation(Enum): Name = "name" -def get_matches(matchweek: int): +def getMatches(matchweek: int): """ Function that constructs the list of matches for a given matchweek """ @@ -139,7 +139,7 @@ def get_matches(matchweek: int): return "Er ging iets fout. Probeer het later opnieuw." matches = list(map(Match, current_day)) - matches = list(map(lambda x: x.get_info(), matches)) + matches = list(map(lambda x: x.getInfo(), matches)) header = "Jupiler Pro League - Speeldag {}".format(matchweek) table = tabulate.tabulate(matches, headers=["Dag", "Datum", "Thuis", "Stand", "Uit", "Tijd"]) @@ -147,7 +147,7 @@ def get_matches(matchweek: int): return "```{}\n\n{}```".format(header, table) -def get_table(): +def getTable(): """ Function that constructs the current table of the JPL """ @@ -157,7 +157,7 @@ def get_table(): return "Er ging iets fout. Probeer het later opnieuw." # Format every row to work for Tabulate - formatted = [_format_row(row) for row in rows] + formatted = [_formatRow(row) for row in rows] header = "Jupiler Pro League Klassement" table = tabulate.tabulate(formatted, headers=["#", "Ploeg", "Punten", "M", "M+", "M-", "M=", "D+", "D-", "D+/-"]) @@ -165,7 +165,7 @@ def get_table(): return "```{}\n\n{}```".format(header, table) -def _format_row(row): +def _formatRow(row): """ Function that formats a row into a list for Tabulate to use """ diff --git a/functions/stringFormatters.py b/functions/stringFormatters.py index f8eb20f..b1646cf 100644 --- a/functions/stringFormatters.py +++ b/functions/stringFormatters.py @@ -1,9 +1,3 @@ -import traceback - -from discord.ext.commands import Context -from dislash import SlashInteraction - - def title_case(string): return " ".join(capitalize(word) for word in string.split(" ")) @@ -19,35 +13,3 @@ def leading_zero(string, size=2): while len(string) < size: string = "0" + string return string - - -def format_error_tb(err: Exception) -> str: - # Remove the InvokeCommandError because it's useless information - x = traceback.format_exception(type(err), err, err.__traceback__) - error_string = "" - for line in x: - if "direct cause of the following" in line: - break - error_string += line.replace("*", "") + "\n" if line.strip() != "" else "" - - return error_string - - -def _format_error_location(src) -> str: - DM = src.guild is None - return "DM" if DM else f"{src.channel.name} ({src.guild.name})" - - -def format_command_usage(ctx: Context) -> str: - return f"{ctx.author.display_name} in {_format_error_location(ctx)}: {ctx.message.content}" - - -def format_slash_command_usage(interaction: SlashInteraction) -> str: - # Create a string with the options used - options = " ".join(list(map( - lambda option: f"{option.name}: \"{option.value}\"", - interaction.data.options.values() - ))) - - command = f"{interaction.slash_command.name} {options or ''}" - return f"{interaction.author.display_name} in {_format_error_location(interaction)}: /{command}" diff --git a/settings.py b/settings.py index 12dd5e6..b64e27c 100644 --- a/settings.py +++ b/settings.py @@ -1,5 +1,3 @@ -from typing import List - from dotenv import load_dotenv import os @@ -33,11 +31,3 @@ TOKEN = os.getenv("TOKEN", "") HOST_IPC = _to_bool(os.getenv("HOSTIPC", "false")) READY_MESSAGE = os.getenv("READYMESSAGE", "I'M READY I'M READY I'M READY I'M READY") # Yes, this is a Spongebob reference STATUS_MESSAGE = os.getenv("STATUSMESSAGE", "with your Didier Dinks.") - -# Guilds to test slash commands in -# Ex: 123,456,789 -SLASH_TEST_GUILDS: List[int] = list( - map(lambda x: int(x), - os.getenv("SLASHTESTGUILDS", "").replace(" ", "").split(",") - ) -) diff --git a/startup/didier.py b/startup/didier.py index 365df73..850080c 100644 --- a/startup/didier.py +++ b/startup/didier.py @@ -2,7 +2,7 @@ from data.snipe import Snipe from discord.ext import commands, ipc from dislash import InteractionClient import os -from settings import HOST_IPC, SLASH_TEST_GUILDS +from settings import HOST_IPC from startup.init_files import check_all from typing import Dict @@ -33,7 +33,7 @@ class Didier(commands.Bot): self.remove_command("help") # Create interactions client - self.interactions = InteractionClient(self, test_guilds=SLASH_TEST_GUILDS) + self.interactions = InteractionClient(self, test_guilds=[728361030404538488, 880175869841277008]) # Load all extensions self.init_extensions()