Part 7 - Miru, an optional component handler#
Miru is an optional component handler for hikari, making it simpler to add components to messages, and to handle component interactions.
We’ll need to edit bot.py
a little bit to get miru working.
At the top of the file, import miru:
import miru
And just above bot.load_extensions_from("./extensions/")
add:
miru.load(bot)
Now we need to edit fun.py
.
At the top of the file, import miru:
import miru
And now beneath our animal
command, add the following:
1class AnimalView(miru.View):
2 def __init__(self, author: hikari.User) -> None:
3 self.author = author
4 super().__init__(timeout=60)
5
6 @miru.text_select(
7 custom_id="animal_select",
8 placeholder="Pick an animal",
9 options=[
10 miru.SelectOption(name, name.lower().replace(" ", "_"), emoji=emoji)
11 for name, emoji in ANIMALS.items()
12 ],
13 )
14 async def select_menu(self, select: miru.TextSelect, ctx: miru.ViewContext) -> None:
15 animal = select.values[0]
16 async with ctx.app.d.client_session.get(
17 f"https://some-random-api.com/animal/{animal}"
18 ) as res:
19 if not res.ok:
20 await ctx.edit_response(
21 f"API returned a {res.status} status :c", components=[]
22 )
23 return
24
25 data = await res.json()
26 embed = hikari.Embed(description=data["fact"], colour=0x3B9DFF)
27 embed.set_image(data["image"])
28
29 animal = animal.replace("_", " ")
30
31 await ctx.edit_response(
32 f"Here's a {animal} for you! :3", embed=embed, components=[]
33 )
34
35 async def on_timeout(self) -> None:
36 await self.message.edit("The menu timed out :c", components=[])
37
38 async def view_check(self, ctx: miru.ViewContext) -> bool:
39 return ctx.user.id == self.author.id
40
41
42@fun_group.child
43@lightbulb.command("animal2", "Get a fact + picture of a cute animal :3")
44@lightbulb.implements(lightbulb.SlashSubCommand)
45async def animal_subcommand_2(ctx: lightbulb.SlashContext) -> None:
46 view = AnimalView(ctx.author)
47 resp = await ctx.respond(
48 "Pick an animal from the dropdown :3", components=view.build()
49 )
50
51 await view.start(resp)
52 await view.wait()
This new animal2
command produces the exact same result as the first animal
command, but it’s much easier to read and understand at a glance, and adding buttons or more select menus would be incredibly easy.
Line 1 - Subclass
miru.View
, to create our customAnimalView
classLine 4 - Initialise our view with a timeout of 60 seconds
Line 6-13 - Create our select menu, with the same custom ID, placeholder and options as before
Line 14-33 - Perform the same request as before, and respond to the interaction with an embed
Line 35-39 - Set our timeout function, and a view check
Read the docs - View Checks & Timeout HandlingLine 42-44 - Create a second animal command, called “
animal2
”Line 46 - Create an instance of
AnimalView
Line 47-49 - Respond to the command interaction with our message and components
Line 51 - Start the view
Line 52 - Wait for the view to finish
Note
If you want to learn how to use buttons and more with Miru, check out the Miru guides, written by Miru’s creator: https://hikari-miru.readthedocs.io/en/latest/getting-started.html