# telek

> Telegram bots as a state machine rather than a pile of callbacks. Pure transitions, effects on the side, two transports, published for the JVM and native Linux.

Page: https://kotlin.website/telek

## 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

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

dependencies {
    implementation("io.github.youndie.telek:core:<VERSION>")

    // pick one:
    implementation("io.github.youndie.telek:telegram:<VERSION>") // kotlin-telegram-bot
    // implementation("io.github.youndie.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.
