@yaebal/inline-results
typed builders for every InlineQueryResult and InputMessageContent variant, so an answerInlineQuery payload reads as data instead of a hand-rolled
object literal — a typo in a field name is a compile error, not a silent 400 from
telegram.
install
pnpm add @yaebal/inline-resultsusage
every builder takes the variant's required fields positionally, and a trailing options
object for everything optional (reply_markup, thumbnails, captions, durations, …) —
typed straight off @yaebal/types, so it can't
drift from the real schema.
import { InlineQueryResult, InputMessageContent } from "@yaebal/inline-results";
bot.on("inline_query", async (ctx) => {
await ctx.api.answerInlineQuery({
inline_query_id: ctx.inlineQuery.id,
results: [
InlineQueryResult.article(
"1",
"yaebal",
InputMessageContent.text("yet another telegram bot api library"),
{ description: "a type-safe, extensible telegram bot api framework" },
),
InlineQueryResult.photo("2", "https://example.com/cat.jpg", "https://example.com/cat_thumb.jpg"),
InlineQueryResult.cached.audio("3", "AwACAgIAA...", { performer: "yaebal" }),
],
});
});formatted text
caption and message_text accept a FormattedText ({ text, entities } — what format from @yaebal/fmt or core's tag functions produce) in
addition to a plain string. pass it through as-is — bot.api decomposes it into the
wire fields the same way it does for every other formatted-text param.
import { html } from "@yaebal/fmt";
// caption / message_text accept a FormattedText ({ text, entities }) in addition
// to a plain string — bot.api decomposes it into the wire fields automatically
InlineQueryResult.article(
"1",
"yaebal",
InputMessageContent.text(html`<b>yaebal</b> — yet another telegram bot api library`),
);cached.*
the file_id-backed variants (already on telegram's servers, not fetched from a url)
live under InlineQueryResult.cached:
InlineQueryResult.cached.photo(id, photoFileId);
InlineQueryResult.cached.document(id, title, documentFileId);
InlineQueryResult.cached.sticker(id, stickerFileId);
// + gif, mpeg4Gif, video, voice, audioInputMessageContent
covers text, location, venue, contact and invoice. not covered: rich block-tree content — build that with @yaebal/rich, its output already satisfies InputMessageContent.
InputMessageContent.text("hello");
InputMessageContent.location(51.5, -0.12);
InputMessageContent.venue(51.5, -0.12, "Big Ben", "Westminster");
InputMessageContent.contact("+123456789", "Ann");
InputMessageContent.invoice("Widget", "a widget", "payload1", "USD", [
{ label: "Widget", amount: 500 },
]);api
| export | covers |
|---|---|
InlineQueryResult.article/audio/contact/document/game/gif/location/mpeg4Gif/photo/venue/video/voice | url-backed result variants |
InlineQueryResult.cached.audio/document/gif/mpeg4Gif/photo/sticker/video/voice | file_id-backed result variants |
InputMessageContent.text/location/venue/contact/invoice | input_message_content payloads |
InlineQueryResultValue / InputMessageContentValue | the raw @yaebal/types union types, re-exported (renamed to avoid colliding
with the builder namespaces above) |
bot.install(...) — this package is a plain set of builder
functions you call wherever you build an answerInlineQuery payload.