0

I've done some research and found a (maybe) old method for direct messaging someone.

async def dm(ctx, recipient=None, message=None):
    if message == None or recipient == None:
        await ctx.channel.send("***Error: Incorrect Usage***\nUsage: `/test [recipient] [message]`")
    else:
        pass

    if message is not None:
        if recipient is not None:
        
            message = str(message)
            await client.send_message(recipient, message)

What this code is supposed to do is to get the recipient of the dm and the message, and direct message the person (the if message == None or recipient == None is to check for missing arguments, and sending an error message.) What is the correct/recent way to direct message someone?

NotASuperSpy
  • 43
  • 2
  • 6

2 Answers2

2

A few things to note, if you are comparing with a None, instead of a comparison operator (==), prefer using an identity operator (is or is not)

secondly, discord.py by default takes all arguments in a function as string, unless you typecast. You can't "send" a message to a string object. You need to typecast/typehint it to discord.Member

finally, there are some unnecessary if/else statements in your code after the first two lines

I will re-write them, feel free to ask anything you don't understand

async def dm(ctx, recipient: discord.Member =None, *, message=None):
    if message is None or recipient is None:
        return await ctx.send("***Error: Incorrect Usage***\nUsage: `/test [recipient] [message]`")
    await recipient.send(message)
Harukomaze
  • 462
  • 4
  • 9
  • Clarification: *Python* itself can take any kind of arguments to functions; it's the Discord API (and thus discord.py) that interprets all command arguments as strings by default. All the rest is great, but that remark could confuse newer Python coders. – CrazyChucky Jun 04 '21 at 10:56
  • Oh, I just realized that this will only send the first word, because it interprets spaces as delimiters between arguments. Instead of `message=None`, `if message is None`, and `recipient.send(message)`, try accepting `*words`, checking `if not words`, and sending `recipient.send(''.join(words))`. – CrazyChucky Jun 04 '21 at 11:05
  • Ahh yes, sorry about that, I will edit it – Harukomaze Jun 04 '21 at 11:43
  • By adding a bare `*` in your edit, you've made `message` a [keyword-only argument](https://stackoverflow.com/questions/14301967/bare-asterisk-in-function-arguments), which I don't think will even work with `discord.py`. `*message` would be to catch [*multiple* arguments](https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters) (strings/words) as a tuple. – CrazyChucky Jun 04 '21 at 11:47
  • 1
    but in discord.py, `*` is used to collect all arguments intact, without converting them into tuple (when used inside an `async` function with `@commands.command()` decorator), I use it all the time, and so does everyone who uses discord.py lib kwargs come before the `*` for example `async def ban(ctx, member: discord.Member = None, *, message = None)` – Harukomaze Jun 04 '21 at 11:52
  • Oh, my mistake. I guess I'm not familiar with all the custom behaviors this library adds. (That would probably a be a good thing to explain in your answer, though! With a link to the [relevant documentation](https://discordpy.readthedocs.io/en/stable/ext/commands/commands.html#keyword-only-arguments).) – CrazyChucky Jun 04 '21 at 11:53
  • And/or maybe also a link to [this question](https://stackoverflow.com/questions/56006198/is-there-a-way-to-include-spaces-in-my-argument) about spaces in Discord command arguments. – CrazyChucky Jun 04 '21 at 11:59
0

You can get the Member object using target = ctx.guild.get_member(int(recipient)) and then await target.send(content=message)

The user you send the message to has to be in a the server that the command was sent in for my answer to work through.

Dimo
  • 26
  • 3