@effect-ak/tg-bot 1.2.4 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/dist/index.cjs +396 -3971
  2. package/dist/index.d.ts +110 -81
  3. package/dist/index.js +391 -3955
  4. package/package.json +16 -12
  5. package/readme.md +34 -465
package/package.json CHANGED
@@ -1,21 +1,27 @@
1
1
  {
2
2
  "name": "@effect-ak/tg-bot",
3
- "version": "1.2.4",
3
+ "version": "1.3.1",
4
4
  "type": "module",
5
- "description": "Telegram Bot runner",
5
+ "description": "Telegram bot framework with long polling, webhooks, and fluent builder API",
6
6
  "license": "MIT",
7
+ "keywords": [
8
+ "telegram",
9
+ "telegram-bot",
10
+ "bot-framework",
11
+ "long-polling",
12
+ "webhook",
13
+ "typescript"
14
+ ],
7
15
  "author": {
8
16
  "name": "Aleksandr Kondaurov",
9
17
  "email": "kondaurov.dev@gmail.com"
10
18
  },
19
+ "homepage": "https://tg-bot-sdk.website",
11
20
  "repository": {
12
21
  "type": "git",
13
- "url": "https://github.com/kondaurovDev/tg-bot-client",
22
+ "url": "https://github.com/kondaurovDev/tg-bot-sdk",
14
23
  "directory": "packages/bot"
15
24
  },
16
- "bugs": {
17
- "url": "https://github.com/effect-ak/tg-bot-client/issues"
18
- },
19
25
  "publishConfig": {
20
26
  "access": "public"
21
27
  },
@@ -26,7 +32,8 @@
26
32
  "types": "./dist/index.d.ts",
27
33
  "import": "./dist/index.js",
28
34
  "require": "./dist/index.cjs"
29
- }
35
+ },
36
+ "./dist/*": "./dist/*"
30
37
  },
31
38
  "files": [
32
39
  "dist/*.js",
@@ -34,11 +41,8 @@
34
41
  "dist/*.d.ts"
35
42
  ],
36
43
  "dependencies": {
37
- "@effect-ak/tg-bot-client": "^1.3.4",
38
- "@effect-ak/tg-bot-api": "^1.3.0"
39
- },
40
- "peerDependencies": {
41
- "effect": "^3.12.7"
44
+ "@effect-ak/tg-bot-client": "^1.4.1",
45
+ "@effect-ak/tg-bot-api": "^1.3.1"
42
46
  },
43
47
  "scripts": {
44
48
  "build": "tsup",
package/readme.md CHANGED
@@ -1,507 +1,76 @@
1
1
  # @effect-ak/tg-bot
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/%40effect-ak%2Ftg-bot)](https://www.npmjs.com/package/@effect-ak/tg-bot)
4
- ![NPM Downloads](https://img.shields.io/npm/dw/%40effect-ak%2Ftg-bot?link=)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ ![NPM Downloads](https://img.shields.io/npm/dw/%40effect-ak%2Ftg-bot)
6
5
 
7
- Effect-based Telegram bot runner that handles long polling, update processing, and error management automatically.
8
-
9
- ## Table of Contents
10
-
11
- - [Features](#features)
12
- - [Installation](#installation)
13
- - [Quick Start](#quick-start)
14
- - [Core Concepts](#core-concepts)
15
- - [Single Mode](#single-mode)
16
- - [Batch Mode](#batch-mode)
17
- - [Bot Response](#bot-response)
18
- - [Usage Examples](#usage-examples)
19
- - [Echo Bot](#echo-bot)
20
- - [Command Handler](#command-handler)
21
- - [Batch Processing](#batch-processing)
22
- - [Using Effect](#using-effectjs)
23
- - [Hot Reload](#hot-reload)
24
- - [Configuration](#configuration)
25
- - [API Reference](#api-reference)
26
- - [How It Works](#how-it-works)
27
- - [Error Handling](#error-handling)
28
- - [Playground](#playground)
29
- - [Related Packages](#related-packages)
30
- - [License](#license)
31
-
32
- ## Features
33
-
34
- - **Effect-based**: Built on top of [Effect](https://effect.website/) for powerful functional programming patterns
35
- - **Two Processing Modes**: Handle updates one-by-one or in batches
36
- - **Automatic Long Polling**: Manages connection to Telegram servers
37
- - **Type-Safe Handlers**: Full TypeScript support for all update types
38
- - **Error Recovery**: Configurable error handling strategies
39
- - **Concurrent Processing**: Process multiple updates in parallel (up to 10 concurrent handlers)
40
- - **Hot Reload**: Reload bot handlers without restarting
41
- - **Built-in Logging**: Configurable logging levels
42
- - **No Public URL Required**: Uses pull model - run bots anywhere, even in a browser
6
+ Telegram bot framework with fluent builder API, long polling, webhooks, and hot reload.
43
7
 
44
8
  ## Installation
45
9
 
46
10
  ```bash
47
- npm install @effect-ak/tg-bot effect
48
- ```
49
-
50
- ```bash
51
- pnpm add @effect-ak/tg-bot effect
52
- ```
53
-
54
- ```bash
55
- yarn add @effect-ak/tg-bot effect
11
+ npm install @effect-ak/tg-bot
56
12
  ```
57
13
 
58
- **Note:** `effect` is a peer dependency and must be installed separately.
59
-
60
14
  ## Quick Start
61
15
 
62
16
  ```typescript
63
- import { runTgChatBot } from "@effect-ak/tg-bot"
17
+ import { createBot } from "@effect-ak/tg-bot"
64
18
 
65
- runTgChatBot({
66
- bot_token: "YOUR_BOT_TOKEN",
67
- mode: "single",
68
- on_message: [
69
- {
70
- match: ({ update }) => !!update.text,
71
- handle: ({ update, ctx }) => ctx.reply(`You said: ${update.text}`)
72
- }
73
- ]
74
- })
75
- ```
76
-
77
- ## Core Concepts
78
-
79
- ### Single Mode
80
-
81
- In single mode, the bot processes each update individually with a dedicated handler for each update type.
82
-
83
- **Handler Format (v2 with guards):**
84
-
85
- ```typescript
86
- on_message: [
87
- {
88
- match: ({ update, ctx }) => ctx.command === "/start", // optional filter
89
- handle: ({ update, ctx }) => ctx.reply("Welcome!") // handler
90
- },
91
- {
92
- match: ({ update }) => !!update.text,
93
- handle: ({ ctx }) => ctx.reply("Got your message!")
94
- },
95
- {
96
- handle: ({ ctx }) => ctx.ignore // fallback (no match = always runs)
97
- }
98
- ]
99
- ```
100
-
101
- **Context helpers:**
102
- - `ctx.reply(text, options?)` - Send a message
103
- - `ctx.replyWithDocument(document, options?)` - Send a document
104
- - `ctx.replyWithPhoto(photo, options?)` - Send a photo
105
- - `ctx.command` - Parsed command (e.g., "/start", "/help")
106
- - `ctx.ignore` - Skip response
19
+ const bot = createBot()
20
+ .onMessage(({ command, text, fallback }) => [
21
+ command("/start", ({ ctx }) => ctx.reply("Welcome!")),
22
+ text(({ update, ctx }) => ctx.reply(`You said: ${update.text}`)),
23
+ fallback(({ ctx }) => ctx.reply("Send me a text message"))
24
+ ])
107
25
 
108
- **Available Handlers:**
109
- - `on_message` - New incoming message
110
- - `on_edited_message` - Message was edited
111
- - `on_channel_post` - New channel post
112
- - `on_edited_channel_post` - Channel post was edited
113
- - `on_inline_query` - Inline query
114
- - `on_chosen_inline_result` - Chosen inline result
115
- - `on_callback_query` - Callback query from inline keyboard
116
- - `on_shipping_query` - Shipping query
117
- - `on_pre_checkout_query` - Pre-checkout query
118
- - `on_poll` - Poll state update
119
- - `on_poll_answer` - User changed their answer in a poll
120
- - `on_my_chat_member` - Bot's chat member status changed
121
- - `on_chat_member` - Chat member status changed
122
- - `on_chat_join_request` - Request to join chat
123
-
124
- **Legacy format (v1 - still supported):**
125
-
126
- ```typescript
127
- on_message: (message) => {
128
- if (!message.text) return BotResponse.ignore
129
- return BotResponse.make({ type: "message", text: "Hello!" })
130
- }
131
- ```
132
-
133
- ### Batch Mode
134
-
135
- In batch mode, the bot receives all updates as an array and processes them together.
136
-
137
- ```typescript
138
- runTgChatBot({
139
- bot_token: "YOUR_BOT_TOKEN",
140
- mode: "batch",
141
- on_batch: async (updates) => {
142
- console.log(`Processing ${updates.length} updates`)
143
- // Process updates...
144
- return true // Continue polling
145
- }
146
- })
26
+ await bot.run({ bot_token: "YOUR_BOT_TOKEN" })
147
27
  ```
148
28
 
149
- ### Bot Response
150
-
151
- Handlers return a `BotResponse` object that describes what to send back to the user.
152
-
153
- **Creating Responses:**
29
+ ## Webhook
154
30
 
155
31
  ```typescript
156
- import { BotResponse } from "@effect-ak/tg-bot"
157
-
158
- // Send a message
159
- BotResponse.make({
160
- type: "message",
161
- text: "Hello!"
162
- })
32
+ const handler = createBot()
33
+ .onMessage(({ command }) => [
34
+ command("/start", ({ ctx }) => ctx.reply("Hello!"))
35
+ ])
36
+ .webhook({ bot_token: "YOUR_BOT_TOKEN" })
163
37
 
164
- // Send a photo
165
- BotResponse.make({
166
- type: "photo",
167
- photo: {
168
- file_content: photoBuffer,
169
- file_name: "image.jpg"
170
- },
171
- caption: "Check this out!"
172
- })
173
-
174
- // Ignore update (don't send anything)
175
- BotResponse.ignore
38
+ // Use as a Request -> Response handler
39
+ export default handler
176
40
  ```
177
41
 
178
- **Supported Response Types:**
179
- All Telegram `send_*` methods are supported: `message`, `photo`, `document`, `video`, `audio`, `voice`, `sticker`, `dice`, etc.
180
-
181
- ## Usage Examples
42
+ ## Advanced: Low-Level API
182
43
 
183
- ### Echo Bot
44
+ For full control without the builder, use `runBot` and `createWebhook` directly:
184
45
 
185
46
  ```typescript
186
- import { runTgChatBot, defineBot } from "@effect-ak/tg-bot"
187
-
188
- const ECHO_BOT = defineBot({
189
- on_message: [
190
- {
191
- match: ({ update }) => !!update.text,
192
- handle: ({ update, ctx }) => ctx.reply(update.text!)
193
- }
194
- ]
195
- })
47
+ import { runBot } from "@effect-ak/tg-bot"
196
48
 
197
- runTgChatBot({
198
- bot_token: "YOUR_BOT_TOKEN",
199
- mode: "single",
200
- ...ECHO_BOT
201
- })
202
- ```
203
-
204
- ### Command Handler
205
-
206
- ```typescript
207
- import { runTgChatBot } from "@effect-ak/tg-bot"
208
- import { MESSAGE_EFFECTS } from "@effect-ak/tg-bot-client"
209
-
210
- runTgChatBot({
211
- bot_token: "YOUR_BOT_TOKEN",
212
- mode: "single",
213
- on_message: [
214
- {
215
- match: ({ ctx }) => ctx.command === "/start",
216
- handle: ({ ctx }) => ctx.reply("Welcome! Send me any message.", {
217
- message_effect_id: MESSAGE_EFFECTS["🎉"]
218
- })
219
- },
220
- {
221
- match: ({ ctx }) => ctx.command === "/help",
222
- handle: ({ ctx }) => ctx.reply("Available commands:\n/start - Start bot\n/help - Show help")
223
- }
224
- ]
225
- })
226
- ```
227
-
228
- ### Batch Processing
229
-
230
- ```typescript
231
- import { runTgChatBot } from "@effect-ak/tg-bot"
232
- import { makeTgBotClient } from "@effect-ak/tg-bot-client"
233
-
234
- const client = makeTgBotClient({ bot_token: "YOUR_BOT_TOKEN" })
235
-
236
- runTgChatBot({
237
- bot_token: "YOUR_BOT_TOKEN",
238
- mode: "batch",
239
- poll: {
240
- batch_size: 100,
241
- poll_timeout: 60
242
- },
243
- on_batch: async (updates) => {
244
- const messages = updates
245
- .map(u => u.message)
246
- .filter(m => m != null)
247
-
248
- await client.execute("send_message", {
249
- chat_id: "ADMIN_CHAT_ID",
250
- text: `Processed ${messages.length} messages`
251
- })
252
-
253
- return true // Continue polling
254
- }
255
- })
256
- ```
257
-
258
- ### Using Effect
259
-
260
- Advanced usage with Effect for composable async operations:
261
-
262
- ```typescript
263
- import { Effect, Micro, pipe } from "effect"
264
- import { launchBot } from "@effect-ak/tg-bot"
265
-
266
- Effect.gen(function* () {
267
- const bot = yield* launchBot({
268
- bot_token: "YOUR_BOT_TOKEN",
269
- mode: "single",
270
- poll: {
271
- log_level: "debug"
272
- },
273
- on_message: [
274
- {
275
- match: ({ update }) => !!update.text,
276
- handle: async ({ ctx }) => {
277
- await Effect.sleep("2 seconds").pipe(Effect.runPromise)
278
- return ctx.reply("Delayed response!")
279
- }
280
- }
281
- ]
282
- })
283
-
284
- // Access bot fiber for control
285
- yield* pipe(
286
- Micro.fiberAwait(bot.fiber()!),
287
- Effect.andThen(Effect.logInfo("Bot stopped")),
288
- Effect.forkDaemon
289
- )
290
- }).pipe(Effect.runPromise)
291
- ```
292
-
293
- ### Hot Reload
294
-
295
- ```typescript
296
- import { runTgChatBot } from "@effect-ak/tg-bot"
297
-
298
- const bot = await runTgChatBot({
49
+ runBot({
299
50
  bot_token: "YOUR_BOT_TOKEN",
300
51
  mode: "single",
301
52
  on_message: [
302
53
  {
303
54
  match: ({ update }) => !!update.text,
304
- handle: ({ ctx }) => ctx.reply("Version 1")
55
+ handle: ({ update, ctx }) => ctx.reply(`You said: ${update.text}`)
305
56
  }
306
57
  ]
307
58
  })
308
-
309
- // Later, reload with new handlers
310
- setTimeout(() => {
311
- bot.reload({
312
- type: "single",
313
- on_message: [
314
- {
315
- match: ({ update }) => !!update.text,
316
- handle: ({ ctx }) => ctx.reply("Version 2 - Hot reloaded!")
317
- }
318
- ]
319
- })
320
- }, 5000)
321
59
  ```
322
60
 
323
- ## Configuration
324
-
325
- ### Poll Settings
326
-
327
- Configure how the bot polls for updates:
328
-
329
- ```typescript
330
- runTgChatBot({
331
- bot_token: "YOUR_BOT_TOKEN",
332
- mode: "single", // or "batch"
333
- poll: {
334
- log_level: "debug", // "info" | "debug"
335
- on_error: "continue", // "stop" | "continue"
336
- batch_size: 50, // 10-100
337
- poll_timeout: 30, // 2-120 seconds
338
- max_empty_responses: 5 // Stop after N empty responses
339
- },
340
- on_message: [/* ... */] // handlers at top level
341
- })
342
- ```
343
-
344
- **Options:**
345
-
346
- - `log_level` (default: `"info"`): Logging verbosity
347
- - `"info"` - Basic logging (new messages, errors)
348
- - `"debug"` - Detailed logging (all updates, responses)
349
-
350
- - `on_error` (default: `"stop"`): Error handling strategy
351
- - `"stop"` - Stop bot on error
352
- - `"continue"` - Continue polling after errors
353
-
354
- - `batch_size` (default: `10`): Number of updates to fetch per poll (10-100)
355
-
356
- - `poll_timeout` (default: `10`): Long polling timeout in seconds (2-120)
357
-
358
- - `max_empty_responses` (default: `undefined`): Stop after N consecutive empty responses (useful for testing)
359
-
360
- ## API Reference
361
-
362
- ### `runTgChatBot(input)`
363
-
364
- Starts the bot with long polling.
365
-
366
- **Parameters:**
367
- - `bot_token` (string, required): Bot token from @BotFather
368
- - `mode` (`"single"` | `"batch"`, required): Processing mode
369
- - `poll` (object, optional): Polling configuration
370
- - `on_message`, `on_callback_query`, etc. (optional): Update handlers (for single mode)
371
- - `on_batch` (required for batch mode): Batch handler function
372
-
373
- **Returns:** `Promise<BotInstance>`
374
-
375
- ### `launchBot(input)`
376
-
377
- Launches bot and returns a bot instance for advanced control.
378
-
379
- **Returns:** `Micro<BotInstance>`
380
- - `BotInstance.reload(mode)` - Hot reload handlers
381
- - `BotInstance.fiber()` - Access underlying Effect fiber
382
-
383
- ### `defineBot(handlers)`
384
-
385
- Helper to define bot handlers with type checking and validation.
386
-
387
- **Parameters:**
388
- - `handlers` (object): Handler functions for different update types
389
-
390
- **Returns:** `BotUpdatesHandlers`
391
-
392
- ### `BotResponse.make(response)`
393
-
394
- Creates a bot response.
395
-
396
- **Parameters:**
397
- - `response` (object): Response configuration with `type` and parameters
398
-
399
- **Returns:** `BotResponse`
400
-
401
- ### `BotResponse.ignore`
402
-
403
- Singleton instance for ignoring updates (no response).
404
-
405
- ## How It Works
406
-
407
- ### Pull Model Architecture
408
-
409
- The Telegram bot API supports both **push** and **pull** notification models. This package uses the **pull** model for several key advantages:
410
-
411
- - **Run bots anywhere without public URLs:** No need to expose public ports or configure webhooks. You can run bots locally, in a browser, or behind firewalls.
412
- - **Leverage Telegram's infrastructure:** Telegram stores updates for 24 hours, giving you plenty of time to process them.
413
- - **Simpler deployment:** No SSL certificates, no webhook configuration, no reverse proxies required.
414
-
415
- ### Architecture Diagram
416
-
417
- ```mermaid
418
- graph TD
419
- User[User] -->|Sends message| TgBot[Telegram Bot]
420
- TgBot -->|Stores for 24h| Queue[Updates Queue<br/>api.telegram.org/bot/updates]
421
-
422
- subgraph Your Code
423
- Runner[Bot Runner<br/>@effect-ak/tg-bot]
424
- Handler[Your Handler Function]
425
- end
426
-
427
- Runner -->|Long polling| Queue
428
- Runner -->|Invokes with update| Handler
429
- Handler -->|Returns BotResponse| Runner
430
- Runner -->|Sends response| TgBot
431
- ```
432
-
433
- **How it works:**
434
- 1. User sends a message to your bot
435
- 2. Telegram stores the update in a queue for 24 hours
436
- 3. Bot runner polls the queue using long polling
437
- 4. Runner invokes your handler function with the update
438
- 5. Handler returns a `BotResponse`
439
- 6. Runner sends the response back to Telegram
440
- 7. Runner tracks the last processed update ID to avoid duplicates
441
-
442
- ## Error Handling
443
-
444
- The bot automatically handles errors at different levels:
445
-
446
- ### Update Handler Errors
447
-
448
- If a handler throws an error, the bot:
449
- 1. Logs the error with update details
450
- 2. Sends an error message to the user (in single mode)
451
- 3. Continues processing other updates (if `on_error: "continue"`)
452
-
453
- ```typescript
454
- on_message: [
455
- {
456
- match: ({ ctx }) => ctx.command === "/error",
457
- handle: () => {
458
- throw new Error("Something went wrong!")
459
- // Bot will catch this and send error message to user
460
- }
461
- },
462
- {
463
- match: ({ update }) => !!update.text,
464
- handle: ({ ctx }) => ctx.reply("OK")
465
- }
466
- ]
467
- ```
468
-
469
- ### Batch Handler Errors
470
-
471
- In batch mode, returning `false` stops the bot:
472
-
473
- ```typescript
474
- on_batch: async (updates) => {
475
- try {
476
- // Process updates
477
- return true // Continue
478
- } catch (error) {
479
- console.error(error)
480
- return false // Stop bot
481
- }
482
- }
483
- ```
484
-
485
- ### Concurrent Processing
486
-
487
- In single mode, up to 10 updates are processed concurrently. If some handlers fail, others continue processing.
488
-
489
- ## Playground
490
-
491
- Develop and test your bot directly in the browser:
492
-
493
- **[Chat Bot Playground](https://effect-ak.github.io/telegram-bot-playground/)**
494
-
495
- No installation required - perfect for quick prototyping and learning!
61
+ ## Features
496
62
 
497
- ## Related Packages
63
+ - **Builder API** — fluent `createBot()` with typed helpers (command, text, photo, etc.)
64
+ - **Two Modes** — single (one-by-one) and batch processing
65
+ - **Polling & Webhooks** — long polling or webhook handler for serverless
66
+ - **Type-Safe Handlers** — all Telegram update types supported
67
+ - **Hot Reload** — update handlers without restarting
68
+ - **Guard Handlers** — match/handle pattern for routing updates
498
69
 
499
- This package is part of the `tg-bot-client` monorepo:
70
+ ## Documentation
500
71
 
501
- - **[@effect-ak/tg-bot-client](../client)** - Type-safe HTTP client for Telegram Bot API
502
- - **[@effect-ak/tg-bot-api](../api)** - TypeScript types for Telegram Bot API and Mini Apps
503
- - **[@effect-ak/tg-bot-codegen](../codegen)** - Code generator that parses official documentation
72
+ Full documentation, examples, and configuration: **[tg-bot-sdk.website](https://tg-bot-sdk.website)**
504
73
 
505
74
  ## License
506
75
 
507
- MIT © [Aleksandr Kondaurov](https://github.com/effect-ak)
76
+ MIT