From 93ede132a216f115afcf2d895df44442a4f060df Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Sun, 6 Feb 2022 17:58:57 +0100 Subject: [PATCH] Memegen slash commands + autocompletion --- cogs/fun.py | 39 +++++++++------------------ cogs/slash/football_slash.py | 2 +- cogs/slash/fun_slash.py | 52 +++++++++++++++++++++++++++++++++++- data/menus/memes.py | 26 ++++++++++++++++++ functions/memes.py | 16 +++++++++-- 5 files changed, 104 insertions(+), 31 deletions(-) create mode 100644 data/menus/memes.py diff --git a/cogs/fun.py b/cogs/fun.py index cb938bb..5eaac9f 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -1,15 +1,16 @@ -from data.embeds.xkcd import XKCDEmbed -from data.menus import leaderboards -from decorators import help -import discord -from discord.ext import commands -from enums.help_categories import Category -from functions import checks, stringFormatters -from functions.database import memes, trump, dadjoke -from functions.memes import generate import json import random + import requests +from discord.ext import commands + +from data.embeds.xkcd import XKCDEmbed +from data.menus.memes import MemesList +from decorators import help +from enums.help_categories import Category +from functions import checks +from functions.database import memes, trump, dadjoke +from functions.memes import generate class Fun(commands.Cog): @@ -98,17 +99,10 @@ class Fun(commands.Cog): if result is None: return await ctx.send("Deze meme staat niet in de database.") - # Convert to list to support item assignment - fields = list(fields) - generated = generate(result, fields) - # If the request was successful, remove the message calling it - if generated["success"]: - await self.utilsCog.removeMessage(ctx.message) - # Send the meme's url or the error message - await ctx.send(generated["message"]) + await ctx.reply(generated["message"], mention_author=False) @commands.command(name="Memes") @commands.check(checks.allowedChannels) @@ -118,16 +112,7 @@ class Fun(commands.Cog): Command that shows a list of memes in the database. :param ctx: Discord Context """ - memeList = memes.getAllMemes() - - # Turn the list into a list of [Name: fields] - memeList = [": ".join([stringFormatters.title_case(meme[1]), - str(meme[2])]) for meme in sorted(memeList, key=lambda x: x[1])] - - pages = paginated_leaderboard.Pages( - source=paginated_leaderboard.Source(memeList, "Memes", discord.Colour.blue()), - clear_reactions_after=True) - await pages.start(ctx) + return await MemesList(ctx=ctx).send() @commands.command(name="Pjoke") @help.Category(category=Category.Fun) diff --git a/cogs/slash/football_slash.py b/cogs/slash/football_slash.py index 0f75eee..b930b97 100644 --- a/cogs/slash/football_slash.py +++ b/cogs/slash/football_slash.py @@ -24,7 +24,7 @@ class FootballSlash(commands.Cog): @_jpl_group.command(name="table", description="Huidige rangschikking") async def _jpl_table_slash(self, ctx: ApplicationContext): await ctx.response.defer() - await ctx.respond(get_table()) + await ctx.send_followup(get_table()) @_jpl_group.command(name="update", description="Update de code voor deze competitie (owner-only)", default_permission=False) @permissions.is_owner() diff --git a/cogs/slash/fun_slash.py b/cogs/slash/fun_slash.py index 00c3c24..3e69a8c 100644 --- a/cogs/slash/fun_slash.py +++ b/cogs/slash/fun_slash.py @@ -1,10 +1,34 @@ from discord.ext import commands -from discord.commands import slash_command, ApplicationContext, Option +from discord.commands import slash_command, ApplicationContext, Option, AutocompleteContext +from functions.database import memes +from functions.database.memes import getAllMemes from data.embeds.xkcd import XKCDEmbed +from data.menus.memes import MemesList +from functions.memes import generate +from functions.stringFormatters import title_case from startup.didier import Didier +all_memes = getAllMemes() + + +def autocomplete_memes(ctx: AutocompleteContext) -> list[str]: + starting = [] + containing = [] + + val = ctx.value.lower() + + # First show matches that start with this word, then matches that contain it + for meme in all_memes: + if meme[1].startswith(val): + starting.append(title_case(meme[1])) + elif val in meme[1]: + containing.append(title_case(meme[1])) + + return [*starting, *containing] + + class FunSlash(commands.Cog): def __init__(self, client: Didier): self.client: Didier = client @@ -15,6 +39,32 @@ class FunSlash(commands.Cog): ): return await ctx.respond(embed=XKCDEmbed(num).create()) + @slash_command(name="memes", description="Lijst van memegen-memes") + async def _memes_slash(self, ctx: ApplicationContext): + return await MemesList(ctx=ctx).respond() + + @slash_command(name="memegen", description="Genereer memes") + async def _memegen_slash(self, ctx: ApplicationContext, + meme: Option(str, description="Naam van de template", required=True, autocomplete=autocomplete_memes), + field1: Option(str, required=True), + field2: Option(str, required=False, default=""), + field3: Option(str, required=False, default=""), + field4: Option(str, required=False, default="")): + # Get the meme info that corresponds to this name + result: memes.Meme = memes.getMeme(meme) + + # No meme found + if result is None: + return await ctx.respond("Deze meme staat niet in de database.", ephemeral=True) + + await ctx.response.defer() + + fields = (field1, field2, field3, field4) + generated = generate(result, fields) + + # Send generated meme or error message + await ctx.send_followup(generated["message"]) + def setup(client: Didier): client.add_cog(FunSlash(client)) diff --git a/data/menus/memes.py b/data/menus/memes.py new file mode 100644 index 0000000..0c3fe66 --- /dev/null +++ b/data/menus/memes.py @@ -0,0 +1,26 @@ +from dataclasses import dataclass, field + +from data.menus.paginated import Paginated +from functions import stringFormatters +from functions.database import memes + + +@dataclass +class MemesList(Paginated): + title: str = field(default="Memes") + + def __post_init__(self): + self.data = self.get_data() + + def get_data(self) -> list[tuple]: + data = [] + meme_list = memes.getAllMemes() + for meme in sorted(meme_list, key=lambda x: x[1]): + name = stringFormatters.title_case(meme[1]) + fields = meme[2] + data.append((name, fields,)) + + return data + + def format_entry(self, index: int, value: tuple) -> str: + return f"{value[0]} ({value[1]})" diff --git a/functions/memes.py b/functions/memes.py index 4ffa2e4..a38d03c 100644 --- a/functions/memes.py +++ b/functions/memes.py @@ -10,6 +10,8 @@ def generate(meme: Meme, fields): """ Main function that takes a Meme as input & generates an image. """ + fields = list(fields) + # If there's only one field, the user isn't required to use quotes if meme.fields == 1: fields = [" ".join(fields)] @@ -37,11 +39,14 @@ def generate(meme: Meme, fields): # Adding a message parameter makes the code in the cog a lot cleaner if not reply["success"]: + reply["success"] = False reply["message"] = "Error! Controleer of je de juiste syntax hebt gebruikt. Gebruik het commando " \ "\"memes\" voor een lijst aan geaccepteerde meme-namen." else: reply["message"] = reply["data"]["url"] + reply["success"] = False + return reply @@ -77,7 +82,8 @@ def _apply_meme(meme: Meme, fields): 102156234: mocking_spongebob, 91538330: _x_x_everywhere, 252600902: _always_has_been, - 167754325: _math_is_math + 167754325: _math_is_math, + 206493414: _i_used_the_x_to_destroy_the_x } # Meme needs no special treatment @@ -104,6 +110,12 @@ def _always_has_been(fields): def _math_is_math(fields): + word = fields[0].upper() + + return ["", f"{word} IS {word}!"] + + +def _i_used_the_x_to_destroy_the_x(fields): word = fields[0] - return [f"{word.upper()} IS {word.upper()}!"] + return ["", f"I used the {word} to destroy the {word}"]