Max IO β TypeScript-ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊ Π΄Π»Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠ°Ρ-Π±ΠΎΡΠΎΠ² Π² ΠΌΠ΅ΡΡΠ΅Π½Π΄ΠΆΠ΅ΡΠ΅ Max. ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π΄Π°ΡΡ middleware-runtime, typed context, long polling, webhook, upload helpers, ΠΊΠ»Π°Π²ΠΈΠ°ΡΡΡΡ ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΌΠΎΠ΄ΡΠ»ΠΈ Π΄Π»Ρ session/scene/i18n.
Π’ΠΈΠΏΡ API ΡΠ²Π΅ΡΡΡΡΡΡ Ρ ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΡΠΌ Π°ΡΡ
ΠΈΠ²ΠΎΠΌ OpenAPI-ΡΡ
Π΅ΠΌ max-messenger-bot/max-bot-api-schemas. Π’Π΅ΠΊΡΡΠΈΠΉ ΠΎΡΠΈΠ΅Π½ΡΠΈΡ: schema_2026_05_20, Π²Π΅ΡΡΠΈΡ Max Bot API 0.0.30.
| ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ | Π§ΡΠΎ Π΄Π°ΡΡ |
|---|---|
| Middleware-runtime | bot.use, bot.on, bot.command, bot.hears, bot.action |
| Typed Context | ctx.reply, ctx.message, ctx.args, ctx.payload, ctx.state, ctx.api |
| Long polling | bot.start(), marker API, ΡΠ΅ΠΆΠΈΠΌ Π΄Π»Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΈ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ |
| Webhook | bot.start({ webhook }), webhookCallback, createWebhook, deleteWebhook |
| Upload | image/video/audio/file, progress, timeout, AbortSignal, retry attachment.not.ready |
| ΠΠ»Π°Π²ΠΈΠ°ΡΡΡΡ | inline keyboard, open_app, message, clipboard, reply keyboard types |
| ΠΠΎΠ΄ΡΠ»ΠΈ | max-io/lib/session, max-io/lib/scene, max-io/lib/i18n |
npm i max-ioyarn add max-ioΠ’ΡΠ΅Π±ΡΠ΅ΡΡΡ Node.js >=14.13.1.
Π‘ΠΎΠ·Π΄Π°ΠΉΡΠ΅ ΡΠΎΠΊΠ΅Π½ Π±ΠΎΡΠ° Π² Max ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°ΠΉΡΠ΅ Π΅Π³ΠΎ ΡΠ΅ΡΠ΅Π· ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ MAX_BOT_TOKEN.
import 'dotenv/config';
import { Bot, Keyboard } from 'max-io';
const bot = new Bot(process.env.MAX_BOT_TOKEN!);
bot.command('start', async (ctx) => {
await ctx.reply('ΠΡΠΈΠ²Π΅Ρ! Π― Π±ΠΎΡ Π½Π° Max IO.', {
attachments: [
Keyboard.inlineKeyboard([
[Keyboard.button.callback('ΠΡΠΎΠ²Π΅ΡΠΈΡΡ callback', 'demo:callback')],
]),
],
});
});
bot.command('echo', async (ctx) => {
const text = ctx.payload || 'ΠΠ°ΠΏΠΈΡΠΈ /echo Π»ΡΠ±ΠΎΠΉ ΡΠ΅ΠΊΡΡ';
await ctx.reply(text);
});
bot.action('demo:callback', async (ctx) => {
await ctx.answerOnCallback({ notification: 'Callback ΠΏΠΎΠ»ΡΡΠ΅Π½' });
});
bot.start().then();ΠΠΎΠΌΠ°Π½Π΄Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ payload ΠΈ args:
bot.command('ban', async (ctx) => {
const [userId, ...reasonParts] = ctx.args ?? [];
const reason = reasonParts.join(' ');
await ctx.reply(`userId=${userId}; reason=${reason || 'Π½Π΅ ΡΠΊΠ°Π·Π°Π½Π°'}`);
});ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅: docs/01-first-bot.md ΠΈ docs/02-listen-and-respond.md.
import 'dotenv/config';
import { Bot } from 'max-io';
const bot = new Bot(process.env.MAX_BOT_TOKEN!);
bot.command('ping', async (ctx) => {
await ctx.reply('pong from webhook');
});
await bot.start({
webhook: {
domain: 'https://example.com',
port: 3000,
secret: process.env.MAX_WEBHOOK_SECRET,
},
});ΠΡΠ»ΠΈ path Π½Π΅ ΡΠΊΠ°Π·Π°Π½, max-io ΡΠΎΠ·Π΄Π°ΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΉ ΡΡΠ°Π±ΠΈΠ»ΡΠ½ΡΠΉ path ΠΏΠΎ ΡΠΎΠΊΠ΅Π½Ρ. ΠΡΠΈ Π·Π°ΠΏΡΡΠΊΠ΅ webhook ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΡΠ΄Π°Π»ΡΡΡΡΡ ΡΡΠ°ΡΡΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ Ρ Π΄ΡΡΠ³ΠΈΠΌΠΈ URL; ΠΏΡΠΈ Π·Π°ΠΏΡΡΠΊΠ΅ polling ΡΠ΄Π°Π»ΡΡΡΡΡ Π²ΡΠ΅ webhook-ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ.
ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅: docs/webhook.md.
marker Π½ΡΠΆΠ΅Π½, ΡΡΠΎΠ±Ρ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠΈΡΡ long polling Ρ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ. ΠΡΠ»ΠΈ marker Π½Π΅ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ, Max API Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅, ΠΏΠΎΡΡΠΎΠΌΡ ΡΠΎΠ±ΡΡΠΈΡ, Π½Π°ΠΊΠΎΠΏΠΈΠ²ΡΠΈΠ΅ΡΡ ΠΏΠΎΠΊΠ° Π±ΠΎΡ Π±ΡΠ» Π½Π΅Π΄ΠΎΡΡΡΠΏΠ΅Π½, Π½Π΅ Π±ΡΠ΄ΡΡ ΠΏΡΠΎΡΠΈΡΠ°Π½Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ.
const bot = new Bot(process.env.MAX_BOT_TOKEN!, {
polling: { marker: Number(process.env.MAX_POLLING_MARKER) || undefined },
});
// ΠΈΠ»ΠΈ
bot.polling.setMarker(123456);
console.log(bot.polling.marker);
// ΠΈΠ»ΠΈ
await bot.start({ marker: bot.polling.marker });Long polling ΡΡΠΎΠΈΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΄Π»Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΈ ΡΡΡΠ½ΠΎΠΉ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ. ΠΠ»Ρ production Max ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅Ρ Webhook; Ρ 11.05.2026 Π΄Π»Ρ polling Π·Π°ΡΠ²Π»Π΅Π½Ρ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ:
2 RPS, timeout30ΡΠ΅ΠΊΡΠ½Π΄, batch Π΄ΠΎ100ΡΠΎΠ±ΡΡΠΈΠΉ ΠΈ TTL ΡΠΎΠ±ΡΡΠΈΠΉ24ΡΠ°ΡΠ°.
bot.command('video', async (ctx) => {
const video = await ctx.api.uploadVideo({
source: './public/video.mp4',
onProgress: ({ loaded, total }) => {
if (total) console.log(`upload ${Math.round((loaded / total) * 100)}%`);
},
});
await ctx.reply('ΠΠΈΠ΄Π΅ΠΎ Π·Π°Π³ΡΡΠΆΠ΅Π½ΠΎ', {
attachments: [video.toJson()],
});
});ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅: docs/03-attachments-and-uploads.md.
const keyboard = Keyboard.inlineKeyboard([
[Keyboard.button.callback('Callback', 'payload')],
[Keyboard.button.openApp('ΠΡΠΊΡΡΡΡ mini app', 'my_bot', 'demo')],
[Keyboard.button.clipboard('Π‘ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ', 'promo-code')],
]);ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅: docs/04-keyboards.md.
import { I18n } from 'max-io/lib/i18n';
import { SceneManager, StepScene } from 'max-io/lib/scene';
import { SessionManager } from 'max-io/lib/session';max-io/lib/sessionβ session middleware Ρ memory/Redis storage.max-io/lib/sceneβ ΡΡΠ΅Π½Ρ ΠΈ step-ΡΡΠ΅Π½Π°ΡΠΈΠΈ ΠΏΠΎΠ²Π΅ΡΡ session.max-io/lib/i18nβ YAML-Π»ΠΎΠΊΠ°Π»ΠΈΠ·Π°ΡΠΈΡ Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΎΠΉ session.
ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅: docs/05-sessions-scenes-i18n.md.
docs/01-first-bot.mdβ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ°, ΡΠΎΠΊΠ΅Π½, ΠΏΠ΅ΡΠ²ΡΠΉ Π·Π°ΠΏΡΡΠΊ.docs/02-listen-and-respond.mdβ updates, ΠΊΠΎΠΌΠ°Π½Π΄Ρ, ΠΎΡΠ²Π΅ΡΡ, ΡΠΎΡΠΌΠ°ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅.docs/03-attachments-and-uploads.mdβ Π²Π»ΠΎΠΆΠ΅Π½ΠΈΡ, upload, progress, cancel.docs/04-keyboards.mdβ inline/reply ΠΊΠ»Π°Π²ΠΈΠ°ΡΡΡΡ ΠΈ ΡΠΈΠΏΡ ΠΊΠ½ΠΎΠΏΠΎΠΊ.docs/webhook.mdβ webhook runtime, custom server, subscriptions.docs/05-sessions-scenes-i18n.mdβ session, scene, i18n.docs/api-notes.mdβ Π²Π°ΠΆΠ½ΡΠ΅ ΠΎΠ³ΠΎΠ²ΠΎΡΠΊΠΈ ΠΏΠΎ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΡ Max API.
| Import | ΠΠ°Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ |
|---|---|
max-io |
Runtime, Bot, Context, Api, helpers, ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ ΡΠΈΠΏΡ |
max-io/types |
ΠΡΠ±Π»ΠΈΡΠ½ΡΠ΅ ΡΠΈΠΏΡ Bot API |
max-io/lib/session |
Session middleware |
max-io/lib/scene |
Scene manager |
max-io/lib/i18n |
I18n middleware |
Π ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΈ Π΅ΡΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ TypeScript-ΠΏΡΠΎΠ΅ΠΊΡΡ Π΄Π»Ρ ΡΡΡΠ½ΠΎΠΉ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ:
examples/01-basic-minimumβ Π±Π°Π·ΠΎΠ²ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ, Π²Π»ΠΎΠΆΠ΅Π½ΠΈΡ, ΠΊΠ»Π°Π²ΠΈΠ°ΡΡΡΡ, upload.examples/02-chat-admin-managementβ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π°Π΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΎΡΠ°ΠΌΠΈ ΡΠ°ΡΠ°.examples/03-webhook-subscriptionsβ webhook runtime, subscribe/unsubscribe, custom server mode.examples/04-sessions-scenes-i18nβ typed context, session, scene ΠΈ i18n.examples/pr-scenariosβ ΡΡΠ΅Π½Π°ΡΠΈΠΈ Π΄Π»Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ PR/issues ΠΈ ΡΠΏΠΎΡΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΡ API.
nestjs-maxβ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Max IO Ρ NestJS.
Max Bot API ΡΠ°Π·Π²ΠΈΠ²Π°Π΅ΡΡΡ, Π° ΡΠ°ΡΡΡ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΡ Π·Π°Π²ΠΈΡΠΈΡ ΠΎΡ ΡΠ΅ΡΠ²Π΅ΡΠ½ΠΎΠΉ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΠ° Max. Π ΠΏΡΠΎΠ΅ΠΊΡΠ΅ Π΅ΡΡΡ ΡΡΡΠ½ΡΠ΅ ΡΡΠ΅Π½Π°ΡΠΈΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π΄Π»Ρ upload, webhook, reply keyboard, chat admin API ΠΈ video details. ΠΡΠ»ΠΈ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ API Π½Π΅ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΎ ΡΡ Π΅ΠΌΠΎΠΉ ΠΈΠ»ΠΈ ΠΆΠΈΠ²ΠΎΠΉ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΎΠΉ, Π»ΡΡΡΠ΅ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°ΡΡ ΡΡΠΎ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π΄ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΏΡΠ±Π»ΠΈΡΠ½ΡΡ ΡΠΈΠΏΠΎΠ².
MIT. ΠΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΠΈ ΠΏΠΎ ΡΡΠΎΡΠΎΠ½Π½ΠΈΠΌ ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠ°ΠΌ ΠΈ Π»ΠΈΡΠ΅Π½Π·ΠΈΡΠΌ ΡΠΌ. Π² THIRD_PARTY_NOTICES.md.