Skip to content

Keyboard

VibeGram menyediakan builder deklaratif Markup untuk inline keyboard, reply keyboard, pagination, dan escaping teks yang aman.

Inline Keyboard

Inline keyboard muncul di bawah pesan dan biasanya memicu callback query atau membuka surface Telegram yang didukung.

ts
import { Markup } from 'vibegram';

const keyboard = Markup.inlineKeyboard([
    [Markup.button.callback('Beli', 'buy_1'), Markup.button.callback('Batal', 'cancel')],
    [Markup.button.url('Website', 'https://contoh.com')],
]);

await ctx.reply('Pilih opsi:', { reply_markup: keyboard });

Markup.grid()

Gunakan Markup.grid() saat sudah punya array tombol inline datar dan ingin VibeGram membaginya menjadi beberapa baris.

ts
const days = ['Sen', 'Sel', 'Rab', 'Kam'].map(day => {
    return Markup.button.callback(day, `day:${day}`);
});

await ctx.reply('Pilih hari:', {
    reply_markup: Markup.grid(days, 2),
});

Tipe Tombol Inline

MethodDeskripsi
Markup.button.callback(text, data)Mengirim callback data ke bot.action().
Markup.button.url(text, url)Membuka URL eksternal.
Markup.button.webApp(text, url)Membuka Telegram Mini App.
Markup.button.pay(text)Tombol pembayaran untuk pesan invoice.
Markup.button.switchInlineQuery(text, query)Membuka inline mode di chat lain.
Markup.button.switchInlineQueryCurrentChat(text, query)Membuka inline mode di chat saat ini.
Markup.button.login(text, loginUrl)Tombol Telegram Login.
Markup.button.copy(text, textToCopy)Tombol copy-to-clipboard.

Contoh Login Button

ts
await ctx.reply('Masuk:', {
    reply_markup: Markup.inlineKeyboard([
        [
            Markup.button.login('Login dengan Telegram', {
                url: 'https://contoh.com/auth/telegram',
                request_write_access: true,
            }),
        ],
    ]),
});

Contoh Copy Button

ts
await ctx.reply('Salin kode undangan:', {
    reply_markup: Markup.inlineKeyboard([
        [Markup.button.copy('Salin kode', 'INVITE-2026')],
    ]),
});

Paginasi

ts
const items = products.map(product => ({
    text: product.name,
    callback_data: `product:${product.id}`,
}));

await ctx.reply('Katalog:', {
    reply_markup: Markup.pagination(items, {
        currentPage: 1,
        itemsPerPage: 6,
        columns: 2,
        actionPrev: 'catalog:prev',
        actionNext: 'catalog:next',
        pageIndicatorPattern: '{current}/{total}',
    }),
});

Tangani actionPrev, actionNext, dan callback data item dengan bot.action().

Reply Keyboard

Reply keyboard mengganti keyboard perangkat dengan tombol native Telegram.

ts
const keyboard = Markup.keyboard(
    [
        [Markup.replyButton.text('Berita'), Markup.replyButton.text('Pengaturan')],
        [Markup.replyButton.requestContact('Bagikan nomor')],
        [Markup.replyButton.requestLocation('Bagikan lokasi')],
    ],
    {
        resize_keyboard: true,
        one_time_keyboard: false,
    }
);

await ctx.reply('Menu:', { reply_markup: keyboard });

Tipe Tombol Reply

MethodDeskripsi
Markup.replyButton.text(text)Tombol teks biasa.
Markup.replyButton.requestContact(text)Meminta nomor telepon user.
Markup.replyButton.requestLocation(text)Meminta lokasi user.
Markup.replyButton.requestPoll(text, type?)Membuka pembuatan poll.
Markup.replyButton.requestUser(text, requestId, options?)Membuka pemilihan user Telegram.
Markup.replyButton.requestChat(text, requestId, options?)Membuka pemilihan chat.
Markup.replyButton.requestManagedBot(text, requestId, options?)Meminta otorisasi managed bot.

Hapus Keyboard

ts
await ctx.reply('Keyboard dihapus.', {
    reply_markup: Markup.removeKeyboard(),
});

Force Reply

ts
await ctx.reply('Siapa nama kamu?', {
    reply_markup: Markup.forceReply({
        input_field_placeholder: 'Ketik nama...',
    }),
});

Escape Teks Tak Tepercaya

Saat menyisipkan teks dari user ke pesan dengan parse_mode, escape hanya nilai dinamisnya.

ts
const safeHtml = Markup.escapeHTML(userName);
await ctx.reply(`Halo <b>${safeHtml}</b>`, { parse_mode: 'HTML' });

const safeMarkdown = Markup.escapeMarkdownV2(userName);
await ctx.reply(`Halo *${safeMarkdown}*`, { parse_mode: 'MarkdownV2' });

const safeLegacyMarkdown = Markup.escapeMarkdown(userName);
await ctx.reply(`Halo _${safeLegacyMarkdown}_`, { parse_mode: 'Markdown' });
HelperDipakai dengan
Markup.escapeHTML(text)parse_mode: 'HTML'
Markup.escapeMarkdownV2(text)parse_mode: 'MarkdownV2'
Markup.escapeMarkdown(text)parse_mode: 'Markdown' (legacy)

Jika seluruh balasan adalah konten dinamis dari user, kirim plain text tanpa parse_mode.

Released under the ISC License.