如何让 Discord.py 机器人更快地删除角色?

How do I make Discord.py bot remove roles sooner?

我制作了一个自动添加和删除角色的机器人。一切正常,但添加在 运行 命令后的 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' 代替 'async for member in guild.fetch_members():' 遗憾的是,这没有任何区别。

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

的内置函数

感谢您的帮助!

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

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 来限制并发请求的数量,可以随意更改值,但请记住——值越高,被禁止的机会就越高(do不超过 50).

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

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

因为我想在离开频道时删除角色,所以我只需要查看用户拥有的角色,然后检查他们是否还在房间里。

所以这是我的新代码:

    @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 倍。