【问题标题】:DM a specific user in discord.pyDM discord.py 中的特定用户
【发布时间】:2021-08-30 10:05:42
【问题描述】:

我想知道如何与一个永远相同的特定人联系。我尝试了很多 StackOverFlow 帖子和官方 discord.py 文档,但都没有奏效。我有 discord.py 1.7.3。到目前为止,我有以下内容:

import discord
from discord.ext import commands

@client.command()
async def dm(ctx):
    user = client.get_user(1234567891011) # <- This user will always be the same.
    await user.send("Hi")

当我在服务器中键入命令时,出现以下异常:

Ignoring exception in command dm:
Traceback (most recent call last):
  File "C:\Users\myuser\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "c:\Users\myuser\Documents\Python Scripts\Bot\main.py", line 110, in dm    await user.send("Hola")
AttributeError: 'NoneType' object has no attribute 'send'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\myuser\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\myuser\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 863, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:\Users\myuser\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'send'

【问题讨论】:

  • 用户似乎不存在,因此get_user() 返回无。您确定具有此 ID 的用户存在吗?
  • 我通过另一个返回作者id并得到了id的命令对其进行了测试(显然示例中显示的不是真实的)
  • get_user 需要一个整数,而不是字符串
  • 将其更改为整数后,它会抛出相同的异常

标签: python discord.py


【解决方案1】:

client.get_user-方法在本地用户缓存上运行。因此,除非您已经缓存了您想要 dm 的用户(例如通过与他们共享服务器并启用 Intents.members),否则您不会将它们放在本地缓存中,因此 get_user-方法将返回 None .

要让它独立于本地用户缓存工作,您可以改用client.fetch_user。它将通过用户的 id 从 discord API 中获取用户,因此总是返回一个用户对象(假设给定的 id 存在)。

使用client.fetch_user,您的命令可能如下所示:

@bot.command()
async def dm(ctx):
    user = await client.fetch_user(1234567891011)
    await user.send('Hi')

【讨论】:

    【解决方案2】:

    此实现允许公会的任何成员在任何频道中简单地输入!dm,机器人将向client.get_user(&lt;user ID&gt;) 中指定的用户发送消息

    import discord
    import os
    from discord.ext import commands
    
    # Declaration Discord.py Variables
    intents = discord.Intents.default()  # Turns on the connection
    intents.members = True  # Ensures the member list will be updated properly
    client = commands.Bot(command_prefix='!', intents=intents)  # defines the symbol used to call a command from the bot
    
    
    @client.command()
    async def dm(ctx):
        """
        Sends a message to a user every time a member types '!dm' in the channel.
        :param ctx: represents the context in which a command is being invoked under
        :return: a message to the user
        """
        await client.get_user(470163626083352577).send("Enter Text")
    
    client.run("Bot_Token")
    
    • 这里有更多关于意图如何工作的信息Privileged Intents,因为您需要激活服务器成员意图

    【讨论】:

    • 我不太确定为什么这是公认的答案,因为在我看来(以及在我的测试中)它不能解决问题。我看到的一些问题: 代码似乎与问题中的相同,只是压缩成一行。 await 不应该做任何事情,因为 client.get_user 不是协程。它只会引发异常。当用户不在本地用户缓存中时,client.get_user 将返回 None 并导致异常。如果它在您的测试中成功,请纠正我,否则应该修改这个答案或者应该接受一个有效的答案。
    • 是的,实际上答案不是问题,而是机器人本身,如果可以的话,我会在帖子的上部对其进行编辑。我将其标记为已接受,因为答案中的那个人与我联系并帮助了我大约半小时,直到它起作用。
    • 好的,很高兴它现在可以工作了。我认为如果您可以建议对 yet-it-compiles 进行编辑(或要求他们编辑他们的答案),这样它会包含现在为您工作的代码(并且可能会添加一些关于错误是什么的解释) )。这样,该问题的未来访问者将知道您为解决问题所做的工作,并且也能够从您的问题中受益。接受答案后,您不仅表明您的问题已得到解决,还表明您是如何解决的,因此解决方案实际上对您有用是非常重要的。
    • 我更改了帖子,以便在顶部显示两个答案都有效。我认为 yet-it-compiles 只是我的一个简化答案,所以它也应该可以工作。
    • @yet-it-compiles 我相信它现在应该可以工作了,感谢您的更新!
    【解决方案3】:

    Bot.get_user() 在客户端的内部缓存中查找。如果缓存中没有找到用户,这个方法返回None

    请注意,如果 get_user 返回 None,则该用户可能不与机器人共享公会,因此您无法 DM 该用户。

    您可以选择尝试获取用户,但您仍然无法 DM 用户,除非您与用户共享公会。

    user = await client.fetch_user(id)
    await user.send('Message')
    

    如果找不到用户,这将引发discord.NotFound,如果你无法直接向用户发送消息,则会引发discord.Forbidden

    确保 id 是整数。

    【讨论】:

      【解决方案4】:

      这个错误是因为你必须在发送消息之前在一个变量中创建一个dm

      试试这个:

      import discord
      from discord.ext import commands
      
      client = commands.Bot(command_prefix='!') 
      
      @client.command()
      async def dm(ctx,member:discord.Member,*,content):
          channel = await member.create_dm() #create dm
          await channel.send(content)  #send the message
      

      编辑: 在这个新代码中,当您运行命令 !dm [message] 时,机器人将创建一个名为 channel 的新 dm(注意:频道名称只是一个变量,它不会命名 dm 频道),然后发送您上次添加的消息

      注意: 用户必须在您发送 dm 的服务器中。

      【讨论】:

      • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
      猜你喜欢
      • 2021-12-24
      • 2018-05-10
      • 2021-11-21
      • 2020-12-27
      • 2021-01-06
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 2021-04-26
      相关资源
      最近更新 更多