Part 5 - Command Groups & Subcommands#

Create a new file named fun.py in the extensions folder - this will contain our bot’s second extension.

In fun.py paste the following:

 1import hikari
 2import lightbulb
 3
 4fun_plugin = lightbulb.Plugin("Fun")
 5
 6
 7@fun_plugin.command
 8@lightbulb.command("fun", "All the entertainment commands you'll ever need!")
 9@lightbulb.implements(lightbulb.SlashCommandGroup)
10async def fun_group(_: lightbulb.SlashContext) -> None:
11    pass  # as slash commands cannot have their top-level command run, we simply pass here
12
13
14@fun_group.child
15@lightbulb.command("meme", "Get a meme!")
16@lightbulb.implements(lightbulb.SlashSubCommand)
17async def meme_subcommand(ctx: lightbulb.SlashContext) -> None:
18    async with ctx.bot.d.client_session.get("https://meme-api.com/gimme") as res:
19        if not res.ok:
20            await ctx.respond(
21                f"API returned a {res.status} status :c",
22                flags=hikari.MessageFlag.EPHEMERAL,
23            )
24            return
25
26        data = await res.json()
27
28        if data["nsfw"]:
29            await ctx.respond(
30                "Response was NSFW, couldn't send :c",
31                flags=hikari.MessageFlag.EPHEMERAL,
32            )
33            return
34
35        embed = hikari.Embed(colour=0x3B9DFF)
36        embed.set_author(name=data["title"], url=data["postLink"])
37        embed.set_image(data["url"])
38
39        await ctx.respond(embed)
40
41def load(bot: lightbulb.BotApp) -> None:
42    bot.add_plugin(fun_plugin)
  • Line 4 - Create a new plugin named Fun

  • Line 7 - Decorator to attach the following command to the plugin

  • Line 8 - Decorator to create the command, setting the name to “fun” and adding a description

  • Line 9 - Convert the decorated function into a SlashCommandGroup

  • Line 10 - The command’s function

  • Line 11 - pass the function, as slash commands cannot have their top-level command run

  • Line 14 - attach the decorated function to the fun_group command group

  • Line 15 - Decorator to create the subcommand, setting the name to meme and adding a description

  • Line 16 - Convert the decorated function into a SlashSubCommand

  • Line 17 - The subcommand’s function

  • Line 18 - Using the client_session from the bot.d data store that we created in the previous section, get a meme from the Meme API
    Read the docs - aiohttp.ClientSession

  • Line 19-24 - If the response returned status code that wasn’t “ok”,

    • Respond with a helpful ephemeral message to the command author

    • return so that no further code in the function is run

  • Line 26 - The response is ok, get the json from it

  • Line 28-33 - If the response is NSFW (Not Safe For Work), we don’t want to send it.

    • Again, we send an ephemeral message to the command author and return so no further code is run

  • Line 35-39 - If the response is ok and the meme is not NSFW, then

    • Line 35 - Create an embed

    • Line 36 - Set the embed’s author to the meme’s title and link

    • Line 37 - Set the embed’s image to the meme’s image url

    • Line 39 - Respond to the interaction with the embed

Note

Using the Meme API Documentation, you could customise this command.

For example:

  • Add an option to choose which subreddit to get the meme from

  • Make a /bulk-meme command which fetches multiple memes in one go

Now, let’s test it!

meme

and if we can’t fetch a meme:

api error