【问题标题】:How do I make Discord.py bot remove roles sooner?如何让 Discord.py 机器人更快地删除角色?
【发布时间】:2021-09-17 10:17:54
【问题描述】:

我制作了一个自动添加和删除角色的机器人。一切正常,但添加在运行命令后的 15/20 秒内起作用。移除过程最多需要 15 分钟。

我做错了什么?几个月前我开始编程并开始使用 Python,所以任何提示都是有用的。

guildid、channelid 和 roleid 现在是数字,我把占位符放进去。


    @tasks.loop(seconds=10)
    async def autoderolergame():
        tasks = []
        guild = client.get_guild(guildid)
        channel = guild.get_channel(channelid)
        role = guild.get_role(roleid)
        for member in guild.members:
            if member not in channel.members:
                try:
                    await member.remove_roles(role, reason='Leaving Voice channel')
                except:
                    pass
            if str(member.status) == 'offline':
                try:
                    await member.remove_roles(role, reason='Going offline, so no more VIP rain')
                except:
                    pass

我也尝试用 'for member in guild.members' 代替 'guild.fetch_members() 中成员的异步:' 遗憾的是,这并没有什么不同。

我正在考虑在频道中保存用户列表并每 10 秒更新一次,然后查看列表并选择不再在频道中的所有用户,删除角色,然后将其从列表中删除,那会是更好的解决方案吗? 我宁愿不这样做,因为我想使用 Discord.py 的内置函数。

感谢您的帮助!

【问题讨论】:

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


    【解决方案1】:

    您可以使用异步方法使其更快

    import asyncio
    
    remove_roles_semaphore = asyncio.Semaphore(20)
    
    async def remove_role(member, role, reason):
        async with remove_roles_semaphore:
            try:
                await member.remove_roles(role, reason=reason)
            except:
                pass
    
    
    @tasks.loop(seconds=10)
    async def autoderolergame():
        guild = client.get_guild(guildid)
        channel = guild.get_channel(channelid)
        role = guild.get_role(roleid)
    
        tasks = []
    
        for member in guild.members:
            if member not in channel.members:
                tasks.append(remove_role(member, role, 'Leaving Voice channel')
            if str(member.status) == 'offline':
                tasks.append(remove_role(member, role, 'Going offline, so no more VIP rain')
    
        await asyncio.gather(*tasks)
    

    尽管请记住,您很容易为此受到速率限制,但如果您达到全局速率限制(每秒 50 个请求),您可能会被禁止。使用此方法需要您自担风险(您可能希望启用 logging 以查看任何速率限制警告)

    我使用asyncio.Semaphore 来限制并发请求的数量,可以随意更改值,但请记住——值越高,被禁止的机会就越高(不要超过 50)。

    遗憾的是,我无法真正测试代码,所以我不能保证它会更快。

    【讨论】:

    • 也试过了,但是没有信号量,遗憾的是没有什么不同。认为这会诚实地工作。但我可能会尝试使用信号量选项,这可能会有所作为。谢谢回答我的问题。我会在一两天后尝试报告,让您知道它是否有效!
    • 如果没有信号量它不能工作,如果你添加它会更慢。我只是用它来限制同时运行的协程的数量。如果这不起作用,我真的认为这里没有答案可悲
    • 我很害怕,Discord 服务不太喜欢它。感谢您查看并尝试帮助我。
    【解决方案2】:

    我找到了解决问题的方法。 我在用代码查看所有的公会成员。

    由于我希望在离开频道时删除角色,我只需要查看用户拥有的角色,然后检查他们是否仍在房间中。

    这是我的新代码:

        @tasks.loop(seconds=10)
        async def autoderolergame():
            tasks = []
            guild = client.get_guild(guildid)
            channel = guild.get_channel(channelid)
            role = guild.get_role(roleid)
            for member in role.members: (<-- only changed this from guild to role)
                if member not in channel.members:
                    try:
                        await member.remove_roles(role, reason='Leaving Voice channel')
                    except:
                        pass
                if str(member.status) == 'offline':
                    try:
                        await member.remove_roles(role, reason='Going offline, so no more VIP rain')
                    except:
                        pass
    

    由于 Łukasz Kwieciński 给了我关于速率限制的提示,我也将时间间隔改为秒。现在这不是问题,因为它的运行速度快了 1000 倍。

    【讨论】:

      猜你喜欢
      • 2020-12-13
      • 2019-01-22
      • 2021-08-16
      • 2019-02-12
      • 1970-01-01
      • 2021-08-07
      • 2020-04-09
      • 2020-11-08
      • 2021-05-08
      相关资源
      最近更新 更多