Persistent View Disnake
При создании выпадающего списка и перезагрузке бота, перестает работать список. Знаю что нужно использовать timeout=None
и bot.add_view
. У меня есть
dropdown_view=RolesDropdownView(options=options, placeholder=placeholder, min_values=min_value, max_values=max_value)
Тоесть это генератор списков по параметрам из слэш команды. Данные динамические. В примере регистрируют view
без аргументов и всё получается, но как мне зарегистрировать его когда у меня динамические данные и я незнаю что отправлять туда. Пробовал после отправки сообщения регистрировать view
эффекта не дало.
if frequency == 0.0:
message = await to_channel.send(message.content, files=files, view=dropdown_view, embeds=embeds) # type: ignore
inter.bot.add_view(view=dropdown_view, message_id=message.id) # type: ignore
await inter.response.send_message("Объявление опубликовано")
И правильно ли то что я для каждого view
использую новый custom_id.
UPD: Или мне надо каждый раз где то сохранять данные View
и сообщения и отправлять их при старте бота.
UPD: пример: main.py
import disnake
import os
from disnake.ext import commands
from typing import List
intents = disnake.Intents.all()
class Bot(commands.InteractionBot):
async def on_ready(self):
print("Bot Started!")
bot = Bot(intents=intents)
bot.load_extension("cogs.cogs")
bot.run(os.environ["discord_bot_token"])
cogs/cogs.py
import disnake
import json
from disnake.ext import commands,
from typing import List
from cogs.views import RolesDropdownView
class UtilsCommand(commands.Cog):
def __init__(self, bot: commands.Bot) -> None:
self.bot = bot
@commands.slash_command(description="Создание меню выбора", dm_permission=False, name="menu_creator")
@commands.default_member_permissions(administrator=True)
async def create_dropdown(
self,
inter: disnake.GuildCommandInteraction,
schema: str = commands.Param(description="схема в json формате для меню"),
to_channel_id: int = commands.Param(name="канал", description="В какой канал отправить", large=True),
)
):
channel = inter.bot.get_channel(to_channel_id)
if channel is None:
await inter.response.send_message("Неверный ID канала")
return None
converted_schema = json.loads(schema)
message = converted_schema["content"]
options = []
placeholder = converted_schema["placeholder"]
min_value = converted_schema["min_value"]
max_value = converted_schema["max_value"]
components = converted_schema["components"]
for component in components:
emoji_info = component["emoji"]
emoji = None
if "name" in emoji_info:
emoji = disnake.utils.get(inter.guild.emojis, name=emoji_info["name"])
option = disnake.SelectOption(
label=component["label"], value=component["value"], default=component["default"], emoji=emoji
)
options.append(option)
dropdown_view = RolesDropdownView(
options=options, placeholder=placeholder, min_values=min_value, max_values=max_value
)
message = await channel.send(content=message, view=dropdown_view) # type: ignore
inter.bot.add_view(view=dropdown_view, message_id=message.id)
await inter.response.send_message("Объявление опубликовано")
def setup(bot: commands.Bot):
bot.add_cog(UtilsCommand(bot))
cogs/views.py
from typing import List
import disnake
import secrets
class BaseDropdown(disnake.ui.StringSelect):
def __init__(
self,
options: List[disnake.SelectOption],
placeholder: str,
custom_id: str,
max_values: int = -1,
min_values: int = 1,
):
super().__init__(
placeholder=placeholder,
min_values=min_values,
max_values=len(options) if max_values == -1 else max_values,
options=options,
custom_id=custom_id,
)
class RolesDropdown(BaseDropdown):
def __init__(
self, options: List[disnake.SelectOption], placeholder: str, max_values: int = -1, min_values: int = 1
):
custom_id = f"RolesDropdown:{secrets.token_urlsafe(8)}"
super().__init__(
options,
placeholder,
custom_id,
max_values,
min_values,
)
async def callback(self, inter: disnake.MessageInteraction) -> None:
for value in inter.values:
role = disnake.utils.get(inter.guild.roles, name=value)
if role is None:
await inter.response.send_message("Роль не найдена", ephemeral=True)
return None
await author.add_roles(role) # type: ignore
await inter.response.send_message("Роли успешно обновлены", ephemeral=True)
class RolesDropdownView(disnake.ui.View):
def __init__(self, options: List[disnake.SelectOption], placeholder: str, min_values: int, max_values: int):
super().__init__(timeout=None)
self.add_item(RolesDropdown(options, placeholder, min_values=min_values, max_values=max_values))
json для генерации списка
{
"content": "",
"placeholder": "Выберите роль здесь",
"min_value": 1,
"max_value": -1,
"components": [
{
"label": "Удалить все роли",
"value": "remove all",
"default": false,
"emoji": {
"name": "redcrossmark"
}
},
{
"label": "Steam",
"emoji": {
"name": "Steam"
},
"value": "Steam",
"default": false
}
]
}