REPOSITORY / ScuroNeko/Laniakea

Wiki

KNOWLEDGE REPOSITORY
7
tgapi Overview
ScuroNeko edited this page 2026-05-20 13:28:29 +03:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

tgapi Overview

Russian version: tgapi-Overview-RU

tgapi is the low-level Telegram Bot API layer used under Laniakeas higher-level bot runtime. Use it when you need direct access to Telegram methods, explicit parameter structs, upload control, or raw request building that sits below plugins and MessageContext helpers.

The important split first

There are two main clients:

  • tgapi.API for JSON requests
  • tgapi.Uploader for multipart file uploads

That split is intentional:

  • JSON-only calls such as SendMessage, GetMe, GetUpdates, or EditMessageText go through API;
  • binary uploads such as SendPhoto, SendDocument, SendVideo, or webhook certificates go through Uploader.

If you stay on the typed method surface, you usually do not need to think about raw HTTP details at all.

The normal layering

In practice, Laniakea has three levels:

  • high-level handler helpers on MessageContext;
  • runtime structure on Bot, plugins, and middleware;
  • low-level Telegram access in tgapi.

tgapi is not a separate product inside the repository. It is the lower-level layer that the high-level bot runtime is already using under the hood.

When to use tgapi directly

Use tgapi directly when:

  • a MessageContext helper does not expose the Telegram feature you need;
  • you need a Telegram method outside the high-level command/payload flow;
  • you want explicit control over params, parse modes, message edits, or uploads;
  • you are writing infrastructure code rather than command logic.

Stay on high-level Laniakea helpers when:

  • you only need normal replies or callback answers;
  • the work belongs inside command or payload handlers;
  • keyboard, draft, localization, and context helpers already cover the use case.

Typical examples where tgapi is the better tool:

  • setting bot metadata or command scopes directly;
  • file downloads and streaming;
  • multipart uploads;
  • one-off Telegram methods that do not have a MessageContext wrapper.

Typed methods first

The normal tgapi workflow is method-specific and typed.

Example:

api := tgapi.NewAPI(tgapi.NewAPIOpts(token))
defer api.Close()

msg, err := api.SendMessage(tgapi.SendMessage{
	ChatID: chatID,
	Text:   "Hello",
})

This is preferred over building raw requests manually because:

  • the method name is fixed correctly;
  • the parameter type matches the Telegram method;
  • the result type is explicit;
  • per-chat rate limiting can be wired by the helper.

Most methods also have a context-aware variant:

msg, err := api.SendMessageWithContext(ctx, params)

Use the context-aware variants when cancellation, deadlines, or graceful shutdown behavior matters.

APIOpts

API is configured through NewAPIOpts(token).

Useful options include:

  • SetHTTPClient(...)
  • UseTestServer(...)
  • SetAPIURL(...)
  • SetLimiter(...)
  • SetLimiterDrop(...)

These options are also what Bot wires internally during construction, so understanding them helps even if you mostly use the high-level bot runtime.

API behavior and responsibilities

tgapi.API handles:

  • JSON request encoding;
  • HTTP execution;
  • internal worker-pool scheduling;
  • optional rate limiting;
  • Telegram 429 retry_after backoff and retry;
  • response decoding into typed results.

A few practical points matter:

  • NewAPIOpts(token) is the normal constructor entry point.
  • if you do not provide an HTTP client, API creates one with a 45-second timeout.
  • SetLimiter(...) connects a utils.RateLimiter.
  • SetLimiterDrop(true) switches from waiting mode to immediate ErrDropOverflow behavior when the limiter is full.
  • Close() must be called to stop the worker pool and close idle connections.

Worker pool behavior

tgapi.API executes requests through an internal worker pool.

That means:

  • even typed API calls go through a managed execution layer;
  • Close() is important because it stops that pool cleanly;
  • context-aware variants are the right choice when cancellation should interrupt waiting work.

This is one reason Close() is not optional in long-lived code.

Uploader behavior and responsibilities

tgapi.Uploader is the multipart companion to API.

Use it when Telegram expects an uploaded file body rather than a file_id or URL. The uploader reuses the underlying API client, including its HTTP client and limiter behavior.

Example:

api := tgapi.NewAPI(tgapi.NewAPIOpts(token))
defer api.Close()

uploader := tgapi.NewUploader(api)
defer uploader.Close()

photo := tgapi.NewUploaderFile("cat.jpg", data)
msg, err := uploader.SendPhoto(tgapi.UploadPhoto{
	ChatID: chatID,
	Caption: "Cat",
}, photo)

NewUploaderFile(name, data) auto-detects a Telegram upload field from the file extension. If needed, override it with SetType(...).

Call Uploader.Close() when you own a standalone uploader instance. When you use the uploader created by laniakea.Bot, bot.Close() handles that lifecycle for you.

Choosing between API and Uploader

Use API when:

  • Telegram accepts JSON-only parameters;
  • you are sending file_id or URL references instead of new binary content.

Use Uploader when:

  • Telegram expects multipart file upload;
  • you are sending new binary content from memory or disk;
  • the method has an Upload* parameter type.

File downloads

tgapi also covers downloads from Telegrams file server.

The usual flow is:

  1. call GetFile(...) to obtain file metadata and FilePath;
  2. download via one of the file-link helpers.

Use:

  • GetFileByLink(...) when you want the full file in memory as []byte;
  • OpenFileByLink(...) when you want a streaming io.ReadCloser.

Prefer the streaming helpers for large files so you do not buffer everything into memory at once.

Low-level request builders

The raw request builders exist as escape hatches, not as the recommended day-to-day API.

Available helpers:

  • NewRequest(...)
  • NewRequestWithChatID(...)
  • NewUploaderRequest(...)
  • NewUploaderRequestWithChatID(...)

The WithChatID variants matter because chat ID is used for per-chat rate limiting.

Low-level escape hatches

For advanced cases, tgapi keeps raw request builders public:

  • tgapi.NewRequest(...)
  • tgapi.NewRequestWithChatID(...)
  • tgapi.NewUploaderRequest(...)
  • tgapi.NewUploaderRequestWithChatID(...)

These are intentionally lower-level than the typed helpers.

Use them only when:

  • the project has not added a typed wrapper for a Telegram method yet;
  • you need a one-off method quickly and are comfortable supplying the exact method name;
  • you can guarantee that the request and response types actually match Telegrams schema.

Example:

req := tgapi.NewRequest[bool]("deleteWebhook", tgapi.DeleteWebhook{
	DropPendingUpdates: true,
})
ok, err := req.Do(api)

The WithChatID variants matter when the request should participate in per-chat rate limiting.

Error model

At the tgapi layer, most failures come back as ordinary Go errors.

Examples:

  • HTTP transport failures;
  • JSON parsing failures;
  • Telegram API errors formatted as "[code] description";
  • limiter-related failures such as drop-overflow mode;
  • context cancellation and deadline errors from WithContext variants.

Telegram 429 retry_after is handled specially:

  • the limiter lock is updated;
  • the client waits;
  • the request is retried automatically unless the context is canceled.

Related page:

Testability

tgapi is easy to test with a fake http.Client transport.

This is a strong pattern for:

  • asserting JSON request bodies;
  • simulating Telegram API responses;
  • testing method wrappers without real network calls.

The repository already uses that style for both API and uploader-related tests.

Related page:

tgapi vs high-level Laniakea

As a rule of thumb:

  • use MessageContext when responding to the current update;
  • use Bot and plugins when structuring runtime behavior;
  • use tgapi when you need direct Telegram method control;
  • use raw NewRequest or NewUploaderRequest only as the final fallback.

That boundary keeps normal bot code ergonomic without hiding Telegram-specific capabilities from advanced users.