Вопрос или проблема
В данный момент я программирую ролевого бота для небольшого сообщества на Discord, чтобы изучить Python 3 и библиотеку Discord в целом. Я пробовал разные решения в интернете, но явно что-то упускаю. Надеялся на какую-нибудь подсказку или идею о том, что не так, так как ошибок не выводится.
@client.event
async def on_ready():
channel = client.get_channel(<ChannelID>) #установить канал на #rules
если isinstance(channel, discord.TextChannel):
text = "Пожалуйста, прочитайте #rules и отреагируйте для подтверждения."
emoji = await channel.send(text)
await emoji.add_reaction('✅')
#Когда реакция
@client.event
async def on_reaction_add(reaction, author):
channel = client.get_channel(<ChannelId>) #Обновление канала как резерв
если reaction.message.channel is not None и channel:
return
если reaction.emoji == "✅":
author = reaction.author
роль = await reaction.author.guild.get_role(<RoleID>)
await author.add_roles(роль) #Проверяет на правильную реакцию и добавляет роль
reaction.message.delete()
Я пытался импортировать дополнительные библиотеки, такие как typing, для дополнительных функций, пробовал async On_Reaction, On_Ready и даже On_Message. У меня есть библиотека эмодзи на случай, если это была проблема. Роль для бота выше, чем роль, которую он пытается назначить, бот имеет права модератора, права членов гильдии и все разрешения, которые могут быть полезны для этого в моем понимании, а именно:
Читать историю сообщений
Создавать выражения
Создавать реакции
Модерировать участников
Управлять ролями
Создавать сообщения
Я также пробовал user.guild.roles и author.guild.roles для назначения.
В вашем фрагменте есть несколько ошибок. Первое — это то, что событие on_reaction_add определено внутри события on_ready, что может не сработать, так как это не поддерживается. Второе, в документации у нас есть discord.on_reaction_add(reaction, user), который имеет параметры класса discord.Reaction и (Union[discord.Member, discord.User]). Вы пытаетесь получить это:
await reaction.author.guild.get_role(<RoleID>)
https://discordpy.readthedocs.io/en/stable/api.html#discord.Reaction, отсюда правильный способ сделать это:
await reaction.message.guild.get_role(<RoleID>)
Тогда у нас есть это:
author = reaction.author
вы уже имеете автора, поэтому не должно быть причин пытаться получить его по-другому. Событие возвращает реакцию и пользователя, где пользователь — это человек, который отреагировал.
Проверьте документацию здесь: https://discordpy.readthedocs.io/en/stable/api.html, найдите discord.on_reaction_add
Ответ или решение
Создание бота для ролей в Discord может показаться сложной задачей, особенно если учесть множество деталей, которые могут стать причиной проблем. Основываясь на предоставленной информации, давайте разберем основные аспекты, которые могут привести к тому, что бот успешно подключается, но не обновляет роли.
1. Определение события обработки реакций
Как вы указали, код для обработчика событий on_reaction_add
был помещен внутрь on_ready
. Это недостаток структуры, так как вышестоящие функции как on_ready
могут вызывать нежелательное поведение у вложенных обработчиков. Необходимо вынести обработчик on_reaction_add
на тот же уровень, что и обработчик on_ready
, чтобы Discord мог правильно распознать его.
2. Параметры и использование объекта реакции
Согласно документации Discord.py, основной целью этого события является получение реакций. Вместо того чтобы использовать reaction.author
, необходимо использовать второй параметр, который передается в on_reaction_add
, чтобы получить пользователя, добавившего реакцию. Ваша запись должна выглядеть следующим образом:
@client.event
async def on_reaction_add(reaction, user):
3. Получение роли и добавление ее пользователю
Ваш код содержит ошибку в способе получения роли. Вместо использования reaction.author
, вы должны использовать user
, который передается в качестве второго аргумента. Также следует убедиться, что вы используете правильный метод получения роли:
role = reaction.message.guild.get_role(<RoleID>)
4. Доступ к нужным каналам и проверка разрешений пользователя
Обратите внимание, что у вашего бота должны быть необходимые разрешения для управления ролями, а также для чтения и отправки сообщений в том канале, где он работает.
Вот пример исправленного кода:
@client.event
async def on_ready():
channel = client.get_channel(<ChannelID>) # Установите свой ChannelID
if isinstance(channel, discord.TextChannel):
text = "Пожалуйста, прочитайте #правила и добавьте реакцию для подтверждения."
await channel.send(text)
after_message = await channel.send('✅')
await after_message.add_reaction('✅')
@client.event
async def on_reaction_add(reaction, user):
if user.bot: # Игнорировать реакции от ботов
return
if reaction.emoji == "✅" and reaction.message.channel.id == <ChannelID>: # Проверить, что реакция добавлена в нужный канал
role = reaction.message.guild.get_role(<RoleID>) # Получить роль по ID
member = reaction.message.guild.get_member(user.id) # Получить члена сервера
if role is not None and member is not None:
await member.add_roles(role) # Добавить роль пользователю
5. Проверка отладочной информации
Если бот продолжает не добавлять роли, включите отладочную информацию, чтобы видеть, доходят ли запросы до обработчика. Например, вы можете добавить print()
-выражения, чтобы проверить, выполняются ли функции.
print(f'{user.name} добавил реакцию.')
Заключение
Следуя этим советам, вы сможете устранить проблемы с вашим ботом и привести его в рабочее состояние. Не забудьте проверить разрешения, убедиться в том, что все идентификаторы правильные, и, что самое важное, избегайте вложенности функций события. Это основные моменты, которые помогут улучшить ваш код и обеспечить его корректную работу.