I need my Discord bot to edit their own previous message, adding a string of text. But I don't understand how to accomplish this. I am using discord.py.
My Discord bot is for hosting reservations for a grand-strategy video game. The bot sends the contents of a .txt file into a channel via message, which contains a list of playable nations. Then a user can do '!reserve (x nation)', and the bot proceeds to update it's list to add that user's name to the list, next to their chosen (x nation).
However, I don't understand how to make the bot edit, and then add strings of text to a message it has previously sent. I have looked through discord.py documentation and browsed stackoverflow, but haven't found anything that has addressed this issue. Additionally, I would need to program the bot to put the user's name after the user's chosen 'nation', inside the list.
For example:
bot message:
Playable Nations List
USA
Italy
...
upon command '!reserve USA'
bot message (edited):
Playable Nations List
USA @user
Italy
...
Regarding code; I have set up a function to grab the message ID of the bot's original message. It is simply the process after that which is incomprehensible to me.
Here is the code:
import discord
from discord import app_commands
from discord.ext import commands
from discord.utils import get
intents = discord.Intents.all()
client = commands.Bot(command_prefix='!', intents = intents)
tree = app_commands.CommandTree
@client.event
async def on_ready():
print("The bot is now ready")
try:
synced = await tree.sync(guild=discord.Object(id=GUILD_ID))
print(f"Synced {len(synced)} command(s)")
except Exception as e:
print(e)
@client.command()
async def host(ctx):
with open('host-template.txt', 'r') as fp:
message = await ctx.send(fp.read())
with open('message.txt', 'w') as f:
f.write(str(message.id))
@client.command()
async def reserve_USA(ctx):
channel = client.get_channel(CHANNEL_ID)
with open("message.txt", "r") as f:
message_id = int(f.read())
message = await channel.fetch_message(message_id)
await message.edit(content="CONTENT") #This basic message.edit function is not feasible.
client.run(BOTTOKEN)
Here is the contents of 'host-template.txt':
Available Nations
USA
Japan
UK
USSR
Germany
France
Italy
I think you are better off using embeds for this. Embeds have fields, which can be easily manipulated. For every country, you can add a field and then add a person under that field. Besides, it will also look way more appealing to the eye.
For starters, you'll have to remove the Available Nations
from host-template.txt
and make it only the countries. Then, you can .readlines()
on it, which will return a list with every line.
with open("host-template.txt") as f:
countries = f.readlines() # countries will now be ['USA', 'Japan', ...]
You need to keep the countries in separate lines for this to work.
And then, you can use discord.Embed
and construct an embed and then add a new field for every country. For example:
country_embed = discord.Embed(title="Available Nations")
for country in countries:
country_embed.add_field(name=country, value="N/A") # we can edit the N/A later with our list of members
.send()
has an embed
kwarg and to send the embed, we will pass our embed instance there.
await ctx.send(embed=country_embed)
Then, when you edit it, you can fetch the message and access message.embeds
which is a list. Since there's only one embed in the message, we get that embed by indexing 0.
message = await channel.fetch_message(message_id)
country_embed = message.embeds[0]
Now, we get the field we need to edit. Message.embeds
is a list so we'll use indexing to get the field we want. The fields will be created in the order the countries are in host-template.txt
, so if we want to access Japan
which is second, we'll subtract 1 from it since indexing starts at 0 and not 1. So,
2 - 1 = 1.
japan_field = country_embed.fields[1]
# Now, we will remove the field and add it again using `Embed.insert_field_at`.
country_embed.remove_field(1)
# We need to check if the value is "N/A" (no users) or if there are users
new_value = ""
if japan_field.value == "N/A": # There is no user so we can replace it
new_value = "<your_new_value>"
else: # There are users logged, so we add to it
new_value = f"{japan_field.value}\n" + "<your_new_value>"
# Now, we insert the field at the same index
country_embed.insert_field_at(1, name=japan_field.name, value=new_value)
# And now, edit the message with the new embed
await message.edit(embed=country_embed)
This can be hard to follow, if you have any doubts you can comment below.
References: