How Dexter Formats WhatsApp Messages: Plain Text and Media Handling

Dexter formats WhatsApp messages as either plain text objects or raw media payloads, sending them directly through Baileys without markdown processing, and extracts inbound text by checking conversation fields, extended text messages, or media captions.

The virattt/dexter repository implements a lightweight WhatsApp integration that prioritizes simplicity over rich formatting. When handling how Dexter formats WhatsApp messages, the system relies on the Baileys library to manage the WhatsApp Web protocol, processing outbound payloads as unstyled text or media and normalizing inbound messages to clean strings.

Outbound Message Structure in Dexter

Dexter’s outbound handler constructs minimal payloads for the WhatsApp Web protocol. Located in src/gateway/channels/whatsapp/outbound.ts, the code builds a payload that is either a plain text object or a media object passed straight through from the caller.

Sending Plain Text vs. Media

The formatting logic uses a simple fallback pattern. If params.media is provided, it is used directly; otherwise, the system creates { text: params.body }. This payload is handed to Baileys’s sendMessage method without any additional styling or markdown processing.

// src/gateway/channels/whatsapp/outbound.ts (lines 94-98)
const payload = params.media ?? { text: params.body };
const result = await active.sock.sendMessage(to, payload);

Sending a plain text message:

import { sendMessageWhatsApp } from './gateway/channels/whatsapp/outbound';

await sendMessageWhatsApp({
  to: '+14155552789',
  body: 'Hello from Dexter!',
});

Sending a media message:

import { sendMessageWhatsApp } from './gateway/channels/whatsapp/outbound';
import type { AnyMessageContent } from '@whiskeysockets/baileys';

const imagePayload: AnyMessageContent = {
  image: { url: 'https://example.com/cat.jpg' },
  caption: 'Cute cat 🐱',
};

await sendMessageWhatsApp({
  to: '+14155552789',
  body: '',
  media: imagePayload,
});

Inbound Message Text Extraction

When Dexter receives a message, it extracts readable text from the raw Baileys structure. The extraction routine in src/gateway/channels/whatsapp/inbound.ts checks multiple properties in a specific priority order to determine the message body.

Parsing Baileys Message Formats

The extraction logic inspects three potential text sources:

  1. conversation – The simplest plain text field
  2. extendedTextMessage.text – Used for messages with formatting or links
  3. Media captions – Extracted from imageMessage, videoMessage, or documentMessage

If none of these properties contain a non-empty string, the message body is considered empty.

// src/gateway/channels/whatsapp/inbound.ts (lines 50-68)
if (typeof candidate.conversation === 'string' && candidate.conversation.trim())
    return candidate.conversation.trim();

const extended = candidate.extendedTextMessage?.text;
if (extended?.trim()) return extended.trim();

const caption = candidate.imageMessage?.caption ??
                candidate.videoMessage?.caption ??
                candidate.documentMessage?.caption;
if (caption?.trim()) return caption.trim();

Receiving and extracting text:

import { extractText } from './gateway/channels/whatsapp/inbound';
import type { WAMessage } from '@whiskeysockets/baileys';

function handleIncoming(msg: WAMessage) {
  const text = extractText(msg);
  console.log('Received:', text);
}

Type Definitions for WhatsApp Integration

The WhatsAppInboundMessage interface in src/gateway/channels/whatsapp/types.ts standardizes the shape of incoming messages for the rest of the application. It carries the extracted body (plain string) along with helper functions for sending typing indicators and replies.

// src/gateway/channels/whatsapp/types.ts (lines 17-22)
interface WhatsAppInboundMessage {
  body: string;
  sendComposing: () => Promise<void>;
  reply: (text: string) => Promise<void>;
  sendMedia: (media: AnyMessageContent) => Promise<void>;
}

Summary

  • Dexter sends WhatsApp messages as either plain text objects or raw media payloads without styling.
  • Outbound logic in src/gateway/channels/whatsapp/outbound.ts uses Baileys's sendMessage method directly with unprocessed payloads.
  • Inbound processing extracts text by checking conversation, extendedTextMessage.text, and media captions in src/gateway/channels/whatsapp/inbound.ts.
  • The WhatsAppInboundMessage interface standardizes incoming message shapes for the rest of the application.

Frequently Asked Questions

Does Dexter support markdown or rich text formatting in WhatsApp messages?

No. As implemented in src/gateway/channels/whatsapp/outbound.ts, Dexter passes text directly to Baileys without markdown processing. WhatsApp's own formatting (bold, italic) must be applied using WhatsApp-specific syntax (asterisks, underscores) by the caller before sending.

How does Dexter handle incoming media messages?

Dexter extracts captions from image, video, and document messages as part of its text extraction logic in src/gateway/channels/whatsapp/inbound.ts. If a media file includes a caption, that text is returned as the message body; otherwise, the body may be empty if no conversation or extended text is present.

What library does Dexter use to connect to WhatsApp?

Dexter uses the Baileys library (@whiskeysockets/baileys) to interact with the WhatsApp Web protocol. The sendMessage method from Baileys is called directly in the outbound handler, and incoming Baileys message structures are parsed in the inbound handler.

Can Dexter send multiple types of media through WhatsApp?

Yes. The outbound handler accepts an AnyMessageContent type from Baileys, which supports images, videos, documents, audio, and other media types. When a media payload is provided, it is passed directly to sendMessage without modification.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →