disnake

Форк
0
/
low_level_components.py 
123 строки · 4.9 Кб
1
# SPDX-License-Identifier: MIT
2

3
"""An example on how to send and process components without using views."""
4

5
import os
6

7
import disnake
8
from disnake.ext import commands
9

10
bot = commands.Bot(command_prefix=commands.when_mentioned)
11

12

13
# As an alternative to using views, it is possible to use a more low-level approach to components.
14
# Firstly, components do not have to be sent as part of a view. Instead, they can be sent as-is.
15
# Take special note of the fact that `custom_id`s have been explicitly set on these components.
16

17
# The main advantage of this is that listeners are, by nature, persistent.
18
# Each listener is stored on the bot strictly once, and are shared by all components.
19
# Because of this, their memory footprint will generally be smaller than that of an equivalent view.
20

21

22
@bot.command()
23
async def send_button(ctx: commands.Context):
24
    await ctx.send(
25
        "Here's a button!",
26
        components=disnake.ui.Button(label="Click me!", custom_id="cool_button"),
27
    )
28

29

30
@bot.command()
31
async def send_select(ctx: commands.Context):
32
    await ctx.send(
33
        "Here's a select!",
34
        components=disnake.ui.StringSelect(options=["1", "2", "3"], custom_id="cool_select"),
35
    )
36

37

38
# To send multiple components, they can simply be stored in a list. They will then automatically
39
# fill out rows as they fit, similar to views if `row` is not set on the components. If a specific
40
# row ordering is desired, simply store them in a list of lists or `disnake.ui.ActionRow`s instead:
41

42

43
@bot.command()
44
async def send_all_the_buttons(ctx: commands.Context):
45
    buttons = []
46
    for y in range(4):
47
        row = disnake.ui.ActionRow()
48
        buttons.append(row)
49
        for x in range(4):
50
            row.add_button(label=f"({x}, {y})", custom_id=f"gridbutton_{x}_{y}")
51

52
    await ctx.send("Here's a 4x4 grid of buttons:", components=buttons)
53

54

55
# As-is, the components sent by these commands will do absolutely nothing. To remedy this, you
56
# would use a listener. Think of the listener as an equivalent to a view button's callback.
57
# However, the listener would function as a callback for **all** buttons. This is where the
58
# `custom_id` comes in: by filtering for the correct custom_id, a listener can be made to respond
59
# to a specific range of components.
60

61

62
# In this case, listening for only buttons is sufficient, thus the `on_button_click`-event is used.
63
# The equivalent event for select menus is `on_dropdown`. For modals, this is `on_modal_submit`.
64
# Finally, for _any_ kind of message interaction, the relevant event is `on_message_interaction`.
65

66

67
@bot.listen("on_button_click")
68
async def cool_button_listener(inter: disnake.MessageInteraction):
69
    if inter.component.custom_id != "cool_button":
70
        # Since `inter.component` returns the component that triggered the interaction,
71
        # this is used to filter interactions for components other than the button we wish to
72
        # process with this listener.
73
        return
74

75
    # Thus, we end up with only buttons sent by the `send_button` command,
76
    # since those buttons were sent with `custom_id=cool_button`.
77
    # At this point, this listener is practically identical to the callback of a view button.
78
    await inter.response.send_message("You clicked the cool button!")
79

80

81
# Similarly, a listener for the select menu can be created:
82

83

84
@bot.listen("on_dropdown")
85
async def cool_select_listener(inter: disnake.MessageInteraction):
86
    if inter.component.custom_id != "cool_select":
87
        # The same principle as for the button, any selects with the wrong `custom_id` are ignored.
88
        return
89

90
    await inter.response.send_message(f"You selected {inter.values}!")
91

92

93
# Lastly, a more generic type of listener for the example with multiple buttons:
94

95

96
@bot.listen("on_button_click")
97
async def grid_listener(inter: disnake.MessageInteraction):
98
    if not inter.component.custom_id or not inter.component.custom_id.startswith("gridbutton"):
99
        # The same principle again, except this time we want all buttons that start with grid_button,
100
        # as there are now 16 different `custom_id`s. This is a much better idea than making 16
101
        # different listeners, one for each button, of course!
102
        return
103

104
    # Now we can extract the x/y data...
105
    _, x, y = inter.component.custom_id.split("_")
106
    await inter.response.send_message(f"You hit ({x}, {y}). You sunk my battleship!")
107

108

109
# Since these `custom_id`s are stored on the buttons and the listeners aren't dependent on any kind
110
# of state, the components handled this way will remain fully functional over bot reloads!
111

112
# Note that listeners can also be added inside of cogs. For this, the only changes that would have
113
# to be made are to use `commands.Cog.listener` instead of `bot.listen`, and the first argument of
114
# the listener would have to be `self`.
115

116

117
@bot.event
118
async def on_ready():
119
    print(f"Logged in as {bot.user} (ID: {bot.user.id})\n------")
120

121

122
if __name__ == "__main__":
123
    bot.run(os.getenv("BOT_TOKEN"))
124

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.