1

discord.py 1.7.2

use case:

When a user joins my channel, I save their discord id in my database. If a user sent a message with the word $sub foo they subscribe to one of my services. When they subscribe to this service. They idea is for them to get a private message every now and again based on the type

Code

import discord,os,asyncio
from discord.ext import commands, tasks
from Entity.notifications import Notification
from dotenv import load_dotenv

from discord.utils import get
bot = commands.Bot(command_prefix='$')

@bot.event
async def on_ready():
    print('Bot is ready')

@tasks.loop(seconds=10)
async def user_notification():
    print("foo") ##terminal shows the word foo
    await bot.wait_until_ready()
    user_sub_notifications= Notification().get_active_user_sub_notification()

    if user_sub_notifications:
        for notification in user_sub_notifications:
            if "user_discord_id" in notification:
                #get user
                user = get(bot.get_all_members(), id=notification['user_discord_id'])
                #get the message to sent to the user
                message = notification['message']
                #private message the user
                #bot.send_message(user, message)
                
    await asyncio.sleep(10)

load_dotenv() 
user_notificarion.start()
bot.run(os.getenv('DISCORD_TOKEN'))

I have tried the follow

user = get(bot.get_all_members(), id=notification['discord_id']) #got NONE
bot.send_message(notification['user_discord_id'], message) ##bot has not attribute send_message

how can I private message the user? Thank you

Sarah James
  • 431
  • 5
  • 19
  • 1
    https://discordpy.readthedocs.io/en/stable/migrating.html#sending-messages – SuperStormer May 05 '21 at 00:56
  • 1
    Does this answer your question? [AttributeError: 'Client' object has no attribute 'send\_message' (Discord Bot)](https://stackoverflow.com/questions/48116872/attributeerror-client-object-has-no-attribute-send-message-discord-bot) – SuperStormer May 05 '21 at 00:57
  • @SuperStormer thanks for your reply, Unfornately not. Most of the example I have come across is based on if a user just sent a fresh message and you want to reply back to them immediately or private message them immediately has you can use the cxt object. However if you want to reply back via private message, days, weeks or hours later. If you have their discord_id, seems like zero examples or use case available – Sarah James May 05 '21 at 01:08
  • 1
    Ah, then you want https://stackoverflow.com/questions/57336369/how-can-i-get-my-bot-to-dm-a-specific-user-id-without-a-command-given – SuperStormer May 05 '21 at 01:12
  • @SuperStormer Yeah I gave that a try and got `AttributeError: 'NoneType' object has no attribute 'send'` The client.get_user returned None. – Sarah James May 05 '21 at 01:28

2 Answers2

1

Thanks to Rapptz from the discord.py github who answered this question. All credit goes to him.

In v1.7 you need to fetch the user first:

user = bot.get_user(user_id) or await bot.fetch_user(user_id)
await user.send('whatever')

In the future in v2.0 (still in development) you'll be able to open a DM directly via user ID:

dm = await client.create_dm(user_id)
await dm.send('whatever')

the actual method which works is the fetch_user

Sarah James
  • 431
  • 5
  • 19
0

The best and easiest way I would say is to do:

await member.send("{message}")

This will automatically open a dm with the member that used the command, and you can type whatever message you want, similar to ctx.send