Split
This package splits messages that exceed the Telegram character limit into multiple parts. It also correctly splits Telegram message entities (bold, italic, links, etc.) across boundaries, so formatting is preserved in each part without manual offset recalculation.
Installation
npm install @gramio/splityarn add @gramio/splitpnpm add @gramio/splitbun add @gramio/splitUsage
import { Bot, format, bold } from "gramio";
import { splitMessage } from "@gramio/split";
const bot = new Bot(process.env.BOT_TOKEN!)
.command("start", async (context) => {
const messages = await splitMessage(
format`${bold("a".repeat(4096 * 2))}`,
(str) => context.send(str)
);
console.log(messages); // array of send results
});
await bot.start();WARNING
If you want to pass context.send without a function wrapper, use context.send.bind(context) — otherwise it will lose context data.
Usage with other frameworks
@gramio/split can be used independently of GramIO — the action callback receives a FormattableString with .text and .entities properties:
import { splitMessage } from "@gramio/split";
import { format, bold } from "@gramio/format";
const messages = await splitMessage(
format`${bold("a".repeat(4096 * 2))}`,
({ text, entities }) => {
return someOtherFramework.sendMessage(text, { entities });
}
);API
splitMessage
function splitMessage<ReturnData>(
text: FormattableString | string,
action: (formattableString: FormattableString) => MaybePromise<ReturnData>,
limit?: number
): Promise<ReturnData[]>| Parameter | Type | Default | Description |
|---|---|---|---|
text | FormattableString | string | — | The message text to split. Can be a plain string or a FormattableString from @gramio/format (which carries entities). |
action | (formattableString: FormattableString) => MaybePromise<ReturnData> | — | A callback invoked sequentially for each split part. The return value is collected into the result array. |
limit | number | 4096 | Maximum character length per part. |
Returns: Promise<ReturnData[]> — an array of results from each action call, in order.
The action callback is called sequentially (not in parallel), which preserves correct message ordering in Telegram.
Custom limit
The default limit is 4096 characters (sendMessage). For photo/video captions use 1024:
import { splitMessage } from "@gramio/split";
import { format, bold } from "@gramio/format";
const messages = await splitMessage(
format`${bold("a".repeat(4096))}`,
({ text, entities }) => {
return context.sendPhoto(PHOTO, {
caption: text,
caption_entities: entities,
});
},
1024
);How entity splitting works
When a message is split, entities are handled as follows:
- Entities that fit entirely within the current part are kept as-is.
- Entities that span the split boundary are split: the first part gets the entity truncated to the boundary, and the remaining part gets a new entity with recalculated
offsetandlength. - Entities entirely in the remaining text get their
offsetshifted accordingly.
This means formatting like bold, italic, links, code, and other Telegram entities are always preserved correctly across all parts.