You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -257,21 +229,29 @@ const program = Effect.gen(function* () {
257
229
258
230
#### Dialog
259
231
260
-
`Dialog` module provides constructors for all target types:
232
+
`Dialog` module provides constructors for all target chats:
261
233
262
234
- `Dialog.user(id)` — private chat with a user.
263
235
- `Dialog.group(id)` — group chat.
264
236
- `Dialog.supergroup(id)` — supergroup chat.
265
237
- `Dialog.channel(id)` — channel.
266
238
267
-
To target a specific thread or topic, chain a method on the peer:
239
+
To target a specific topic, chain a method on the peer:
268
240
269
241
- `Dialog.user(id).topic(topicId)` — topic in a private chat.
270
242
- `Dialog.supergroup(id).topic(topicId)` — topic in a forum supergroup.
271
243
- `Dialog.channel(id).directMessages(topicId)` — channel direct messages.
272
244
273
245
`Dialog.ofMessage` extracts the dialog from an incoming `Message` object.
274
246
247
+
**Dialog ID vs peer ID**
248
+
249
+
Bot API uses a single integer (`chat_id`) that [encodes both peer type and ID](https://core.telegram.org/api/bots/ids): user 1:1; group = `-id`; supergroup/channel = `-(id + 1000000000000)`. Some responses return dialog IDs, others peer IDs — wrong format causes errors.
250
+
251
+
**Branded types**
252
+
253
+
`UserId`, `GroupId`, `SupergroupId`, `ChannelId`, `DialogId` prevent mixing. `SupergroupId` and `ChannelId` are the same type (supergroups are a special kind of channel; both share the same ID space). Use `Dialog.decodePeerId`, `Dialog.encodePeerId`, `Dialog.decodeDialogId` to convert.
254
+
275
255
#### Reply
276
256
277
257
`Reply` module provides two ways to create a reply reference:
@@ -281,35 +261,67 @@ To target a specific thread or topic, chain a method on the peer:
281
261
282
262
Both accept an optional `optional` flag — when `true`, the message will be sent even if the referenced message is not found.
283
263
264
+
#### Markup
265
+
266
+
`Markup` module provides reply markup types and constructors:
267
+
268
+
- `inlineKeyboard(rows)` — buttons attached to the message (callback, URL, web app, etc.).
269
+
- `replyKeyboard(rows, options?)` — custom keyboard replacing the default; options include `oneTime`, `resizable`, `selective`, `inputPlaceholder`.
270
+
- `replyKeyboardRemove` — hide a reply keyboard.
271
+
- `forceReply` — show a reply input field.
272
+
273
+
Use `InlineButton` and `ReplyButton` builders to create button rows. Example:
`Send.message` creates a reusable `MessageToSend` that bundles content, markup, reply, and options — everything except the target dialog. This lets you define a message template once and send it to different dialogs later.
292
+
`Send.message` creates a `MessageToSend` — a reusable Effect that bundles content, markup, reply, and options. It does not send until you run it.
293
+
294
+
Flow:
287
295
288
-
`MessageToSend` is pipeable: you can chain modifiers on it and provide the target dialog with `Send.to`.
296
+
1.`Send.message(content)` creates a `MessageToSend` (an Effect that requires `TargetDialog`).
297
+
2. Chain modifiers (`Send.withMarkup`, `Send.withoutNotification`, etc.) to customize.
298
+
3.`Send.to(dialog)` provides the target and returns a plain Effect; the message sends when that Effect runs (e.g. `yield*` in a generator, `Effect.runPromise`, or as part of a larger program).
289
299
290
300
**Example:** Creating and sending prepared messages.
291
301
292
302
```ts
293
303
import { Content, Dialog, Send, Text } from'@grom.js/effect-tg'
294
-
import { pipe } from'effect'
304
+
import { Effect, pipe } from'effect'
295
305
296
-
//Define a reusable message
306
+
//Reusable template
297
307
const welcomeMessage =Send.message(
298
308
Content.text(Text.html('<b>Welcome!</b> Thanks for joining.')),
299
309
)
300
310
301
-
// Send to a specific user
302
-
const program =welcomeMessage.pipe(
303
-
Send.to(Dialog.user(123456789)),
304
-
)
311
+
// Send to different dialogs — runs the Effect to perform the API call
0 commit comments