update readmes

This commit is contained in:
2026-08-21 15:51:06 +06:00
parent 016400a821
commit ce48393895
104 changed files with 2615 additions and 333 deletions

View File

@@ -1,17 +1,105 @@
# WebApp
Here you may find simple example of `WebApp`. For work of this example you will need one of two things:
A Kotlin Multiplatform Telegram Web App showcase. One JVM process serves the
compiled browser client, exposes helper routes, and runs the bot with long polling.
* Your own domain with SSL (letsencrypt is okay)
* Test account in telegram
## Bot and server behavior
What is there in this module:
The server binds `0.0.0.0` on the configured port. It serves the production JS
distribution from `WebApp/build/dist/js/productionExecutable`, falling back to
`developmentExecutable`; startup fails if neither directory exists.
* JVM part of this example is a server with simple static webapp sharing and bot which just gives the webapp button to open webapp
* JS part is the WebApp with one button and reacting to chaged user theme and app viewport
Bot handlers include:
## How to run
- `/reply_markup` — a one-time reply-keyboard Web App button;
- `/inline` — an inline Web App button with a small link preview below the text;
- `/attachment_menu` — an inline Web App button with a large preview above the text;
- `/prepareKeyboard` — saves a managed-bot request button for the current user in
an in-memory map; it sends no confirmation;
- any other command — help for `/inline` and `/reply_markup`;
- inline queries — an **Open webApp** results button;
- write-access-allowed events with a Web App name — a thank-you message.
Only `/reply_markup` and `/inline` are registered in Telegram's command menu. Bot
information and every update are printed to standard output.
## HTTP routes
| Route | Behavior |
| --- | --- |
| `GET /*` | Serves the compiled Web App and uses `index.html` as the default file. |
| `POST /inline` | Reads plain request text plus `webAppQueryIdField`, then answers that Web App query with a `Result` article containing the text. |
| `POST /check` | Validates serialized Web App init data and returns `true` or `false`. |
| `POST /setCustomEmoji` | Validates init data, reads `userIdField`, and asks the bot to set the fixed sample emoji status; returns a Boolean. |
| `POST /getPreparedKeyboardButtonId` | Validates init data and returns the user's saved button ID (`200`), no content (`204`), or forbidden (`403`). |
The three validation routes accept JSON shaped as
`{"data":"<WebApp initData>","hash":"<initData hash>"}`. Prepared button IDs are
process-local and disappear on restart.
This is demo routing, not a hardened public API: `/inline` does not validate init
data, and the two user-specific routes accept a separate caller-supplied user ID
after validating the payload. Add identity binding, authorization, rate limits, and
deployment hardening before exposing these endpoints beyond a controlled example.
## Browser client
The Compose HTML client validates `initData`, displays chat/safety information, and
loads a prepared button ID. Its controls demonstrate:
- direct and bot-mediated custom emoji status changes;
- answering in chat through `/inline` and hiding the software keyboard;
- popups, alerts, confirmation, write/contact access, and closing confirmation;
- prepared `requestChat`, header/background/bottom-bar colors, back/main/secondary
buttons, and haptic feedback;
- accelerometer, gyroscope, and device-orientation readings at 200 ms intervals;
- cloud, device, and secure storage; and
- logging the supported Telegram Web App events.
Client feature availability depends on the Telegram platform/version and user-granted
permissions. Opening the URL outside Telegram does not provide authenticated init
data.
## Telegram and hosting setup
1. Create a bot and keep its token private.
2. Build the browser distribution and publish the JVM server through a public HTTPS
origin with a valid certificate; the built-in server itself provides no TLS.
3. Pass that public root URL as `WEB_APP_URL` and configure the bot's Web App/domain
in BotFather where Telegram requires it.
4. Enable inline mode to test inline queries. Configure attachment-menu/write-access
integration separately; `/attachment_menu` only sends a button.
5. Use the bot's private chat for reply-keyboard and `/prepareKeyboard` flows. Emoji,
contact, sensor, storage, and managed-bot examples need compatible clients and
the relevant user permissions/capabilities.
The client calls helper APIs on `window.location.origin`, so deploy it at the same
origin and root routing as the JVM server. Protect server logs, which contain updates.
## Build and run from the repository root
Build the production browser files explicitly with:
```bash
./gradlew run --args="TOKEN WEB_APP_ADDRESS"
./gradlew :WebApp:jsBrowserDistribution
```
`runJvm` also triggers that distribution task through `compileKotlinJvm`. Run from
the repository root because static paths are resolved relative to the working
directory:
```bash
./gradlew :WebApp:runJvm --args="BOT_TOKEN https://webapp.example 8080"
```
The first argument is the required bot token, the second is the required public Web
App URL, and the optional third argument is the port (default `8080` if absent or
nonnumeric). Exact `debug` and `testServer` flags are detected anywhere; keep the
token and URL first, and place a custom numeric port third.
```bash
./gradlew :WebApp:runJvm --args="BOT_TOKEN https://webapp.example 8080 debug testServer"
```
No environment variables are read by this example. Stop both the HTTP server and
bot polling with `Ctrl+C`.

View File

@@ -1,3 +1,4 @@
import dev.inmo.tgbotapi.types.CustomEmojiId
/** Fixed sample custom emoji used by both the Web App and its bot-assisted route. */
val CustomEmojiIdToSet = CustomEmojiId("5424939566278649034")

View File

@@ -3,4 +3,5 @@ import dev.inmo.tgbotapi.types.request.RequestId
import kotlin.random.Random
import kotlin.random.nextUInt
/** Process-local request ID used when the bot saves its sample managed-bot button. */
val preparedSampleKeyboardRequestId = RequestId(Random.nextUInt().toUShort())

View File

@@ -1,5 +1,11 @@
import kotlinx.serialization.Serializable
/**
* JSON body used by server routes that validate Telegram Web App initialization.
*
* @property data raw `initData` received by the browser Web App.
* @property hash hash exposed by the parsed, unsafe initialization data.
*/
@Serializable
data class WebAppDataWrapper(
val data: String,

View File

@@ -38,6 +38,7 @@ import org.w3c.dom.*
import kotlin.random.Random
import kotlin.random.nextUBytes
/** Appends [text] and a paragraph break to this HTML element. */
fun HTMLElement.log(text: String) {
appendText(text)
appendElement("p", {})
@@ -50,6 +51,10 @@ private object RootStyleSheet : StyleSheet() {
}
}
/**
* Renders the Telegram Web App showcase and connects its controls to the JVM
* server's same-origin validation and bot-helper routes.
*/
@OptIn(ExperimentalUnsignedTypes::class)
fun main() {
console.log("Web app started")

View File

@@ -38,13 +38,13 @@ import kotlinx.serialization.json.Json
import java.io.File
/**
* Accepts two parameters:
* Starts the static Web App server and long-polling bot.
*
* * Telegram Token
* * URL where will be placed
* * Port (default 8080)
*
* Will start the server to share the static (index.html and WebApp.js) on 0.0.0.0:8080
* The first element of [args] must be the bot token and the second the public Web
* App URL used in Telegram buttons. The optional third element is parsed as the
* listening port and defaults to `8080`. Exact `debug` and `testServer` values
* enable diagnostic logging and Telegram's test environment, respectively.
* Production JS output is served when present, otherwise development output.
*/
@OptIn(PreviewFeature::class)
suspend fun main(vararg args: String) {