REPOSITORY / ScuroNeko/Laniakea

Wiki

KNOWLEDGE REPOSITORY
9
Migration
ScuroNeko edited this page 2026-08-19 14:59:10 +03:00

Migration

Russian version: Migration-RU

Use this page when upgrading an existing bot between Laniakea release candidates. It focuses on migration-impacting API and behavior changes, especially the larger RC transitions that require code edits instead of just a rebuild.

How to use this page

For the full release history, read the repository CHANGELOG.md. This page is narrower: it groups the most important upgrade work by milestone and calls out what usually needs to change in real bots.

Also see:

When jumping across multiple RC versions:

  1. Update to the latest version in go.mod.
  2. Fix compile errors first.
  3. Revisit startup and shutdown code.
  4. Revisit handler signatures.
  5. Revisit any direct tgapi calls and renamed types.
  6. Run tests against realistic update payloads and callback data.

The largest migration points in the current history are rc.4, rc.7, rc.10, rc.12, and the v1.0.0 stable release.

v1.0.0

v1.0.0 is a public-API hygiene release. Most changes are renames and type-system tightenings that cause compile errors and are easy to fix mechanically.

Handler type rename: MsgContextMessageContext

Every handler signature and every explicit type reference to MsgContext must be renamed to MessageContext.

// before
func ping(ctx *laniakea.MsgContext, db *App) error { ... }

// after
func ping(ctx *laniakea.MessageContext, db *App) error { ... }

This includes CommandExecutor, MiddlewareExecutor, SceneContext.MessageContext, and any local variable type annotations.

Runner builder change: Onetime and Timeout removed

The Onetime(bool) and Timeout(duration) builder methods have been replaced by Every(duration) and Async(bool).

// before — one-time sync
runner.Onetime(true).Async(false)

// after — one-time sync
runner.Async(false)

// before — periodic
runner.Timeout(5 * time.Minute)

// after — periodic
runner.Every(5 * time.Minute)

The default remains async one-shot (Every(0).Async(true)), so runners without a builder call are unaffected.

Observer method renames

If you implement the Observer interface directly, rename the two affected methods:

Before After
OnReceiveUpdate(UpdateReceivedEvent) OnUpdateReceived(UpdateReceivedEvent)
OnHandledUpdate(UpdateHandledEvent) OnUpdateHandled(UpdateHandledEvent)

Scene.PluginName unexported

Scene.PluginName was a mutable public field. It is now unexported. Remove any reads or writes to this field; the framework assigns it during AddPlugins(...) registration.

SceneSession.Data unexported

SceneSession.Data []byte was a public field. It is now unexported. Use the accessor helpers: HasData(), BindData(...), SaveData(...), ClearData().

BotPayloadType* constants are now const

BotPayloadTypeJSON, BotPayloadTypeBase64, BotPayloadTypeCompact, and BotPayloadTypeCompactBase64 were var. They are now const. Any code assigning to them will fail to compile.

Webhook error sentinels

Inline errors.New(...) error values returned from webhook startup have been replaced by exported sentinels. If you were comparing webhook startup errors with ==, switch to errors.Is(...).

v1.0.0-rc.12

rc.12 is mainly a handler and validation release. The biggest breaking change is that handlers now return error.

What changed

  • CommandExecutor[T] changed from func(ctx *MsgContext, db T) to func(ctx *MsgContext, db T) error.
  • Plugin.Command(...), Plugin.Payload(...), and Plugin.AddUpdateHandler(...) now expect error-returning handlers.
  • Long plain-text reply helpers were added: AnswerLong(...), AnswerLongf(...), KeyboardLong(...), and SplitMessageText(...).
  • Message and caption validation now happens before sending Telegram API requests.
  • Optional strict callback payload decoding was added through StrictPayloadType.

What to migrate

Update every handler to return error, even if it normally succeeds:

func ping(ctx *laniakea.MsgContext, db *App) error {
	ctx.Answer("pong")
	return nil
}

If your old handlers did their own error reporting inline, you can now choose between:

  • still replying manually and returning nil;
  • or returning an error and letting the bot's centralized error handling format the user-visible response.

If you previously used Answer(...) for text that could exceed Telegram's single-message limit, consider moving to AnswerLong(...) or KeyboardLong(...) instead of changing the behavior of existing calls.

If your callback payloads relied on tolerant decoding, be aware that enabling strict payload mode will reject payloads encoded in a different format than the bot default.

v1.0.0-rc.10

rc.10 is the largest migration step in the current codebase. It changed construction, run semantics, handler dependency typing, plugin registration behavior, and update handling.

What changed

  • NewBot[T](opts) now returns (*Bot[T], error).
  • Run() and RunWithContext(ctx) now return error.
  • Bot instances became explicitly single-use.
  • Handler dependency typing changed from forced *T usage to consistent T.
  • The old DatabaseContext(...), GetDBContext(), and DbLogger[T] names were replaced by the app-data-based SetAppData(...), GetAppData(), and AppDataLogger[T] model.
  • Plugin.AddUpdateHandler(...) was introduced for non-command update routing.
  • Builder helpers such as NewMiddleware(...) now return values instead of pointers.
  • Plugin registration now snapshots plugin state at AddPlugins(...).
  • BaseMenuButton was renamed to MenuButton.

What to migrate

Construction now needs explicit error handling:

bot, err := laniakea.NewBot[*sql.DB](opts)
if err != nil {
	return err
}
defer bot.Close()

Startup now also returns errors:

if err := bot.RunWithContext(ctx); err != nil {
	return err
}

If your bot type used Bot[MyDB] while handlers expected *MyDB, update the generic parameter to match what you actually want to inject. Shared dependencies should usually use pointer types:

bot, err := laniakea.NewBot[*sql.DB](opts)
bot.SetAppData(db)

If you mutated plugins after AddPlugins(...), stop doing that. Register commands, payloads, middleware, logger configuration, and OnClose hooks before handing the plugin to the bot.

If you previously routed every update through commands and payloads, consider moving non-command update types to AddUpdateHandler(...) instead of overloading command logic.

Typical rc.10 fixes

  • add err handling after NewBot(...);
  • add err handling after Run() or RunWithContext(...);
  • replace Bot[MyDB] with Bot[*MyDB] where shared mutable dependencies are intended;
  • replace *NewMiddleware(...)-style assumptions with direct values;
  • rename BaseMenuButton usages to MenuButton.

v1.0.0-rc.7

rc.7 focused on shutdown and logging model cleanup.

What changed

  • Bot.Close(ctx) became Bot.Close().
  • remote Telegram session shutdown moved to Bot.CloseRemote(ctx).
  • tgapi.API.CloseApi() was renamed to tgapi.API.Close().
  • tgapi.API.Close() was renamed to tgapi.API.CloseRemote().
  • tgapi.API.CloseWithContext() was renamed to tgapi.API.CloseRemoteWithContext(ctx).
  • plugin lifecycle APIs such as SetLogger, RemoveLogger, SetOnClose, and Plugin.Close() were added.

What to migrate

Replace local shutdown calls:

defer bot.Close()

If you actually need Telegram Bot API remote close semantics, call them explicitly:

if err := bot.CloseRemote(ctx); err != nil {
	return err
}

And update direct tgapi calls to the renamed close methods.

v1.0.0-rc.4

rc.4 mainly affects callers using lower-level tgapi webhook APIs.

What changed

  • WithContext variants were added across more tgapi methods.
  • Webhook certificate upload moved away from the JSON SetWebhook.Certificate path.
  • Certificate upload now goes through uploader-based webhook APIs.

What to migrate

If you were sending webhook certificates through SetWebhook.Certificate, switch to Uploader.SetWebhook(...) or Uploader.SetWebhookWithContext(...).

If you maintain infrastructure code around deadlines or cancellation, prefer the newer WithContext variants consistently instead of wrapping only some calls.

Behavior changes worth noticing

Not every important change is a compile-time break.

Pay attention to these behavior changes after upgrading:

  • polling retry now uses exponential backoff instead of busy looping;
  • RunWithContext does not close resources automatically; callers still need Close();
  • callback payload decoding can now be strict or tolerant depending on configuration;
  • message and caption validation now fails earlier, before Telegram requests are made;
  • long plain-text replies now have dedicated helpers instead of implicit splitting.

After upgrading

After a version jump, it is worth rechecking:

  • startup and shutdown flows;
  • command and payload handlers;
  • callback payload decoding;
  • any direct tgapi usage;
  • tests that use update fixtures or callback payload samples.

When in doubt

If an upgrade feels ambiguous, compare:

  • the relevant section in CHANGELOG.md;
  • current examples in README.md;
  • the focused wiki pages linked above.