Changing and removing

Edit and delete messages you already sent on Telegram, Discord, Slack, ntfy and Mastodon. The result of send is the handle, and the types say who cannot.

A deploy fails, then it succeeds. Sending a second message is noise. Changing the first one is what you want, and four of the seven channels can do it.

Copy this

server/api/deploy.post.ts
export default defineEventHandler(async () => {
  const message = await discord.send('Deploy running…')

  await new Promise((r) => setTimeout(r, 3000))

  await discord.edit(message, 'Deploy finished')
  // await discord.delete(message)

  return { ok: true }
})

That runs. The message in Discord changes in place.

The result is the handle

send returns everything needed to point at the message again, so there is nothing to keep track of yourself:

const message = await telegram.send('Deploy running…')

message.id // the service's own id, as a string
message.url // a permalink, where the service gives one
message.raw // what the service answered, untouched
message.response // status and every header

A bare id is not enough anywhere: Telegram also needs the chat, Discord the thread, Bluesky the record key. So the whole object goes back in. If you keep an id in your own database, the handle types are exported and tell you exactly which fields to store.

Who can do what

Channeleditdelete
Telegram✅ within 48 hours
Discord
Mastodon✅ answers with the deleted post
ntfy✅ needs server 2.16.0
Slack✅ with a bot token✅ with a bot token
Bluesky
Webhookyou decideyou decide

Where a channel cannot, the method is not on the type, so you find out while typing:

bluesky.edit(post, 'nope')
//      ^^^^ Property 'edit' does not exist

Call it anyway from plain JavaScript and you get a sentence with the reason, not undefined is not a function.

Bluesky is not missing a feature here, it is refusing to lie.putRecord on a post answers with a 200 and the appview ignores the change. An edit would look like it worked and do nothing, which is worse than not offering it. Delete and post again.

What happens to the images

This is the part every service gets wrong differently, so the module turns them all the same way round: nothing is removed that you did not ask to remove.

await discord.edit(message, 'New text') // images stay
await discord.edit(message, 'New text', { media: [] }) // images gone, on purpose
await discord.edit(message, 'New text', { media: [pic] }) // added, old ones stay

Underneath, that means the opposite work in each place. Discord drops every attachment a PATCH does not name, so the module names them again. Mastodon keeps them unless the field is present, so the module leaves it out. Same three lines for you.

Telegram cannot remove an image at all.editMessageMedia replaces and, since Bot API 7.11, adds, but there is no way back to a text only message and no deleteMedia. Asking for it gets a refusal that says so, rather than quietly changing only the caption. Delete the message and send a new one.

Telegram picks one of four methods

You write one edit. Which of Telegram's four runs follows from the handle and from what you pass:

What you giveWhat runs
text, on a text messageeditMessageText
text, on a message with an imageeditMessageCaption
mediaeditMessageMedia, which can also add an image to a text message
no text, only replyMarkupeditMessageReplyMarkup

What will cost you an hour

  • Telegram only deletes within 48 hours. That is Telegram's rule, not ours.
  • A Slack incoming webhook has no id at all. It answers ok. Editing needs a bot token, and then the same code works.
  • ntfy replaces rather than edits. It ties messages together with a sequence id, and publishing again with the same one replaces the notification on the phone. An older server than 2.16.0 does not know the field and quietly publishes a second notification instead.
  • Mastodon edits are public. It keeps a version history and clients show an "edited" marker. This is not a quiet fix.
  • Deleting twice is fine on Bluesky and a 404 on Discord. AT Proto made it idempotent on purpose.

Read more