How to get message by id discord.py - python

I'm wondering how to get a message by its message id. I have tried discord.fetch_message(id) and discord.get_message(id), but both raise:
Command raised an exception: AttributeError: module 'discord' has no attribute 'fetch_message'/'get_message'

When getting a message, you're going to need an abc.Messageable object - essentially an object where you can send a message in, for example a text channel, a DM etc.
Example:
#bot.command()
async def getmsg(ctx, msgID: int): # yes, you can do msg: discord.Message
# but for the purposes of this, i'm using an int
msg = await ctx.fetch_message(msgID) # you now have the message object from the id
# ctx.fetch_message gets it from the channel
# the command was executed in
###################################################
#bot.command()
async def getmsg(ctx, channel: discord.TextChannel, member: discord.Member):
msg = discord.utils.get(await channel.history(limit=100).flatten(), author=member)
# this gets the most recent message from a specified member in the past 100 messages
# in a certain text channel - just an idea of how to use its versatility
References:
abc.Messageable
TextChannel.history()
TextChannel.fetch_message()
Context.fetch_message()

Related

how do i check if a discord message contains a string

so i am trying to make a discord bot with discord,.py and i want the bot to say something when someone sends a message that contains a certain string. this is what i want to happen
#client.event
async def on_message(msg):
if 'i' in msg:
channel = client.get_channel("742261026686500896")
await channel.send("i")
i get this error
TypeError: argument of type 'Message' is not iterable
how would i go about doing this?
#client.event
async def on_message(msg):
if 'i' in msg:
channel = client.get_channel("742261026686500896")
await channel.send("i")
The discord Message is an uniterable object (the reason you are getting the error). You are not accessing the information properly. The Message object contains information on the other, channel, etc.
You can check the docs on this topic, here.
To access the content of the message, you should use msg.content.
Then, you can run the test on that. Example:
#client.event
async def on_message(msg):
if 'i' in msg.conent:
channel = client.get_channel("742261026686500896")
await channel.send("i")
msg is an object with several attributes. The text portion is found in msg.content. Try this:
#client.event
async def on_message(msg):
if 'i' in msg.content:
channel = client.get_channel("742261026686500896")
await channel.send("i")

Bot don't want to remove member's reaction

I have an authorization system on my server. When member reacts to message, he's getting access to stuff like chats etc. I want bot to remove reaction left by member, so number of reactions on the message will always=1
#client.event
async def on_raw_reaction_add(payload):
message=payload.reaction.message
if payload.channel_id==804320454152028170:
if str(payload.emoji) == '✅':
await message.remove_reaction("✅", payload.member)
else:
return
When I am leaving reaction under the message, I am getting this error:
message=payload.reaction.message
AttributeError: 'RawReactionActionEvent' object has no attribute 'reaction'
Ignoring exception in on_message
Read your error message! Looking at the docs you can easily find out that payload simply does not have such attribute.
To get a message from payload you will need to do something like this
guild = client.get_guild(payload.guild_id)
channel = guild.get_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)

ctx.content in command and event difference (discord.py)

In discord.py is there some option how i can get access to msg.content (or ctx.content how everyone uses it) under a command ? Below you can see 2 examples of what i mean. The first one is event and i simply copy the message and let the bot to send it back. The second is command but there the msg.content doesnt work. My problem is that i dont want to use events so much and have everything under a command.
#bot.event
async def on_message(msg):
chat = bot.get_channel(797224597443051611)
if msg.channel.id != channel:
return
if msg.content.startswith("!rps"):
message = str(msg.content)
await chat.send(message)
Someone types !rps hello. Outpup in discord is !rps hello
#bot.command()
async def rps(msg):
if msg.channel.id != channel:
return
message = str(msg.content)
await msg.send(message)
Someone types !rps hello (my prefix is !). Output is error in console:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Context' object has no attribute 'content'
Commands always take commands.Context as the first argument, also you should call it ctx instead of msg, to access the message content you can use ctx.message.content
#bot.command()
async def rps(ctx):
if ctx.channel.id != channel:
return
message = str(ctx.message.content)
await ctx.send(message)
Take a look at the commands introduction
In order to get the rest of the message of a command, you need to pass another argument. This argument will include all the messages that's sent after !rps. Also, using ctx instead of msg is better in commands.
#bot.command()
async def rps(ctx, *, args):
if ctx.channel.id != channel:
return
await ctx.send(args)
In this code, args argument includes all the messages after the !rps.

How to get the message content/embed from the message id?

I want to know how to get a message content (specifically the embeds) from the message id? Just like you can get the member using a member id
on_raw_reaction_add() example:
#bot.event
async def on_raw_reaction_add(payload):
channel = bot.get_channel(payload.channel_id)
msg = await channel.fetch_message(payload.message_id)
embed = msg.embeds[0]
# do something you want to
Command example:
#bot.command()
async def getmsg(ctx, channel: discord.TextChannel, msgID: int):
msg = await channel.fetch_message(msgID)
await ctx.send(msg.embeds[0].description)
In the command I'm passing in channel and msgID, so a sample command execution would like !getmsg #general 112233445566778899 - the channel must be in the same server that you're executing the command in!
Then I'm getting the message object using the fetch_message() coroutine, which allows me to get a list of embeds in said message. I then choose the first, and only, embed by choosing position index 0.
After that, the bot then sends the description (or whatever attribute you'd like) of the embed.
References:
discord.TextChannel
TextChannel.fetch_message()
Message.embeds
discord.Embed - This is where you can find the different attributes of the embed
commands.command() - Command decorator
on_raw_reaction_add()
discord.RawReactionActionEvent - The payload returned from the reaction event
RawReactionActionEvent.message_id - The ID of the message which was reacted to
RawReactionActionEvent.channel_id - The text channel that the reaction was added in

Discord.py how do I send a DM to anyone I want through a command

Someone asked me to make a bot for him that sends a DM to anyone he specifies through a command, like *send_dm #Jess#6461 hello.
I've searched alot and I came across this code:
async def send_dm(ctx,member:discord.Member,*,content):
await client.send_message(member,content)
but then I got the error:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Bot' object has no attribute 'send_message'
I want to type for example : *send_dm #Jess#6461 hello and the bot sends a DM saying "hello" to that user.
client.send_message() has been replaced by channel.send() in the version 1 of discord.py
You can use Member.create_dm() to create a channel for sending messages to the user
async def send_dm(ctx, member: discord.Member, *, content):
channel = await member.create_dm()
await channel.send(content)
HI there hope this help you
client.command(aliases=['dm'])
async def DM(ctx, user : discord.User, *, msg):
try:
await user.send(msg)
await ctx.send(f':white_check_mark: Your Message has been sent')
except:
await ctx.send(':x: Member had their dm close, message not sent')
change you client if you use any other str
The easiest way to do is:
async def send_dm(ctx,member:discord.Member,*,content):
await member.send(content)

Categories