不和谐.py |更新频道名称 on_member_join
Posted
技术标签:
【中文标题】不和谐.py |更新频道名称 on_member_join【英文标题】:Discord.py | Update channel name on_member_join 【发布时间】:2021-06-22 19:27:33 【问题描述】:当成员加入/退出服务器时,我正在尝试更新频道名称。 我有一个统计频道,其中显示了成员数。
我想我会创建一个函数,它从 ID 获取频道,然后计算服务器成员数,最后用正确的成员数更改频道名称。
base.py
这是我在文件 base.py 中的函数 同样在这个文件中,我处理 on_member_join / on_member_remove 事件。所以我想知道当用户进入或离开时如何调用 refresh() 函数。
class base(commands.Cog):
def __init__(self, client):
self.client = client
@client.command()
async def refresh(self, ctx):
stats_channel = client.get_channel(1234567890)
membri = len(ctx.guild.members)
await stats_channel.edit(name='???? Users: '.format(membri))
一旦我定义了刷新函数,我会尝试在用户进入时调用它
@commands.Cog.listener()
async def on_member_join(self, member):
await self.refresh()
print("Other stuff")
但是一旦有会员进入服务器,就会出现这个错误:
Ignoring exception in on_member_join
Traceback (most recent call last):
File "C:\Users\Matteo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "C:\Users\Matteo\Desktop\Bot\comandi\base.py", line 33, in on_member_join
await self.refresh()
File "C:\Users\Matteo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\discord\ext\commands\core.py", line 372, in __call__
return await self.callback(self.cog, *args, **kwargs)
TypeError: refresh() missing 1 required positional argument: 'ctx'
我尝试了几种方法来尝试修复它,但都没有成功。
【问题讨论】:
从refresh
的签名中可以看出,它需要一个ctx
(上下文)参数,就像任何其他 Cog(或非 Cog)命令一样。我认为 Member 对象(您在on_member_join
处理程序中给出)传递了预期的相同内容。你也许可以打电话给self.refresh(member)
。
这样做你会侥幸成功,但这是不好的做法,可能会让你和其他人在稍后查看你的代码时感到困惑。
不一定,因为“上下文”是一个松散的对象类型,如果我记得的话。它是多种不同可能对象类型的抽象表示。 编辑:我可能在想雪花,或者别的什么...
无论如何,我同意你的回答——如果它实际上不是一个命令,那么就不要这样框定它。
【参考方案1】:
首先,您可以通过多种方式做到这一点。为什么是刷新客户端命令?您希望用户手动调用它吗?如果是,请为 ctx 设置一个默认值。
@client.command()
async def refresh(self, ctx = None):
#other stuff
if ctx is not None:
await ctx.send('refreshed member count')
或者如果你不需要它作为命令
async def refresh(self): #no client.command() decorator
#do stuff here
【讨论】:
我的意图是自动编辑名称。反正我已经试过了,我放了@client.command 因为它没有找到ctx,而且我知道这是一个错误的东西 把ctx去掉就行了,为什么还要加ctx。 它有效,谢谢。我添加了 ctx,因为我从另一个函数中复制了一些行,这些行创建了统计类别和频道【参考方案2】:不要
不要在每次成员加入服务器时更新频道名称。为什么?
Discord 对您可以更改频道名称的时间有很高的速率限制,即每 10 分钟 2 次。高于 2 倍将使您受到速率限制。这是为了彻底删除像你这样的计数器机器人。
做
如果您仍然想这样做,而不是每次触发 on_member_join 事件时都更新,您可以检查服务器上的成员数量并每隔一段时间更改频道名称,最好每 30 分钟或一小时一次。
您可以使用tasks.loop
装饰器以间隔触发函数。这是图书馆提供的。 Here
这是您应该做的解决方案,而不是使用 on_member_join 事件。
# Define a variable to store the old amount.
old_amount = 0
@tasks.loop(minutes=30)
async def member_checker():
# Get the guild object
guild = bot.get_guild(YOUR_GUILD_ID)
# Check if it's not the same, if it is, update the channel.
if old_amount != guild.member_count:
# Update the old amount, and update your channel.
old_amount = guild.member_count
your_channel = guild.get_channel(YOUR_CHANNEL_ID)
await your_channel.edit(name=guild.member_count)
# This function is triggered before the loop occur
@member_checker.before_loop
async def before_looping_occur():
# You would also need this to not let the loop run before
# on ready occur, this is to avoid bot.get_guild returns None
await bot.wait_until_ready()
# Start this task somewhere
member_checker.start()
【讨论】:
我试过了,我最初把 member_checker.start() 放在 on_member_join 里面,但是没有用。然后我决定将 member_checker.start() 放在一个简单的“while True”中,但它卡在了 before_looping_occur 请实际阅读文档。 member_checker.start() 应该调用一次。不要放在on_member_join里面,只调用一次这个方法。当你启动机器人时,你可以直接把它放在机器人声明的下方。 Discord 的文档说速率限制是每秒 50 个请求,不管你调用哪个请求,只是一个全局速率限制,仅此而已以上是关于不和谐.py |更新频道名称 on_member_join的主要内容,如果未能解决你的问题,请参考以下文章