不和谐.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的主要内容,如果未能解决你的问题,请参考以下文章

权限覆盖不更改不和谐频道权限。不和谐.py

获取Bot的频道?不和谐.py

如何在频道列表中指定语音频道的位置?不和谐.py

不和谐.py |我正在尝试使用会员名称和会员 ID 解除我的机器人禁令

让不和谐机器人说出服务器和频道名称的命令

如何知道 twitch 流媒体是不是直播并发送相关消息?不和谐.py