Skip to main content
Level: Beginner · Tags: WhatsApp, Telegram, Media Features shown: send photo, video, file, voice, sticker · send location · send contact · receive media (bot.onType) · loadMediaOf() · receive a location

Prerequisites

Node.js 22.12 or newer and a folder with "type": "module" (see Getting started). Then install:

The complete bot

Sample transcript

Captured with npx botmesh dev bot.js. The simulator prints media as [kind: source] without downloading it, so the placeholder URLs work there. :media image ./cat.jpg My cat sends cat.jpg from the folder you run the command in (use any image you have):

How it works

  • One method per kind. ctx.photo, ctx.video, ctx.file, ctx.voice and ctx.sticker take a URL, a local path or a Buffer; ctx.file(source, filename, caption) sets the name the user sees. ctx.location(lat, lng, name?) takes coordinates and ctx.contact(phone, displayName?) a phone number.
  • Transport details stay in the provider. On WhatsApp a voice note is converted with ffmpeg and a sticker needs the optional sharp package. Telegram sends them as they are, so there a sticker URL must point at a .webp file (hence 512.webp). What each channel supports is in the capability matrix.
  • Inbound media is lazy. The message only carries a reference; loadMediaOf(ctx, { maxBytes }) downloads it once and returns { buffer, mimetype }, or undefined if the download fails. A file over maxBytes throws MediaTooLargeError, which the handler turns into a reply. ctx.body is the caption.
  • Locations arrive as type: 'location' with ctx.sharedLocation (latitude, longitude, name?); ctx.location() is the method that sends one. The simulator has no command to share a location; the docs test sends one with MockProvider.incomingLocation().
  • Outside a handler, bot.send(chatId, { kind: 'image', media: { url }, caption }) sends the same contents, for example from a scheduled task.

Run it on WhatsApp or Telegram

node bot.js prints a QR: scan it in WhatsApp → Linked devices. For Telegram, install @botmesh/telegram and swap the provider as shown in Or connect Telegram; the factory does not change.

Next steps