This problem is very simple. It requires a couple of steps.
- Save the message ID, content, and channel ID to a database (this could be JSON, but SQL is the best way to go)
- Every time a new message is sent, delete the old message (using the database to get that old message) and send the new message to the channel.
- Once the new message is sent, save and update that new message ID in the database.
Of course, you need to create other systems for deleting certain rows in the database once the user decides they don't want a sticky message anymore. However, I won't cover that here (at least for now), as it is out of the context of your question.
Step one: Creating the database
For this, I'll be using sqllite3 for Python
# --- SQL startup ---con = sqlite3.connect("sticky_messages.db") # connect to the databasecur = con.cursor() # create the cursortry: cur.execute("CREATE TABLE sticky(guild_id, channel_id, message_id, message)") # attempt to create the table print("Created new sticky table for sticky_messages")except sqlite3.OperationalError: print("Found existing table for sticky") # if the table already exists
The above is very simple. We're just setting up the sqqlite3 database.
For Pycord
Creating the creation slash command
@bot.slash_command()async def set_up_sticky_messages(ctx, msg_content: str, channel: discord.TextChannel): ref = cur.execute(f"""SELECT * FROM sticky WHERE channel_id=?""", (channel.id,)) ref_fetch = ref.fetchall() if ref_fetch: return await ctx.respond("You already have a sticky message setup") msg = await channel.send(msg_content) cur.execute(f"""INSERT INTO sticky VALUES (?, ?, ?, ?);""", (ctx.guild.id, channel.id, msg.id, msg_content)) con.commit() # save to db await ctx.respond("Created sticky message")
How this works:
- We first check to see if there is already a sticky message entry in the database. If there is, we return an error message.
- We then send the message into the channel that the user provides (if you want to use an embed here, it's very simple)
- We save the related info (as mentioned above) into the database to be used later
This outputs:
The message event
The message event is used for getting and deleting the past message as well as sending the new sticky message.
@bot.eventasync def on_message(msg): ref = cur.execute(f"""SELECT * FROM sticky WHERE channel_id=?""", (msg.channel.id,)) ref_fetch = ref.fetchall() if not ref_fetch: # No record found in database return channel_id = ref_fetch[0][1] message_id = ref_fetch[0][2] message_content = ref_fetch[0][3] channel = await bot.fetch_channel(channel_id) message = await channel.fetch_message(message_id) await message.delete() # delete old message new_msg = await channel.send(message_content) # send new message cur.execute("UPDATE sticky SET message_id = ? WHERE channel_id= ?", (new_msg.id, channel_id)) con.commit() # update db
How this works
- We first check to see if the message is in the database. If it isn't, we return nothing.
- If it is in the database, we delete the old message and send a new one. We update the database's ID with the new message ID.
For Discord.py
It should be very similar database-wise. The only thing you'd need to change is how you're handling the slash commands.