I’m trying to build a Discord bot using Python that can send private messages to specific users. The idea is that when I type a command like !message @username, the bot should automatically send a direct message to that mentioned user.
Here’s what I have so far but it’s not working correctly:
@bot.event
async def on_message(ctx):
if ctx.content.startswith('!message'):
dm_text = 'Hello! You received a private message'
await bot.send_message(ctx.author, dm_text)
The problem is that this code only sends the DM back to me (the person who typed the command) instead of sending it to the user I mentioned. I need help figuring out how to extract the mentioned user from the message and send the DM to them instead. Any suggestions on how to fix this?
Actually there’s another approach that might be cleaner if you’re planning to expand your bot’s functionality. Consider using the commands extension instead of handling everything in on_message. This makes command parsing much more straightforward:
from discord.ext import commands
@bot.command()
async def message(ctx, user: discord.Member, *, content="Hello! You received a private message"):
try:
await user.send(content)
await ctx.send(f"Message delivered to {user.mention}")
except discord.HTTPException:
await ctx.send("Failed to send message. User might have DMs disabled.")
This way you can use !message @user your custom message here and it automatically converts the mention to a Member object. The commands framework handles the parsing for you, plus you get built-in error handling if someone doesn’t provide a valid user mention. Much cleaner than manually parsing message content and dealing with mentions array indexing.
quick tip - make sure you’re not forgetting about the bot permissions too. even with the code fixed, your bot needs proper intents enabled or it wont see message content. add intents = discord.Intents.default() and intents.message_content = True when creating your bot instance, otherwise discord blocks content access since the recent api changes.
The main issue with your code is that you’re using ctx.author which refers to whoever sent the command, not the mentioned user. You need to parse the mentions from the message content. Here’s a corrected approach:
@bot.event
async def on_message(message):
if message.content.startswith('!message'):
if message.mentions:
user = message.mentions[0] # Gets first mentioned user
dm_text = 'Hello! You received a private message'
try:
await user.send(dm_text)
await message.channel.send(f'DM sent to {user.display_name}')
except discord.Forbidden:
await message.channel.send('Cannot send DM to that user')
else:
await message.channel.send('Please mention a user')
The key change is using message.mentions[0] to get the mentioned user object, then calling user.send() instead of sending to the command author. Also added error handling since some users block DMs from bots.