Discord.py Bot的权限系统

时间:2018-02-04 20:18:57

标签: python python-3.x python-asyncio discord discord.py

我正在使用discord.py和asyncio制作一个discord bot。机器人具有kickban等命令,显然不应该为普通用户所用。

我想创建一个简单的系统,该系统将使用ctx.message.author检测用户角色拥有的权限,以获取发送命令的用户。

我不希望机器人检测到特定的角色名称,因为这些角色因服务器而异。我也不希望机器人有多个文件来保持简单。

我已经看过discord.py文档和其他各种来源,但没有包含如何实现他们所讨论的各种方法的示例。

例如,这是我的机器人的一个命令:

async def kick(ctx, userName: discord.User):
    if True: #ctx.message.author.Permissions.administrator
        await BSL.kick(userName)
    else:
        permission_error = str('Sorry ' + ctx.message.author + ' you do not have permissions to do that!')
        await BSL.send_message(ctx.message.channel, permission_error)

if else声明是我自己尝试这样做的地方。 #ctx.message.author.Permissions.administrator已注释掉,因为它不起作用,并替换为True以进行测试。

感谢您提前提供任何帮助和建议。

3 个答案:

答案 0 :(得分:3)

Permissions是该类的名称。要获取消息作者权限,您应该访问作者的server_permissions属性。

if ctx.message.author.server_permissions.administrator:
 # you could also use server_permissions.kick_members

更新

验证调用命令的人员的权限的更好方法是使用commands扩展名的check功能,特别是has_permissions检查。例如,如果您只想向拥有manage_roles权限或ban_members权限的人员打开您的命令,您可以像这样编写命令:

from discord import Member
from discord.ext.commands import has_permissions, MissingPermissions

@bot.command(name="kick", pass_context=True)
@has_permissions(manage_roles=True, ban_members=True)
async def _kick(ctx, member: Member):
    await bot.kick(member)

@_kick.error
async def kick_error(error, ctx):
    if isinstance(error, MissingPermissions):
        text = "Sorry {}, you do not have permissions to do that!".format(ctx.message.author)
        await bot.send_message(ctx.message.channel, text)

答案 1 :(得分:1)

您还可以使用装饰器。

 getComponent(props = {} || this.props, state) {
    switch (this.state.weather) {
      case !this.fetchedweatherdata:
        return (
          <DisplayWeather
            currentweather={this.state.currentweather}
            currentforecast={this.state.currentforecast}
            currenttime={this.state.currenttime}
          />
        );

      case !this.hourlyWeather:
        return (
          <DisplayHourlyWeather hourlyWeather={this.state.hourlyWeather} />
        );

      case this.fetchedweatherdata:
        return <Form loadWeather={this.fetchWeatherData} />;

      default:
        return null;
    }
  }

检查用户和漫游器权限的优势意味着,通过提供有用的“权限不足”错误消息,可以更轻松地处理错误。

答案 2 :(得分:0)

提示被接受的答案可能无效:

  1. discord.py库的重写版本和预重写版本可能存在兼容性问题,这些版本仍然不作废,不推荐使用并且仍在使用。

  2. 该机器人还应该检查其自身的权限,以排除导致错误的原因。

  3. 如果出现错误,或者对漫游器本身的权限无效,则漫游器应该说些什么,对吗?

  4. 需要实施某些措施以防止漫游器尝试在DM或组上下文中使用此命令。几乎总是错误。

我提出以下解决方案(假设您使用命令扩展名):

import discord
from discord.ext import commands
import time
@bot.command(pass_context=True,description="Kicks the given member. Please ensure both the bot and the command invoker have the permission 'Kick Members' before running this command.")
async def kick(ctx, target:discord.Member):
    """(GUILD ONLY) Boot someone outta the server. See 's!kick' for more."""
    if not str(ctx.message.channel).startswith("Direct Message with "):
        msg=await bot.say("Checking perms...")
        time.sleep(0.5)
        if ctx.message.server.me.server_permissions.kick_members:
            if ctx.message.author.server_permissions.kick_members:
                await bot.edit_message(msg,new_content="All permissions valid, checking issues with target...")
                time.sleep(0.5)
                if target==ctx.message.server.owner:
                    await bot.edit_message(msg, new_content="All permissions are correct, but you're attempting to kick the server owner, whom you can't kick no matter how hard you try. Whoops!")
                else:
                    if target==ctx.message.server.me:
                        await bot.edit_message(msg, new_content="Whoops! All permissions are corrent, but you just tried to make me kick myself, which is not possible. Perhaps you meant someone else, not poor me?")
                    else:
                        await bot.edit_message(msg, new_content="All permissions correct, and no issues with target being self or server owner, attempting to kick.")
                        time.sleep(2)
                        try:
                            await bot.kick(target)
                            await bot.edit_message(msg, ":boom: BAM! ***kicc'd***")
                        except Exception:
                            await bot.edit_message(msg, new_content="I was unable to kick the passed member. The member may have a higher role than me, I may have crashed into a rate-limit, or an unknown error may have occured. In that case, try again.")
            else:
                await bot.edit_message(msg, new_content="I've the correct permissions, {}, but you do not. Perhaps ask for them?").format(ctx.message.author.mention)
        else:
            await bot.edit_message(msg, new_content="I'm just a poor bot with no permissions. Could you kindly grant me the permission `Kick Members`? Thanks! :slight_smile:")
    else:
        await bot.say("'Tis a DM! This command is for servers only... try this again in a server maybe? :slight_smile:")