Discord.py — Проверьте, есть ли у пользователя определенные роли?

#python #discord #discord.py

Вопрос:

Я пытаюсь создать команду, которая может запрещать людей на Сервере и тех, кто не находится на сервере. Но есть проблема: если я использую async def ban(ctx, member: discord.Member, *, reason): для использования атрибут «роли», то он не сможет запретить тех, кого нет на сервере. Если я использую async def ban(ctx, member: discord.User, *, reason): , я не смогу использовать атрибут «роли», потому что это не атрибут.

Зачем я это делаю? Я пытаюсь сделать так, чтобы модераторы сервера не могли запретить тем, у кого есть роли модераторов

Код:

 async def ban(ctx, member: discord.User = None, *, reason=None):
    if get(ctx.author.roles, id=866038959980544050) or get(ctx.author.roles, id=866436325503008768) or get(
            ctx.author.roles, id=866441730631008316) or ctx.author.guild_permissions.administrator:  # Check if the author has the Role "Moderator", "Admin", etc.

        if get(member.roles, id=867371024466968596) or get(member.roles, id=867132420489871411) and not ctx.author.guild_permissions.administrator:  # Check if the member has the Role "Moderator", "Admin", etc.
            await ctx.send("You cannot ban this user.")
 

Ответ №1:

Предполагая, что вы используете команды discord.ext., вы могли бы использовать ввод текста.Конвертер союзов, чтобы убедиться, что аргумент является либо пользователем, либо участником.

 import typing

[...]

async def ban(ctx, user: typing.Union[discord.Member, discord.User]):
 

Обратите внимание, что порядок имеет значение: discord.Member сначала он пытается применить этот конвертер , прежде чем пытаться discord.User , таким образом, отдавая приоритет преобразованию в участника, а не преобразованию в пользователя (что должно быть тем, что вы хотите).

Чтобы различить эти два случая, теперь вы можете проверить, соответствует ли user тип discord.Member , и выполнить проверку.

     if type(user) is discord.Member:
        if YOUR_CHECKS:
            await ctx.send('You cannot ban this user')
            return

    # Perform ban
    await ctx.send('Ban successful')
 

При тестировании я обнаружил, что библиотека команд выдаст вам числовой идентификатор пользователя вместо реального пользователя и покажет
Failed fetching discord object! Passing ID instead. в качестве предупреждения. Если вам нужно больше, чем просто идентификатор пользователя, вы можете преобразовать его в пользовательский объект с помощью

     if type(user) is int:
        user = await bot.fetch_user(user)
        if user is None:
            await ctx.send('User not found')
            return
 

Обратите внимание, что fetch_user это вызов API, и вы, возможно, захотите избежать его. Смотрите документы для получения дополнительной информации.

Ответ №2:

Одним из способов сделать это было бы проверить, входит ли данный member игрок в текущую гильдию. Если это так True , вы можете создать новый member object с их идентификатором или другим предпочтительным методом, в противном случае вы можете предположить, что у них нет роли модератора. Для простоты я включил проверку только для одной роли, но вы можете настроить ее так, как хотите. Кроме этого, все остальное более подробно объясняется в приведенном ниже коде.

 if member in ctx.guild.members: # checks if the provided member is in the current server
    member = ctx.guild.get_member(member.id) # Get the member object of the user
    if get(member.roles, id=866038959980544050): # Check if this role is in the member's roles
        await ctx.send("This member has <@amp;866038959980544050>")
    else:
        await ctx.send("This member does not have <@amp;866038959980544050>")
    return # returns, since member was in the server
# This happens if the provided member is not in the current server
await ctx.send("This member, who is not in this server, does not have <@amp;866038959980544050>")
 

Код выше работает так, как написано

Ответ №3:

Вы должны использовать это

 @bot.command(...)
@commands.has_any_role(role id)
...