1

So I recently created a discord bot with various meme commands and moderating commands. I am relatively new to python but I understand the gist of it. I have already created a command that lets me(only me) DM a user through the bot. I now want to try and make the bot be able to read the messages that are sent back to it and send them to me, whether its printed in shell or sent to a specific channel/me I don't care, I just want to be able to see what is sent to it. I did some reading around and found this, and from that I collected this:

@bot.event
async def on_message(message):
    channel = bot.get_channel('channel ID')
    if message.server is None and message.author != bot.user:
        await bot.send_message(channel, message.content)
    await bot.process_commands(message)

This alone has not worked for me, I get an error saying that "AttributeError: 'Message' object has no attribute 'server'" when I DM'ed the bot. I was told that discord.py rewrite does not use 'server', but rather 'guild'. So I changed it to say message.guild. From there it gave me the error "AttributeError: 'Bot' object has no attribute 'send_message'", and that's about as far as I got there. I've tinkered with it and changed things here and there and made some slight progress...I think. My new code is:

@bot.event
async def on_message(ctx, message):
    channel = bot.get_channel('channel ID')
    if message.guild is None and message.author != bot.user:
        await ctx.send(channel, message.content)
    await bot.process_commands(message)

This gives me the error "TypeError: on_message() missing 1 required positional argument: 'message'". That is as far as I've gotten now. Any help would be appreciated, as I said, I'm still somewhat new to python, I've only started using it about 2 months ago.

Bob Smith
  • 220
  • 4
  • 21
LeThiccBoi
  • 13
  • 1
  • 3

3 Answers3

3

You're using the ctx parameter, which is unique to commands.

'ctx' is commands.Context, which provides information about commands that are executed. Since this isn't a command, but rather an event, you shouldn't provide it.

Untested, but this should do the trick:

(I made it so it ignores messages from ALL bots, to avoid spam)

for printing messages to console

@bot.event
async def on_message(message: discord.Message):
    if message.guild is None and not message.author.bot:
        print(message.content)
    await bot.process_commands(message)

for dumping message contents to a channel

msg_dump_channel = 1234
@bot.event
async def on_message(message: discord.Message):
    channel = bot.get_channel(msg_dump_channel)
    if message.guild is None and not message.author.bot:
        # if the channel is public at all, make sure to sanitize this first
        await channel.send(message.content)
    await bot.process_commands(message)
2

Your first code is using ancient, outdated and unsupported dpy version.

You mostly updated it correctly in the second code except for few mistakes like the on_message event.

It is not working because it only takes one argument message, there is no ctx in that event.

So the event is passing one argument but your function takes 2 thus the error. The correct code would be: async def on_message(message):

But now you'll be confused what to do with this line you wrote: await ctx.send(channel, message.content)

Even if ctx existed this wouldn't work because send doesn't take destination anymore, instead you call send on destination destination.send("Hello") so translated to your code if the channel is where you want to send it would be await channel.send(message.content)

Also one final note I noticed that you used string here: bot.get_channel('channel ID') this could be you just giving example but just remember that IDs are ints, if you pass string it will never find that channel.

For example this is invalid: bot.get_channel('123456789111315178')

And this would be valid: bot.get_channel(123456789111315178)

BrainDead
  • 786
  • 7
  • 16
  • Ok so I replied earlier about seeing if the bot could do something like "User#0000 sent: insert message". But I figured that out and deleted the reply. But now I am trying to see how I can get the bot to fetch attachment URL's and send those as well. This is how far I got: `@bot.event async def on_message(message: discord.Message, attachment: discord.Attachment): if message.guild is None and not message.author.bot: print(message.author , "sent: ", message.content) if attachment.size > 0: print(attachment.url) await bot.process_commands(message)` – LeThiccBoi Mar 20 '20 at 07:00
  • That seems like a new question but anyway as I said before the on_message takes only one argument. You will only get `message` to work with, always. So you can access attachements from that message with `message.attachments` https://discordpy.readthedocs.io/en/latest/api.html#discord.Message.attachments – BrainDead Mar 20 '20 at 18:33
-1

Based on that error, I'd say you're likely calling on_message() at some point and not giving the message parameter. Look through your code and see if that's maybe the case.

Alternatively, if it's some other code you haven't written that's calling your function, then it might only be calling on_message() with one argument, in which case the ctx argument might be incompatible with that function.

Bob Smith
  • 220
  • 4
  • 21