youndie@kotlin.website:~/src$ cat telek/README.md

telek

kmp: jvm + linux · telegram · fsm
Telegram bots as a finite state machine rather than a pile of callbacks. Pure transitions, effects on the side, two transports to pick from, published for the JVM and for native Linux so a bot can ship as one binary.

Why it exists

Every Telegram bot starts as a when over the incoming message and ends as callbacks with a nullable awaitingCity field in a map somewhere. Not laziness — the framework hands you an event and no place to put the fact that this user is halfway through something.

state + input → newState + effects

What that buys

A transition is a function: current state and input in, next state and a list of effects out. It performs none of them. From that one split everything else follows —

  • a transition is testable with no bot, no network and no mocks;
  • a conversation replays from its inputs, because nothing hid in a closure;
  • persisting a wizard is persisting a value, which is what makes it survive a restart.

Two transports, same shape

repositories { maven("https://reposilite.kotlin.website/snapshots") }

dependencies {
    implementation("ru.workinprogress.telek:core:<VERSION>")

    // pick one:
    implementation("ru.workinprogress.telek:telegram:<VERSION>") // kotlin-telegram-bot
    // implementation("ru.workinprogress.telek:ktg:<VERSION>")   // ktgbotapi
}

Swapping transports is only possible because the core never touches the network. If transitions did their own sends, the transport would be baked into every one of them.

Native, because the core is pure

core, ktg, router, router-ktg, persistence and testing publish for JVM, linuxX64 and linuxArm64, so a bot can ship as a single native binary. telegram and router-telegram stay JVM-only, because kotlin-telegram-bot is — the honest shape of the dependency rather than a limitation to work around.