如何让 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 倍。
我制作了一个自动添加和删除角色的机器人。一切正常,但添加在 运行 命令后的 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 倍。