@icanseeuanywhere/telekaf 4.16.3

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 (172) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +978 -0
  3. package/filters.d.ts +1 -0
  4. package/filters.js +1 -0
  5. package/format.d.ts +1 -0
  6. package/format.js +1 -0
  7. package/future.d.ts +1 -0
  8. package/future.js +1 -0
  9. package/lib/button.js +101 -0
  10. package/lib/cli.mjs +105 -0
  11. package/lib/composer.js +582 -0
  12. package/lib/context.js +1277 -0
  13. package/lib/core/helpers/args.js +58 -0
  14. package/lib/core/helpers/check.js +56 -0
  15. package/lib/core/helpers/compact.js +17 -0
  16. package/lib/core/helpers/deunionize.js +13 -0
  17. package/lib/core/helpers/formatting.js +91 -0
  18. package/lib/core/helpers/util.js +50 -0
  19. package/lib/core/network/client.js +320 -0
  20. package/lib/core/network/error.js +21 -0
  21. package/lib/core/network/multipart-stream.js +61 -0
  22. package/lib/core/network/polling.js +87 -0
  23. package/lib/core/network/webhook.js +54 -0
  24. package/lib/core/types/rich-message.js +102 -0
  25. package/lib/core/types/typegram.js +28 -0
  26. package/lib/filters.js +69 -0
  27. package/lib/format.js +38 -0
  28. package/lib/future.js +166 -0
  29. package/lib/index.js +49 -0
  30. package/lib/input.js +61 -0
  31. package/lib/markup.js +111 -0
  32. package/lib/middleware.js +2 -0
  33. package/lib/reactions.js +84 -0
  34. package/lib/router.js +46 -0
  35. package/lib/scenes/base.js +39 -0
  36. package/lib/scenes/context.js +104 -0
  37. package/lib/scenes/index.js +21 -0
  38. package/lib/scenes/stage.js +49 -0
  39. package/lib/scenes/wizard/context.js +31 -0
  40. package/lib/scenes/wizard/index.js +45 -0
  41. package/lib/scenes.js +17 -0
  42. package/lib/session.js +166 -0
  43. package/lib/telegraf.js +246 -0
  44. package/lib/telegram-types.js +6 -0
  45. package/lib/telegram.js +1265 -0
  46. package/lib/types.js +2 -0
  47. package/lib/utils.js +5 -0
  48. package/markup.d.ts +1 -0
  49. package/markup.js +1 -0
  50. package/package.json +138 -0
  51. package/scenes.d.ts +1 -0
  52. package/scenes.js +1 -0
  53. package/session.d.ts +1 -0
  54. package/session.js +1 -0
  55. package/src/button.ts +182 -0
  56. package/src/composer.ts +1008 -0
  57. package/src/context.ts +1739 -0
  58. package/src/core/helpers/args.ts +63 -0
  59. package/src/core/helpers/check.ts +71 -0
  60. package/src/core/helpers/compact.ts +18 -0
  61. package/src/core/helpers/deunionize.ts +26 -0
  62. package/src/core/helpers/formatting.ts +119 -0
  63. package/src/core/helpers/util.ts +96 -0
  64. package/src/core/network/client.ts +396 -0
  65. package/src/core/network/error.ts +29 -0
  66. package/src/core/network/multipart-stream.ts +45 -0
  67. package/src/core/network/polling.ts +94 -0
  68. package/src/core/network/webhook.ts +58 -0
  69. package/src/core/types/rich-message.ts +474 -0
  70. package/src/core/types/typegram.ts +55 -0
  71. package/src/filters.ts +109 -0
  72. package/src/format.ts +110 -0
  73. package/src/future.ts +231 -0
  74. package/src/index.ts +18 -0
  75. package/src/input.ts +59 -0
  76. package/src/markup.ts +142 -0
  77. package/src/middleware.ts +24 -0
  78. package/src/reactions.ts +118 -0
  79. package/src/router.ts +55 -0
  80. package/src/scenes/base.ts +52 -0
  81. package/src/scenes/context.ts +136 -0
  82. package/src/scenes/index.ts +21 -0
  83. package/src/scenes/stage.ts +71 -0
  84. package/src/scenes/wizard/context.ts +58 -0
  85. package/src/scenes/wizard/index.ts +63 -0
  86. package/src/scenes.ts +1 -0
  87. package/src/session.ts +204 -0
  88. package/src/telegraf.ts +354 -0
  89. package/src/telegram-types.ts +250 -0
  90. package/src/telegram.ts +1671 -0
  91. package/src/types.ts +2 -0
  92. package/src/utils.ts +1 -0
  93. package/types.d.ts +1 -0
  94. package/types.js +1 -0
  95. package/typings/button.d.ts +36 -0
  96. package/typings/button.d.ts.map +1 -0
  97. package/typings/composer.d.ts +227 -0
  98. package/typings/composer.d.ts.map +1 -0
  99. package/typings/context.d.ts +693 -0
  100. package/typings/context.d.ts.map +1 -0
  101. package/typings/core/helpers/args.d.ts +11 -0
  102. package/typings/core/helpers/args.d.ts.map +1 -0
  103. package/typings/core/helpers/check.d.ts +56 -0
  104. package/typings/core/helpers/check.d.ts.map +1 -0
  105. package/typings/core/helpers/compact.d.ts +4 -0
  106. package/typings/core/helpers/compact.d.ts.map +1 -0
  107. package/typings/core/helpers/deunionize.d.ts +18 -0
  108. package/typings/core/helpers/deunionize.d.ts.map +1 -0
  109. package/typings/core/helpers/formatting.d.ts +30 -0
  110. package/typings/core/helpers/formatting.d.ts.map +1 -0
  111. package/typings/core/helpers/util.d.ts +27 -0
  112. package/typings/core/helpers/util.d.ts.map +1 -0
  113. package/typings/core/network/client.d.ts +55 -0
  114. package/typings/core/network/client.d.ts.map +1 -0
  115. package/typings/core/network/error.d.ts +16 -0
  116. package/typings/core/network/error.d.ts.map +1 -0
  117. package/typings/core/network/multipart-stream.d.ts +19 -0
  118. package/typings/core/network/multipart-stream.d.ts.map +1 -0
  119. package/typings/core/network/polling.d.ts +16 -0
  120. package/typings/core/network/polling.d.ts.map +1 -0
  121. package/typings/core/network/webhook.d.ts +7 -0
  122. package/typings/core/network/webhook.d.ts.map +1 -0
  123. package/typings/core/types/rich-message.d.ts +295 -0
  124. package/typings/core/types/rich-message.d.ts.map +1 -0
  125. package/typings/core/types/typegram.d.ts +45 -0
  126. package/typings/core/types/typegram.d.ts.map +1 -0
  127. package/typings/filters.d.ts +18 -0
  128. package/typings/filters.d.ts.map +1 -0
  129. package/typings/format.d.ts +22 -0
  130. package/typings/format.d.ts.map +1 -0
  131. package/typings/future.d.ts +12 -0
  132. package/typings/future.d.ts.map +1 -0
  133. package/typings/index.d.ts +16 -0
  134. package/typings/index.d.ts.map +1 -0
  135. package/typings/input.d.ts +55 -0
  136. package/typings/input.d.ts.map +1 -0
  137. package/typings/markup.d.ts +27 -0
  138. package/typings/markup.d.ts.map +1 -0
  139. package/typings/middleware.d.ts +8 -0
  140. package/typings/middleware.d.ts.map +1 -0
  141. package/typings/reactions.d.ts +32 -0
  142. package/typings/reactions.d.ts.map +1 -0
  143. package/typings/router.d.ts +21 -0
  144. package/typings/router.d.ts.map +1 -0
  145. package/typings/scenes/base.d.ts +22 -0
  146. package/typings/scenes/base.d.ts.map +1 -0
  147. package/typings/scenes/context.d.ts +36 -0
  148. package/typings/scenes/context.d.ts.map +1 -0
  149. package/typings/scenes/index.d.ts +11 -0
  150. package/typings/scenes/index.d.ts.map +1 -0
  151. package/typings/scenes/stage.d.ts +24 -0
  152. package/typings/scenes/stage.d.ts.map +1 -0
  153. package/typings/scenes/wizard/context.d.ts +29 -0
  154. package/typings/scenes/wizard/context.d.ts.map +1 -0
  155. package/typings/scenes/wizard/index.d.ts +16 -0
  156. package/typings/scenes/wizard/index.d.ts.map +1 -0
  157. package/typings/scenes.d.ts +2 -0
  158. package/typings/scenes.d.ts.map +1 -0
  159. package/typings/session.d.ts +55 -0
  160. package/typings/session.d.ts.map +1 -0
  161. package/typings/telegraf.d.ts +117 -0
  162. package/typings/telegraf.d.ts.map +1 -0
  163. package/typings/telegram-types.d.ts +134 -0
  164. package/typings/telegram-types.d.ts.map +1 -0
  165. package/typings/telegram.d.ts +691 -0
  166. package/typings/telegram.d.ts.map +1 -0
  167. package/typings/types.d.ts +3 -0
  168. package/typings/types.d.ts.map +1 -0
  169. package/typings/utils.d.ts +2 -0
  170. package/typings/utils.d.ts.map +1 -0
  171. package/utils.d.ts +1 -0
  172. package/utils.js +1 -0
package/src/context.ts ADDED
@@ -0,0 +1,1739 @@
1
+ import * as tg from './core/types/typegram'
2
+ import * as tt from './telegram-types'
3
+ import { Deunionize, PropOr, UnionKeys } from './core/helpers/deunionize'
4
+ import ApiClient from './core/network/client'
5
+ import { Guard, Guarded, Keyed, MaybeArray } from './core/helpers/util'
6
+ import Telegram from './telegram'
7
+ import { FmtString } from './format'
8
+ import d from 'debug'
9
+ import { Digit, MessageReactions } from './reactions'
10
+
11
+ const debug = d('telegraf:context')
12
+
13
+ type Tail<T> = T extends [unknown, ...infer U] ? U : never
14
+
15
+ type Shorthand<FName extends Exclude<keyof Telegram, keyof ApiClient>> = Tail<
16
+ Parameters<Telegram[FName]>
17
+ >
18
+
19
+ /**
20
+ * Narrows down `C['update']` (and derived getters)
21
+ * to specific update type `U`.
22
+ *
23
+ * Used by [[`Composer`]],
24
+ * possibly useful for splitting a bot into multiple files.
25
+ */
26
+ export type NarrowedContext<
27
+ C extends Context,
28
+ U extends tg.Update,
29
+ > = Context<U> & Omit<C, keyof Context>
30
+
31
+ export type FilteredContext<
32
+ Ctx extends Context,
33
+ Filter extends tt.UpdateType | Guard<Ctx['update']>,
34
+ > = Filter extends tt.UpdateType
35
+ ? NarrowedContext<Ctx, Extract<tg.Update, Record<Filter, object>>>
36
+ : NarrowedContext<Ctx, Guarded<Filter>>
37
+
38
+ export class Context<U extends Deunionize<tg.Update> = tg.Update> {
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
+ readonly state: Record<string | symbol, any> = {}
41
+
42
+ constructor(
43
+ readonly update: U,
44
+ readonly telegram: Telegram,
45
+ readonly botInfo: tg.UserFromGetMe
46
+ ) {}
47
+
48
+ get updateType() {
49
+ for (const key in this.update) {
50
+ if (typeof this.update[key] === 'object') return key as UpdateTypes<U>
51
+ }
52
+
53
+ throw new Error(
54
+ `Cannot determine \`updateType\` of ${JSON.stringify(this.update)}`
55
+ )
56
+ }
57
+
58
+ get me() {
59
+ return this.botInfo?.username
60
+ }
61
+
62
+ /**
63
+ * @deprecated Use ctx.telegram instead
64
+ */
65
+ get tg() {
66
+ return this.telegram
67
+ }
68
+
69
+ get message() {
70
+ return this.update.message as PropOr<U, 'message'>
71
+ }
72
+
73
+ get editedMessage() {
74
+ return this.update.edited_message as PropOr<U, 'edited_message'>
75
+ }
76
+
77
+ get inlineQuery() {
78
+ return this.update.inline_query as PropOr<U, 'inline_query'>
79
+ }
80
+
81
+ get shippingQuery() {
82
+ return this.update.shipping_query as PropOr<U, 'shipping_query'>
83
+ }
84
+
85
+ get preCheckoutQuery() {
86
+ return this.update.pre_checkout_query as PropOr<U, 'pre_checkout_query'>
87
+ }
88
+
89
+ get chosenInlineResult() {
90
+ return this.update.chosen_inline_result as PropOr<U, 'chosen_inline_result'>
91
+ }
92
+
93
+ get channelPost() {
94
+ return this.update.channel_post as PropOr<U, 'channel_post'>
95
+ }
96
+
97
+ get editedChannelPost() {
98
+ return this.update.edited_channel_post as PropOr<U, 'edited_channel_post'>
99
+ }
100
+
101
+ get messageReaction() {
102
+ return this.update.message_reaction as PropOr<U, 'message_reaction'>
103
+ }
104
+
105
+ get messageReactionCount() {
106
+ return this.update.message_reaction_count as PropOr<
107
+ U,
108
+ 'message_reaction_count'
109
+ >
110
+ }
111
+
112
+ get callbackQuery() {
113
+ return this.update.callback_query as PropOr<U, 'callback_query'>
114
+ }
115
+
116
+ get poll() {
117
+ return this.update.poll as PropOr<U, 'poll'>
118
+ }
119
+
120
+ get pollAnswer() {
121
+ return this.update.poll_answer as PropOr<U, 'poll_answer'>
122
+ }
123
+
124
+ get myChatMember() {
125
+ return this.update.my_chat_member as PropOr<U, 'my_chat_member'>
126
+ }
127
+
128
+ get chatMember() {
129
+ return this.update.chat_member as PropOr<U, 'chat_member'>
130
+ }
131
+
132
+ get chatJoinRequest() {
133
+ return this.update.chat_join_request as PropOr<U, 'chat_join_request'>
134
+ }
135
+
136
+ get chatBoost() {
137
+ return this.update.chat_boost as PropOr<U, 'chat_boost'>
138
+ }
139
+
140
+ get removedChatBoost() {
141
+ return this.update.removed_chat_boost as PropOr<U, 'removed_chat_boost'>
142
+ }
143
+
144
+ /** Shorthand for any `message` object present in the current update. One of
145
+ * `message`, `edited_message`, `channel_post`, `edited_channel_post` or
146
+ * `callback_query.message`
147
+ */
148
+ get msg() {
149
+ return getMessageFromAnySource(this) as GetMsg<U> & Msg
150
+ }
151
+
152
+ /** Shorthand for any message_id present in the current update. */
153
+ get msgId() {
154
+ return getMsgIdFromAnySource(this) as GetMsgId<U>
155
+ }
156
+
157
+ get chat(): Getter<U, 'chat'> {
158
+ return (
159
+ this.msg ??
160
+ this.messageReaction ??
161
+ this.messageReactionCount ??
162
+ this.chatJoinRequest ??
163
+ this.chatMember ??
164
+ this.myChatMember ??
165
+ this.removedChatBoost
166
+ )?.chat as Getter<U, 'chat'>
167
+ }
168
+
169
+ get senderChat() {
170
+ const msg = this.msg
171
+ return (msg?.has('sender_chat') && msg.sender_chat) as Getter<
172
+ U,
173
+ 'sender_chat'
174
+ >
175
+ }
176
+
177
+ get from() {
178
+ return getUserFromAnySource(this) as GetUserFromAnySource<U>
179
+ }
180
+
181
+ get inlineMessageId() {
182
+ return (this.callbackQuery ?? this.chosenInlineResult)?.inline_message_id
183
+ }
184
+
185
+ get passportData() {
186
+ if (this.message == null) return undefined
187
+ if (!('passport_data' in this.message)) return undefined
188
+ return this.message?.passport_data
189
+ }
190
+
191
+ get webAppData() {
192
+ if (!(this.message && 'web_app_data' in this.message)) return undefined
193
+
194
+ const { data, button_text } = this.message.web_app_data
195
+
196
+ return {
197
+ data: {
198
+ json<T>() {
199
+ return JSON.parse(data) as T
200
+ },
201
+ text() {
202
+ return data
203
+ },
204
+ },
205
+ button_text,
206
+ }
207
+ }
208
+
209
+ /**
210
+ * @deprecated use {@link Telegram.webhookReply}
211
+ */
212
+ get webhookReply(): boolean {
213
+ return this.telegram.webhookReply
214
+ }
215
+
216
+ set webhookReply(enable: boolean) {
217
+ this.telegram.webhookReply = enable
218
+ }
219
+
220
+ get reactions() {
221
+ return MessageReactions.from(this)
222
+ }
223
+
224
+ /**
225
+ * @internal
226
+ */
227
+ assert<T extends string | number | object>(
228
+ value: T | undefined,
229
+ method: string
230
+ ): asserts value is T {
231
+ if (value === undefined) {
232
+ throw new TypeError(
233
+ `Telegraf: "${method}" isn't available for "${this.updateType}"`
234
+ )
235
+ }
236
+ }
237
+
238
+ has<Filter extends tt.UpdateType | Guard<Context['update']>>(
239
+ filters: MaybeArray<Filter>
240
+ ): this is FilteredContext<Context, Filter> {
241
+ if (!Array.isArray(filters)) filters = [filters]
242
+ for (const filter of filters)
243
+ if (
244
+ // TODO: this should change to === 'function' once TS bug is fixed
245
+ // https://github.com/microsoft/TypeScript/pull/51502
246
+ typeof filter !== 'string'
247
+ ? // filter is a type guard
248
+ filter(this.update)
249
+ : // check if filter is the update type
250
+ filter in this.update
251
+ )
252
+ return true
253
+
254
+ return false
255
+ }
256
+
257
+ get text() {
258
+ return getTextAndEntitiesFromAnySource(this)[0] as GetText<U>
259
+ }
260
+
261
+ entities<EntityTypes extends tg.MessageEntity['type'][]>(
262
+ ...types: EntityTypes
263
+ ) {
264
+ const [text = '', entities = []] = getTextAndEntitiesFromAnySource(this)
265
+
266
+ type SelectedTypes = EntityTypes extends []
267
+ ? tg.MessageEntity['type']
268
+ : EntityTypes[number]
269
+
270
+ return (
271
+ types.length
272
+ ? entities.filter((entity) => types.includes(entity.type))
273
+ : entities
274
+ ).map((entity) => ({
275
+ ...entity,
276
+ fragment: text.slice(entity.offset, entity.offset + entity.length),
277
+ })) as (tg.MessageEntity & { type: SelectedTypes; fragment: string })[]
278
+ }
279
+
280
+ /**
281
+ * @see https://core.telegram.org/bots/api#answerinlinequery
282
+ */
283
+ answerInlineQuery(...args: Shorthand<'answerInlineQuery'>) {
284
+ this.assert(this.inlineQuery, 'answerInlineQuery')
285
+ return this.telegram.answerInlineQuery(this.inlineQuery.id, ...args)
286
+ }
287
+
288
+ /**
289
+ * @see https://core.telegram.org/bots/api#answercallbackquery
290
+ */
291
+ answerCbQuery(...args: Shorthand<'answerCbQuery'>) {
292
+ this.assert(this.callbackQuery, 'answerCbQuery')
293
+ return this.telegram.answerCbQuery(this.callbackQuery.id, ...args)
294
+ }
295
+
296
+ /**
297
+ * @see https://core.telegram.org/bots/api#answercallbackquery
298
+ */
299
+ answerGameQuery(...args: Shorthand<'answerGameQuery'>) {
300
+ this.assert(this.callbackQuery, 'answerGameQuery')
301
+ return this.telegram.answerGameQuery(this.callbackQuery.id, ...args)
302
+ }
303
+
304
+ /**
305
+ * Shorthand for {@link Telegram.getUserChatBoosts}
306
+ */
307
+ getUserChatBoosts() {
308
+ this.assert(this.chat, 'getUserChatBoosts')
309
+ this.assert(this.from, 'getUserChatBoosts')
310
+ return this.telegram.getUserChatBoosts(this.chat.id, this.from.id)
311
+ }
312
+
313
+ /**
314
+ * @see https://core.telegram.org/bots/api#answershippingquery
315
+ */
316
+ answerShippingQuery(...args: Shorthand<'answerShippingQuery'>) {
317
+ this.assert(this.shippingQuery, 'answerShippingQuery')
318
+ return this.telegram.answerShippingQuery(this.shippingQuery.id, ...args)
319
+ }
320
+
321
+ /**
322
+ * @see https://core.telegram.org/bots/api#answerprecheckoutquery
323
+ */
324
+ answerPreCheckoutQuery(...args: Shorthand<'answerPreCheckoutQuery'>) {
325
+ this.assert(this.preCheckoutQuery, 'answerPreCheckoutQuery')
326
+ return this.telegram.answerPreCheckoutQuery(
327
+ this.preCheckoutQuery.id,
328
+ ...args
329
+ )
330
+ }
331
+
332
+ /**
333
+ * @see https://core.telegram.org/bots/api#editmessagetext
334
+ */
335
+ editMessageText(text: string | FmtString, extra?: tt.ExtraEditMessageText) {
336
+ this.assert(this.msgId ?? this.inlineMessageId, 'editMessageText')
337
+ return this.telegram.editMessageText(
338
+ this.chat?.id,
339
+ this.msgId,
340
+ this.inlineMessageId,
341
+ text,
342
+ extra
343
+ )
344
+ }
345
+
346
+ /**
347
+ * @see https://core.telegram.org/bots/api#editmessagecaption
348
+ */
349
+ editMessageCaption(
350
+ caption: string | FmtString | undefined,
351
+ extra?: tt.ExtraEditMessageCaption
352
+ ) {
353
+ this.assert(this.msgId ?? this.inlineMessageId, 'editMessageCaption')
354
+ return this.telegram.editMessageCaption(
355
+ this.chat?.id,
356
+ this.msgId,
357
+ this.inlineMessageId,
358
+ caption,
359
+ extra
360
+ )
361
+ }
362
+
363
+ /**
364
+ * @see https://core.telegram.org/bots/api#editmessagemedia
365
+ */
366
+ editMessageMedia(
367
+ media: tt.WrapCaption<tg.InputMedia>,
368
+ extra?: tt.ExtraEditMessageMedia
369
+ ) {
370
+ this.assert(this.msgId ?? this.inlineMessageId, 'editMessageMedia')
371
+ return this.telegram.editMessageMedia(
372
+ this.chat?.id,
373
+ this.msgId,
374
+ this.inlineMessageId,
375
+ media,
376
+ extra
377
+ )
378
+ }
379
+
380
+ /**
381
+ * @see https://core.telegram.org/bots/api#editmessagereplymarkup
382
+ */
383
+ editMessageReplyMarkup(markup: tg.InlineKeyboardMarkup | undefined) {
384
+ this.assert(this.msgId ?? this.inlineMessageId, 'editMessageReplyMarkup')
385
+ return this.telegram.editMessageReplyMarkup(
386
+ this.chat?.id,
387
+ this.msgId,
388
+ this.inlineMessageId,
389
+ markup
390
+ )
391
+ }
392
+
393
+ /**
394
+ * @see https://core.telegram.org/bots/api#editmessagelivelocation
395
+ */
396
+ editMessageLiveLocation(
397
+ latitude: number,
398
+ longitude: number,
399
+ extra?: tt.ExtraEditMessageLiveLocation
400
+ ) {
401
+ this.assert(this.msgId ?? this.inlineMessageId, 'editMessageLiveLocation')
402
+ return this.telegram.editMessageLiveLocation(
403
+ this.chat?.id,
404
+ this.msgId,
405
+ this.inlineMessageId,
406
+ latitude,
407
+ longitude,
408
+ extra
409
+ )
410
+ }
411
+
412
+ /**
413
+ * @see https://core.telegram.org/bots/api#stopmessagelivelocation
414
+ */
415
+ stopMessageLiveLocation(markup?: tg.InlineKeyboardMarkup) {
416
+ this.assert(this.msgId ?? this.inlineMessageId, 'stopMessageLiveLocation')
417
+ return this.telegram.stopMessageLiveLocation(
418
+ this.chat?.id,
419
+ this.msgId,
420
+ this.inlineMessageId,
421
+ markup
422
+ )
423
+ }
424
+
425
+ /**
426
+ * @see https://core.telegram.org/bots/api#sendmessage
427
+ */
428
+ sendMessage(text: string | FmtString, extra?: tt.ExtraReplyMessage) {
429
+ this.assert(this.chat, 'sendMessage')
430
+ return this.telegram.sendMessage(this.chat.id, text, {
431
+ message_thread_id: getThreadId(this),
432
+ ...extra,
433
+ })
434
+ }
435
+
436
+ /**
437
+ * @see https://core.telegram.org/bots/api#sendmessage
438
+ */
439
+ reply(...args: Shorthand<'sendMessage'>) {
440
+ return this.sendMessage(...args)
441
+ }
442
+
443
+ /**
444
+ * @see https://core.telegram.org/bots/api#getchat
445
+ */
446
+ getChat(...args: Shorthand<'getChat'>) {
447
+ this.assert(this.chat, 'getChat')
448
+ return this.telegram.getChat(this.chat.id, ...args)
449
+ }
450
+
451
+ /**
452
+ * @see https://core.telegram.org/bots/api#exportchatinvitelink
453
+ */
454
+ exportChatInviteLink(...args: Shorthand<'exportChatInviteLink'>) {
455
+ this.assert(this.chat, 'exportChatInviteLink')
456
+ return this.telegram.exportChatInviteLink(this.chat.id, ...args)
457
+ }
458
+
459
+ /**
460
+ * @see https://core.telegram.org/bots/api#createchatinvitelink
461
+ */
462
+ createChatInviteLink(...args: Shorthand<'createChatInviteLink'>) {
463
+ this.assert(this.chat, 'createChatInviteLink')
464
+ return this.telegram.createChatInviteLink(this.chat.id, ...args)
465
+ }
466
+
467
+ /**
468
+ * @see https://core.telegram.org/bots/api#editchatinvitelink
469
+ */
470
+ editChatInviteLink(...args: Shorthand<'editChatInviteLink'>) {
471
+ this.assert(this.chat, 'editChatInviteLink')
472
+ return this.telegram.editChatInviteLink(this.chat.id, ...args)
473
+ }
474
+
475
+ /**
476
+ * @see https://core.telegram.org/bots/api#revokechatinvitelink
477
+ */
478
+ revokeChatInviteLink(...args: Shorthand<'revokeChatInviteLink'>) {
479
+ this.assert(this.chat, 'revokeChatInviteLink')
480
+ return this.telegram.revokeChatInviteLink(this.chat.id, ...args)
481
+ }
482
+
483
+ /**
484
+ * @see https://core.telegram.org/bots/api#banchatmember
485
+ */
486
+ banChatMember(...args: Shorthand<'banChatMember'>) {
487
+ this.assert(this.chat, 'banChatMember')
488
+ return this.telegram.banChatMember(this.chat.id, ...args)
489
+ }
490
+
491
+ /**
492
+ * @see https://core.telegram.org/bots/api#banchatmember
493
+ * @deprecated since API 5.3. Use {@link Context.banChatMember}
494
+ */
495
+ get kickChatMember() {
496
+ return this.banChatMember
497
+ }
498
+
499
+ /**
500
+ * @see https://core.telegram.org/bots/api#unbanchatmember
501
+ */
502
+ unbanChatMember(...args: Shorthand<'unbanChatMember'>) {
503
+ this.assert(this.chat, 'unbanChatMember')
504
+ return this.telegram.unbanChatMember(this.chat.id, ...args)
505
+ }
506
+
507
+ /**
508
+ * @see https://core.telegram.org/bots/api#restrictchatmember
509
+ */
510
+ restrictChatMember(...args: Shorthand<'restrictChatMember'>) {
511
+ this.assert(this.chat, 'restrictChatMember')
512
+ return this.telegram.restrictChatMember(this.chat.id, ...args)
513
+ }
514
+
515
+ /**
516
+ * @see https://core.telegram.org/bots/api#promotechatmember
517
+ */
518
+ promoteChatMember(...args: Shorthand<'promoteChatMember'>) {
519
+ this.assert(this.chat, 'promoteChatMember')
520
+ return this.telegram.promoteChatMember(this.chat.id, ...args)
521
+ }
522
+
523
+ /**
524
+ * @see https://core.telegram.org/bots/api#setchatadministratorcustomtitle
525
+ */
526
+ setChatAdministratorCustomTitle(
527
+ ...args: Shorthand<'setChatAdministratorCustomTitle'>
528
+ ) {
529
+ this.assert(this.chat, 'setChatAdministratorCustomTitle')
530
+ return this.telegram.setChatAdministratorCustomTitle(this.chat.id, ...args)
531
+ }
532
+
533
+ /**
534
+ * @see https://core.telegram.org/bots/api#setchatphoto
535
+ */
536
+ setChatPhoto(...args: Shorthand<'setChatPhoto'>) {
537
+ this.assert(this.chat, 'setChatPhoto')
538
+ return this.telegram.setChatPhoto(this.chat.id, ...args)
539
+ }
540
+
541
+ /**
542
+ * @see https://core.telegram.org/bots/api#deletechatphoto
543
+ */
544
+ deleteChatPhoto(...args: Shorthand<'deleteChatPhoto'>) {
545
+ this.assert(this.chat, 'deleteChatPhoto')
546
+ return this.telegram.deleteChatPhoto(this.chat.id, ...args)
547
+ }
548
+
549
+ /**
550
+ * @see https://core.telegram.org/bots/api#setchattitle
551
+ */
552
+ setChatTitle(...args: Shorthand<'setChatTitle'>) {
553
+ this.assert(this.chat, 'setChatTitle')
554
+ return this.telegram.setChatTitle(this.chat.id, ...args)
555
+ }
556
+
557
+ /**
558
+ * @see https://core.telegram.org/bots/api#setchatdescription
559
+ */
560
+ setChatDescription(...args: Shorthand<'setChatDescription'>) {
561
+ this.assert(this.chat, 'setChatDescription')
562
+ return this.telegram.setChatDescription(this.chat.id, ...args)
563
+ }
564
+
565
+ /**
566
+ * @see https://core.telegram.org/bots/api#pinchatmessage
567
+ */
568
+ pinChatMessage(...args: Shorthand<'pinChatMessage'>) {
569
+ this.assert(this.chat, 'pinChatMessage')
570
+ return this.telegram.pinChatMessage(this.chat.id, ...args)
571
+ }
572
+
573
+ /**
574
+ * @see https://core.telegram.org/bots/api#unpinchatmessage
575
+ */
576
+ unpinChatMessage(...args: Shorthand<'unpinChatMessage'>) {
577
+ this.assert(this.chat, 'unpinChatMessage')
578
+ return this.telegram.unpinChatMessage(this.chat.id, ...args)
579
+ }
580
+
581
+ /**
582
+ * @see https://core.telegram.org/bots/api#unpinallchatmessages
583
+ */
584
+ unpinAllChatMessages(...args: Shorthand<'unpinAllChatMessages'>) {
585
+ this.assert(this.chat, 'unpinAllChatMessages')
586
+ return this.telegram.unpinAllChatMessages(this.chat.id, ...args)
587
+ }
588
+
589
+ /**
590
+ * @see https://core.telegram.org/bots/api#leavechat
591
+ */
592
+ leaveChat(...args: Shorthand<'leaveChat'>) {
593
+ this.assert(this.chat, 'leaveChat')
594
+ return this.telegram.leaveChat(this.chat.id, ...args)
595
+ }
596
+
597
+ /**
598
+ * @see https://core.telegram.org/bots/api#setchatpermissions
599
+ */
600
+ setChatPermissions(...args: Shorthand<'setChatPermissions'>) {
601
+ this.assert(this.chat, 'setChatPermissions')
602
+ return this.telegram.setChatPermissions(this.chat.id, ...args)
603
+ }
604
+
605
+ /**
606
+ * @see https://core.telegram.org/bots/api#getchatadministrators
607
+ */
608
+ getChatAdministrators(...args: Shorthand<'getChatAdministrators'>) {
609
+ this.assert(this.chat, 'getChatAdministrators')
610
+ return this.telegram.getChatAdministrators(this.chat.id, ...args)
611
+ }
612
+
613
+ /**
614
+ * @see https://core.telegram.org/bots/api#getchatmember
615
+ */
616
+ getChatMember(...args: Shorthand<'getChatMember'>) {
617
+ this.assert(this.chat, 'getChatMember')
618
+ return this.telegram.getChatMember(this.chat.id, ...args)
619
+ }
620
+
621
+ /**
622
+ * @see https://core.telegram.org/bots/api#getchatmembercount
623
+ */
624
+ getChatMembersCount(...args: Shorthand<'getChatMembersCount'>) {
625
+ this.assert(this.chat, 'getChatMembersCount')
626
+ return this.telegram.getChatMembersCount(this.chat.id, ...args)
627
+ }
628
+
629
+ /**
630
+ * @see https://core.telegram.org/bots/api#setpassportdataerrors
631
+ */
632
+ setPassportDataErrors(errors: readonly tg.PassportElementError[]) {
633
+ this.assert(this.from, 'setPassportDataErrors')
634
+ return this.telegram.setPassportDataErrors(this.from.id, errors)
635
+ }
636
+
637
+ /**
638
+ * @see https://core.telegram.org/bots/api#sendphoto
639
+ */
640
+ sendPhoto(photo: string | tg.InputFile, extra?: tt.ExtraPhoto) {
641
+ this.assert(this.chat, 'sendPhoto')
642
+ return this.telegram.sendPhoto(this.chat.id, photo, {
643
+ message_thread_id: getThreadId(this),
644
+ ...extra,
645
+ })
646
+ }
647
+
648
+ /**
649
+ * @see https://core.telegram.org/bots/api#sendphoto
650
+ */
651
+ replyWithPhoto(...args: Shorthand<'sendPhoto'>) {
652
+ return this.sendPhoto(...args)
653
+ }
654
+
655
+ /**
656
+ * @see https://core.telegram.org/bots/api#sendmediagroup
657
+ */
658
+ sendMediaGroup(media: tt.MediaGroup, extra?: tt.ExtraMediaGroup) {
659
+ this.assert(this.chat, 'sendMediaGroup')
660
+ return this.telegram.sendMediaGroup(this.chat.id, media, {
661
+ message_thread_id: getThreadId(this),
662
+ ...extra,
663
+ })
664
+ }
665
+
666
+ /**
667
+ * @see https://core.telegram.org/bots/api#sendmediagroup
668
+ */
669
+ replyWithMediaGroup(...args: Shorthand<'sendMediaGroup'>) {
670
+ return this.sendMediaGroup(...args)
671
+ }
672
+
673
+ /**
674
+ * @see https://core.telegram.org/bots/api#sendaudio
675
+ */
676
+ sendAudio(audio: string | tg.InputFile, extra?: tt.ExtraAudio) {
677
+ this.assert(this.chat, 'sendAudio')
678
+ return this.telegram.sendAudio(this.chat.id, audio, {
679
+ message_thread_id: getThreadId(this),
680
+ ...extra,
681
+ })
682
+ }
683
+
684
+ /**
685
+ * @see https://core.telegram.org/bots/api#sendaudio
686
+ */
687
+ replyWithAudio(...args: Shorthand<'sendAudio'>) {
688
+ return this.sendAudio(...args)
689
+ }
690
+
691
+ /**
692
+ * @see https://core.telegram.org/bots/api#senddice
693
+ */
694
+ sendDice(extra?: tt.ExtraDice) {
695
+ this.assert(this.chat, 'sendDice')
696
+ return this.telegram.sendDice(this.chat.id, {
697
+ message_thread_id: getThreadId(this),
698
+ ...extra,
699
+ })
700
+ }
701
+
702
+ /**
703
+ * @see https://core.telegram.org/bots/api#senddice
704
+ */
705
+ replyWithDice(...args: Shorthand<'sendDice'>) {
706
+ return this.sendDice(...args)
707
+ }
708
+
709
+ /**
710
+ * @see https://core.telegram.org/bots/api#senddocument
711
+ */
712
+ sendDocument(document: string | tg.InputFile, extra?: tt.ExtraDocument) {
713
+ this.assert(this.chat, 'sendDocument')
714
+ return this.telegram.sendDocument(this.chat.id, document, {
715
+ message_thread_id: getThreadId(this),
716
+ ...extra,
717
+ })
718
+ }
719
+
720
+ /**
721
+ * @see https://core.telegram.org/bots/api#senddocument
722
+ */
723
+ replyWithDocument(...args: Shorthand<'sendDocument'>) {
724
+ return this.sendDocument(...args)
725
+ }
726
+
727
+ /**
728
+ * @see https://core.telegram.org/bots/api#sendsticker
729
+ */
730
+ sendSticker(sticker: string | tg.InputFile, extra?: tt.ExtraSticker) {
731
+ this.assert(this.chat, 'sendSticker')
732
+ return this.telegram.sendSticker(this.chat.id, sticker, {
733
+ message_thread_id: getThreadId(this),
734
+ ...extra,
735
+ })
736
+ }
737
+
738
+ /**
739
+ * @see https://core.telegram.org/bots/api#sendsticker
740
+ */
741
+ replyWithSticker(...args: Shorthand<'sendSticker'>) {
742
+ return this.sendSticker(...args)
743
+ }
744
+
745
+ /**
746
+ * @see https://core.telegram.org/bots/api#sendvideo
747
+ */
748
+ sendVideo(video: string | tg.InputFile, extra?: tt.ExtraVideo) {
749
+ this.assert(this.chat, 'sendVideo')
750
+ return this.telegram.sendVideo(this.chat.id, video, {
751
+ message_thread_id: getThreadId(this),
752
+ ...extra,
753
+ })
754
+ }
755
+
756
+ /**
757
+ * @see https://core.telegram.org/bots/api#sendvideo
758
+ */
759
+ replyWithVideo(...args: Shorthand<'sendVideo'>) {
760
+ return this.sendVideo(...args)
761
+ }
762
+
763
+ /**
764
+ * @see https://core.telegram.org/bots/api#sendanimation
765
+ */
766
+ sendAnimation(animation: string | tg.InputFile, extra?: tt.ExtraAnimation) {
767
+ this.assert(this.chat, 'sendAnimation')
768
+ return this.telegram.sendAnimation(this.chat.id, animation, {
769
+ message_thread_id: getThreadId(this),
770
+ ...extra,
771
+ })
772
+ }
773
+
774
+ /**
775
+ * @see https://core.telegram.org/bots/api#sendanimation
776
+ */
777
+ replyWithAnimation(...args: Shorthand<'sendAnimation'>) {
778
+ return this.sendAnimation(...args)
779
+ }
780
+
781
+ /**
782
+ * @see https://core.telegram.org/bots/api#sendvideonote
783
+ */
784
+ sendVideoNote(
785
+ videoNote: string | tg.InputFileVideoNote,
786
+ extra?: tt.ExtraVideoNote
787
+ ) {
788
+ this.assert(this.chat, 'sendVideoNote')
789
+ return this.telegram.sendVideoNote(this.chat.id, videoNote, {
790
+ message_thread_id: getThreadId(this),
791
+ ...extra,
792
+ })
793
+ }
794
+
795
+ /**
796
+ * @see https://core.telegram.org/bots/api#sendvideonote
797
+ */
798
+ replyWithVideoNote(...args: Shorthand<'sendVideoNote'>) {
799
+ return this.sendVideoNote(...args)
800
+ }
801
+
802
+ /**
803
+ * @see https://core.telegram.org/bots/api#sendinvoice
804
+ */
805
+ sendInvoice(invoice: tt.NewInvoiceParameters, extra?: tt.ExtraInvoice) {
806
+ this.assert(this.chat, 'sendInvoice')
807
+ return this.telegram.sendInvoice(this.chat.id, invoice, {
808
+ message_thread_id: getThreadId(this),
809
+ ...extra,
810
+ })
811
+ }
812
+
813
+ /**
814
+ * @see https://core.telegram.org/bots/api#sendinvoice
815
+ */
816
+ replyWithInvoice(...args: Shorthand<'sendInvoice'>) {
817
+ return this.sendInvoice(...args)
818
+ }
819
+
820
+ /**
821
+ * @see https://core.telegram.org/bots/api#sendgame
822
+ */
823
+ sendGame(game: string, extra?: tt.ExtraGame) {
824
+ this.assert(this.chat, 'sendGame')
825
+ return this.telegram.sendGame(this.chat.id, game, {
826
+ message_thread_id: getThreadId(this),
827
+ ...extra,
828
+ })
829
+ }
830
+
831
+ /**
832
+ * @see https://core.telegram.org/bots/api#sendgame
833
+ */
834
+ replyWithGame(...args: Shorthand<'sendGame'>) {
835
+ return this.sendGame(...args)
836
+ }
837
+
838
+ /**
839
+ * @see https://core.telegram.org/bots/api#sendvoice
840
+ */
841
+ sendVoice(voice: string | tg.InputFile, extra?: tt.ExtraVoice) {
842
+ this.assert(this.chat, 'sendVoice')
843
+ return this.telegram.sendVoice(this.chat.id, voice, {
844
+ message_thread_id: getThreadId(this),
845
+ ...extra,
846
+ })
847
+ }
848
+
849
+ /**
850
+ * @see https://core.telegram.org/bots/api#sendvoice
851
+ */
852
+ replyWithVoice(...args: Shorthand<'sendVoice'>) {
853
+ return this.sendVoice(...args)
854
+ }
855
+
856
+ /**
857
+ * @see https://core.telegram.org/bots/api#sendpoll
858
+ */
859
+ sendPoll(poll: string, options: readonly string[], extra?: tt.ExtraPoll) {
860
+ this.assert(this.chat, 'sendPoll')
861
+ return this.telegram.sendPoll(this.chat.id, poll, options, {
862
+ message_thread_id: getThreadId(this),
863
+ ...extra,
864
+ })
865
+ }
866
+
867
+ /**
868
+ * @see https://core.telegram.org/bots/api#sendpoll
869
+ */
870
+ replyWithPoll(...args: Shorthand<'sendPoll'>) {
871
+ return this.sendPoll(...args)
872
+ }
873
+
874
+ /**
875
+ * @see https://core.telegram.org/bots/api#sendpoll
876
+ */
877
+ sendQuiz(quiz: string, options: readonly string[], extra?: tt.ExtraPoll) {
878
+ this.assert(this.chat, 'sendQuiz')
879
+ return this.telegram.sendQuiz(this.chat.id, quiz, options, {
880
+ message_thread_id: getThreadId(this),
881
+ ...extra,
882
+ })
883
+ }
884
+
885
+ /**
886
+ * @see https://core.telegram.org/bots/api#sendpoll
887
+ */
888
+ replyWithQuiz(...args: Shorthand<'sendQuiz'>) {
889
+ return this.sendQuiz(...args)
890
+ }
891
+
892
+ /**
893
+ * @see https://core.telegram.org/bots/api#stoppoll
894
+ */
895
+ stopPoll(...args: Shorthand<'stopPoll'>) {
896
+ this.assert(this.chat, 'stopPoll')
897
+ return this.telegram.stopPoll(this.chat.id, ...args)
898
+ }
899
+
900
+ /**
901
+ * @see https://core.telegram.org/bots/api#sendchataction
902
+ */
903
+ sendChatAction(
904
+ action: Shorthand<'sendChatAction'>[0],
905
+ extra?: tt.ExtraSendChatAction
906
+ ) {
907
+ this.assert(this.chat, 'sendChatAction')
908
+ return this.telegram.sendChatAction(this.chat.id, action, {
909
+ message_thread_id: getThreadId(this),
910
+ ...extra,
911
+ })
912
+ }
913
+
914
+ /**
915
+ * @see https://core.telegram.org/bots/api#sendchataction
916
+ *
917
+ * Sends the sendChatAction request repeatedly, with a delay between requests,
918
+ * as long as the provided callback function is being processed.
919
+ *
920
+ * The sendChatAction errors should be ignored, because the goal is the actual long process completing and performing an action.
921
+ *
922
+ * @param action - chat action type.
923
+ * @param callback - a function to run along with the chat action.
924
+ * @param extra - extra parameters for sendChatAction.
925
+ * @param {number} [extra.intervalDuration=8000] - The duration (in milliseconds) between subsequent sendChatAction requests.
926
+ */
927
+ async persistentChatAction(
928
+ action: Shorthand<'sendChatAction'>[0],
929
+ callback: () => Promise<void>,
930
+ {
931
+ intervalDuration,
932
+ ...extra
933
+ }: tt.ExtraSendChatAction & { intervalDuration?: number } = {}
934
+ ) {
935
+ await this.sendChatAction(action, { ...extra })
936
+
937
+ const timer = setInterval(
938
+ () =>
939
+ this.sendChatAction(action, { ...extra }).catch((err) => {
940
+ debug('Ignored error while persisting sendChatAction:', err)
941
+ }),
942
+ intervalDuration ?? 4000
943
+ )
944
+
945
+ try {
946
+ await callback()
947
+ } finally {
948
+ clearInterval(timer)
949
+ }
950
+ }
951
+
952
+ /**
953
+ * @deprecated use {@link Context.sendChatAction} instead
954
+ * @see https://core.telegram.org/bots/api#sendchataction
955
+ */
956
+ replyWithChatAction(...args: Shorthand<'sendChatAction'>) {
957
+ return this.sendChatAction(...args)
958
+ }
959
+
960
+ /**
961
+ * Shorthand for {@link Telegram.setMessageReaction}
962
+ * @param reaction An emoji or custom_emoji_id to set as reaction to current message. Leave empty to remove reactions.
963
+ * @param is_big Pass True to set the reaction with a big animation
964
+ */
965
+ react(
966
+ reaction?: MaybeArray<
967
+ tg.TelegramEmoji | `${Digit}${string}` | tg.ReactionType
968
+ >,
969
+ is_big?: boolean
970
+ ) {
971
+ this.assert(this.chat, 'setMessageReaction')
972
+ this.assert(this.msgId, 'setMessageReaction')
973
+ const emojis = reaction
974
+ ? Array.isArray(reaction)
975
+ ? reaction
976
+ : [reaction]
977
+ : undefined
978
+ const reactions = emojis?.map(
979
+ (emoji): tg.ReactionType =>
980
+ typeof emoji === 'string'
981
+ ? Digit.has(emoji[0] as string)
982
+ ? { type: 'custom_emoji', custom_emoji_id: emoji }
983
+ : { type: 'emoji', emoji: emoji as tg.TelegramEmoji }
984
+ : emoji
985
+ )
986
+ return this.telegram.setMessageReaction(
987
+ this.chat.id,
988
+ this.msgId,
989
+ reactions,
990
+ is_big
991
+ )
992
+ }
993
+
994
+ /**
995
+ * @see https://core.telegram.org/bots/api#sendlocation
996
+ */
997
+ sendLocation(latitude: number, longitude: number, extra?: tt.ExtraLocation) {
998
+ this.assert(this.chat, 'sendLocation')
999
+ return this.telegram.sendLocation(this.chat.id, latitude, longitude, {
1000
+ message_thread_id: getThreadId(this),
1001
+ ...extra,
1002
+ })
1003
+ }
1004
+
1005
+ /**
1006
+ * @see https://core.telegram.org/bots/api#sendlocation
1007
+ */
1008
+ replyWithLocation(...args: Shorthand<'sendLocation'>) {
1009
+ return this.sendLocation(...args)
1010
+ }
1011
+
1012
+ /**
1013
+ * @see https://core.telegram.org/bots/api#sendvenue
1014
+ */
1015
+ sendVenue(
1016
+ latitude: number,
1017
+ longitude: number,
1018
+ title: string,
1019
+ address: string,
1020
+ extra?: tt.ExtraVenue
1021
+ ) {
1022
+ this.assert(this.chat, 'sendVenue')
1023
+ return this.telegram.sendVenue(
1024
+ this.chat.id,
1025
+ latitude,
1026
+ longitude,
1027
+ title,
1028
+ address,
1029
+ { message_thread_id: getThreadId(this), ...extra }
1030
+ )
1031
+ }
1032
+
1033
+ /**
1034
+ * @see https://core.telegram.org/bots/api#sendvenue
1035
+ */
1036
+ replyWithVenue(...args: Shorthand<'sendVenue'>) {
1037
+ return this.sendVenue(...args)
1038
+ }
1039
+
1040
+ /**
1041
+ * @see https://core.telegram.org/bots/api#sendcontact
1042
+ */
1043
+ sendContact(phoneNumber: string, firstName: string, extra?: tt.ExtraContact) {
1044
+ this.assert(this.chat, 'sendContact')
1045
+ return this.telegram.sendContact(this.chat.id, phoneNumber, firstName, {
1046
+ message_thread_id: getThreadId(this),
1047
+ ...extra,
1048
+ })
1049
+ }
1050
+
1051
+ /**
1052
+ * @see https://core.telegram.org/bots/api#sendcontact
1053
+ */
1054
+ replyWithContact(...args: Shorthand<'sendContact'>) {
1055
+ return this.sendContact(...args)
1056
+ }
1057
+
1058
+ /**
1059
+ * @deprecated use {@link Telegram.getStickerSet}
1060
+ * @see https://core.telegram.org/bots/api#getstickerset
1061
+ */
1062
+ getStickerSet(setName: string) {
1063
+ return this.telegram.getStickerSet(setName)
1064
+ }
1065
+
1066
+ /**
1067
+ * @see https://core.telegram.org/bots/api#setchatstickerset
1068
+ */
1069
+ setChatStickerSet(setName: string) {
1070
+ this.assert(this.chat, 'setChatStickerSet')
1071
+ return this.telegram.setChatStickerSet(this.chat.id, setName)
1072
+ }
1073
+
1074
+ /**
1075
+ * @see https://core.telegram.org/bots/api#deletechatstickerset
1076
+ */
1077
+ deleteChatStickerSet() {
1078
+ this.assert(this.chat, 'deleteChatStickerSet')
1079
+ return this.telegram.deleteChatStickerSet(this.chat.id)
1080
+ }
1081
+
1082
+ /**
1083
+ * Use this method to create a topic in a forum supergroup chat. The bot must be an administrator in the chat for this
1084
+ * to work and must have the can_manage_topics administrator rights. Returns information about the created topic as a
1085
+ * ForumTopic object.
1086
+ *
1087
+ * @see https://core.telegram.org/bots/api#createforumtopic
1088
+ */
1089
+ createForumTopic(...args: Shorthand<'createForumTopic'>) {
1090
+ this.assert(this.chat, 'createForumTopic')
1091
+ return this.telegram.createForumTopic(this.chat.id, ...args)
1092
+ }
1093
+
1094
+ /**
1095
+ * Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must be an administrator in
1096
+ * the chat for this to work and must have can_manage_topics administrator rights, unless it is the creator of the
1097
+ * topic. Returns True on success.
1098
+ *
1099
+ * @see https://core.telegram.org/bots/api#editforumtopic
1100
+ */
1101
+ editForumTopic(extra: tt.ExtraEditForumTopic) {
1102
+ this.assert(this.chat, 'editForumTopic')
1103
+ this.assert(this.message?.message_thread_id, 'editForumTopic')
1104
+ return this.telegram.editForumTopic(
1105
+ this.chat.id,
1106
+ this.message.message_thread_id,
1107
+ extra
1108
+ )
1109
+ }
1110
+
1111
+ /**
1112
+ * Use this method to close an open topic in a forum supergroup chat. The bot must be an administrator in the chat
1113
+ * for this to work and must have the can_manage_topics administrator rights, unless it is the creator of the topic.
1114
+ * Returns True on success.
1115
+ *
1116
+ * @see https://core.telegram.org/bots/api#closeforumtopic
1117
+ */
1118
+ closeForumTopic() {
1119
+ this.assert(this.chat, 'closeForumTopic')
1120
+ this.assert(this.message?.message_thread_id, 'closeForumTopic')
1121
+
1122
+ return this.telegram.closeForumTopic(
1123
+ this.chat.id,
1124
+ this.message.message_thread_id
1125
+ )
1126
+ }
1127
+
1128
+ /**
1129
+ * Use this method to reopen a closed topic in a forum supergroup chat. The bot must be an administrator in the chat
1130
+ * for this to work and must have the can_manage_topics administrator rights, unless it is the creator of the topic.
1131
+ * Returns True on success.
1132
+ *
1133
+ * @see https://core.telegram.org/bots/api#reopenforumtopic
1134
+ */
1135
+ reopenForumTopic() {
1136
+ this.assert(this.chat, 'reopenForumTopic')
1137
+ this.assert(this.message?.message_thread_id, 'reopenForumTopic')
1138
+
1139
+ return this.telegram.reopenForumTopic(
1140
+ this.chat.id,
1141
+ this.message.message_thread_id
1142
+ )
1143
+ }
1144
+
1145
+ /**
1146
+ * Use this method to delete a forum topic along with all its messages in a forum supergroup chat. The bot must be an
1147
+ * administrator in the chat for this to work and must have the can_delete_messages administrator rights.
1148
+ * Returns True on success.
1149
+ *
1150
+ * @see https://core.telegram.org/bots/api#deleteforumtopic
1151
+ */
1152
+ deleteForumTopic() {
1153
+ this.assert(this.chat, 'deleteForumTopic')
1154
+ this.assert(this.message?.message_thread_id, 'deleteForumTopic')
1155
+
1156
+ return this.telegram.deleteForumTopic(
1157
+ this.chat.id,
1158
+ this.message.message_thread_id
1159
+ )
1160
+ }
1161
+
1162
+ /**
1163
+ * Use this method to clear the list of pinned messages in a forum topic. The bot must be an administrator in the chat
1164
+ * for this to work and must have the can_pin_messages administrator right in the supergroup. Returns True on success.
1165
+ *
1166
+ * @see https://core.telegram.org/bots/api#unpinallforumtopicmessages
1167
+ */
1168
+ unpinAllForumTopicMessages() {
1169
+ this.assert(this.chat, 'unpinAllForumTopicMessages')
1170
+ this.assert(this.message?.message_thread_id, 'unpinAllForumTopicMessages')
1171
+
1172
+ return this.telegram.unpinAllForumTopicMessages(
1173
+ this.chat.id,
1174
+ this.message.message_thread_id
1175
+ )
1176
+ }
1177
+
1178
+ /**
1179
+ * Use this method to edit the name of the 'General' topic in a forum supergroup chat. The bot must be an administrator
1180
+ * in the chat for this to work and must have can_manage_topics administrator rights. Returns True on success.
1181
+ *
1182
+ * @see https://core.telegram.org/bots/api#editgeneralforumtopic
1183
+ */
1184
+ editGeneralForumTopic(name: string) {
1185
+ this.assert(this.chat, 'editGeneralForumTopic')
1186
+ return this.telegram.editGeneralForumTopic(this.chat.id, name)
1187
+ }
1188
+
1189
+ /**
1190
+ * Use this method to close an open 'General' topic in a forum supergroup chat. The bot must be an administrator in the
1191
+ * chat for this to work and must have the can_manage_topics administrator rights. Returns True on success.
1192
+ *
1193
+ * @see https://core.telegram.org/bots/api#closegeneralforumtopic
1194
+ */
1195
+ closeGeneralForumTopic() {
1196
+ this.assert(this.chat, 'closeGeneralForumTopic')
1197
+ return this.telegram.closeGeneralForumTopic(this.chat.id)
1198
+ }
1199
+
1200
+ /**
1201
+ * Use this method to reopen a closed 'General' topic in a forum supergroup chat. The bot must be an administrator in
1202
+ * the chat for this to work and must have the can_manage_topics administrator rights. The topic will be automatically
1203
+ * unhidden if it was hidden. Returns True on success.
1204
+ *
1205
+ * @see https://core.telegram.org/bots/api#reopengeneralforumtopic
1206
+ */
1207
+ reopenGeneralForumTopic() {
1208
+ this.assert(this.chat, 'reopenGeneralForumTopic')
1209
+ return this.telegram.reopenGeneralForumTopic(this.chat.id)
1210
+ }
1211
+
1212
+ /**
1213
+ * Use this method to hide the 'General' topic in a forum supergroup chat. The bot must be an administrator in the chat
1214
+ * for this to work and must have the can_manage_topics administrator rights. The topic will be automatically closed
1215
+ * if it was open. Returns True on success.
1216
+ *
1217
+ * @see https://core.telegram.org/bots/api#hidegeneralforumtopic
1218
+ */
1219
+ hideGeneralForumTopic() {
1220
+ this.assert(this.chat, 'hideGeneralForumTopic')
1221
+ return this.telegram.hideGeneralForumTopic(this.chat.id)
1222
+ }
1223
+
1224
+ /**
1225
+ * Use this method to unhide the 'General' topic in a forum supergroup chat. The bot must be an administrator in the
1226
+ * chat for this to work and must have the can_manage_topics administrator rights. Returns True on success.
1227
+ *
1228
+ * @see https://core.telegram.org/bots/api#unhidegeneralforumtopic
1229
+ */
1230
+ unhideGeneralForumTopic() {
1231
+ this.assert(this.chat, 'unhideGeneralForumTopic')
1232
+ return this.telegram.unhideGeneralForumTopic(this.chat.id)
1233
+ }
1234
+
1235
+ /**
1236
+ * Use this method to clear the list of pinned messages in a General forum topic.
1237
+ * The bot must be an administrator in the chat for this to work and must have the can_pin_messages administrator
1238
+ * right in the supergroup.
1239
+ *
1240
+ * @param chat_id Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
1241
+ *
1242
+ * @see https://core.telegram.org/bots/api#unpinallgeneralforumtopicmessages
1243
+ */
1244
+ unpinAllGeneralForumTopicMessages() {
1245
+ this.assert(this.chat, 'unpinAllGeneralForumTopicMessages')
1246
+ return this.telegram.unpinAllGeneralForumTopicMessages(this.chat.id)
1247
+ }
1248
+
1249
+ /**
1250
+ * @deprecated use {@link Telegram.setStickerPositionInSet}
1251
+ * @see https://core.telegram.org/bots/api#setstickerpositioninset
1252
+ */
1253
+ setStickerPositionInSet(sticker: string, position: number) {
1254
+ return this.telegram.setStickerPositionInSet(sticker, position)
1255
+ }
1256
+
1257
+ /**
1258
+ * @deprecated use {@link Telegram.setStickerSetThumbnail}
1259
+ * @see https://core.telegram.org/bots/api#setstickersetthumbnail
1260
+ */
1261
+ setStickerSetThumb(...args: Parameters<Telegram['setStickerSetThumbnail']>) {
1262
+ return this.telegram.setStickerSetThumbnail(...args)
1263
+ }
1264
+
1265
+ setStickerSetThumbnail(
1266
+ ...args: Parameters<Telegram['setStickerSetThumbnail']>
1267
+ ) {
1268
+ return this.telegram.setStickerSetThumbnail(...args)
1269
+ }
1270
+
1271
+ setStickerMaskPosition(
1272
+ ...args: Parameters<Telegram['setStickerMaskPosition']>
1273
+ ) {
1274
+ return this.telegram.setStickerMaskPosition(...args)
1275
+ }
1276
+
1277
+ setStickerKeywords(...args: Parameters<Telegram['setStickerKeywords']>) {
1278
+ return this.telegram.setStickerKeywords(...args)
1279
+ }
1280
+
1281
+ setStickerEmojiList(...args: Parameters<Telegram['setStickerEmojiList']>) {
1282
+ return this.telegram.setStickerEmojiList(...args)
1283
+ }
1284
+
1285
+ deleteStickerSet(...args: Parameters<Telegram['deleteStickerSet']>) {
1286
+ return this.telegram.deleteStickerSet(...args)
1287
+ }
1288
+
1289
+ setStickerSetTitle(...args: Parameters<Telegram['setStickerSetTitle']>) {
1290
+ return this.telegram.setStickerSetTitle(...args)
1291
+ }
1292
+
1293
+ setCustomEmojiStickerSetThumbnail(
1294
+ ...args: Parameters<Telegram['setCustomEmojiStickerSetThumbnail']>
1295
+ ) {
1296
+ return this.telegram.setCustomEmojiStickerSetThumbnail(...args)
1297
+ }
1298
+
1299
+ /**
1300
+ * @deprecated use {@link Telegram.deleteStickerFromSet}
1301
+ * @see https://core.telegram.org/bots/api#deletestickerfromset
1302
+ */
1303
+ deleteStickerFromSet(sticker: string) {
1304
+ return this.telegram.deleteStickerFromSet(sticker)
1305
+ }
1306
+
1307
+ /**
1308
+ * @see https://core.telegram.org/bots/api#uploadstickerfile
1309
+ */
1310
+ uploadStickerFile(...args: Shorthand<'uploadStickerFile'>) {
1311
+ this.assert(this.from, 'uploadStickerFile')
1312
+ return this.telegram.uploadStickerFile(this.from.id, ...args)
1313
+ }
1314
+
1315
+ /**
1316
+ * @see https://core.telegram.org/bots/api#createnewstickerset
1317
+ */
1318
+ createNewStickerSet(...args: Shorthand<'createNewStickerSet'>) {
1319
+ this.assert(this.from, 'createNewStickerSet')
1320
+ return this.telegram.createNewStickerSet(this.from.id, ...args)
1321
+ }
1322
+
1323
+ /**
1324
+ * @see https://core.telegram.org/bots/api#addstickertoset
1325
+ */
1326
+ addStickerToSet(...args: Shorthand<'addStickerToSet'>) {
1327
+ this.assert(this.from, 'addStickerToSet')
1328
+ return this.telegram.addStickerToSet(this.from.id, ...args)
1329
+ }
1330
+
1331
+ /**
1332
+ * @deprecated use {@link Telegram.getMyCommands}
1333
+ * @see https://core.telegram.org/bots/api#getmycommands
1334
+ */
1335
+ getMyCommands() {
1336
+ return this.telegram.getMyCommands()
1337
+ }
1338
+
1339
+ /**
1340
+ * @deprecated use {@link Telegram.setMyCommands}
1341
+ * @see https://core.telegram.org/bots/api#setmycommands
1342
+ */
1343
+ setMyCommands(commands: readonly tg.BotCommand[]) {
1344
+ return this.telegram.setMyCommands(commands)
1345
+ }
1346
+
1347
+ /**
1348
+ * @deprecated use {@link Context.replyWithMarkdownV2}
1349
+ * @see https://core.telegram.org/bots/api#sendmessage
1350
+ */
1351
+ replyWithMarkdown(markdown: string, extra?: tt.ExtraReplyMessage) {
1352
+ return this.reply(markdown, { parse_mode: 'Markdown', ...extra })
1353
+ }
1354
+
1355
+ /**
1356
+ * @see https://core.telegram.org/bots/api#sendmessage
1357
+ */
1358
+ replyWithMarkdownV2(markdown: string, extra?: tt.ExtraReplyMessage) {
1359
+ return this.reply(markdown, { parse_mode: 'MarkdownV2', ...extra })
1360
+ }
1361
+
1362
+ /**
1363
+ * @see https://core.telegram.org/bots/api#sendmessage
1364
+ */
1365
+ replyWithHTML(html: string, extra?: tt.ExtraReplyMessage) {
1366
+ return this.reply(html, { parse_mode: 'HTML', ...extra })
1367
+ }
1368
+
1369
+ // -------------------------------------------------------------------------
1370
+ // Bot API 10.1 — Rich Messages
1371
+ // -------------------------------------------------------------------------
1372
+
1373
+ /**
1374
+ * Context-aware shorthand for {@link Telegram.sendRichMessage}.
1375
+ * Sends a structured rich message to the current chat.
1376
+ * @see https://core.telegram.org/bots/api#sendrichmessage
1377
+ */
1378
+ sendRichMessage(
1379
+ richMessage: tg.InputRichMessage,
1380
+ extra?: tt.ExtraSendRichMessage
1381
+ ) {
1382
+ this.assert(this.chat, 'sendRichMessage')
1383
+ return this.telegram.sendRichMessage(this.chat.id, richMessage, extra)
1384
+ }
1385
+
1386
+ /**
1387
+ * Context-aware shorthand for {@link Telegram.sendRichMessageDraft}.
1388
+ * Streams a partial rich message to the current chat (for AI-generated replies).
1389
+ * @see https://core.telegram.org/bots/api#sendrichmessagedraft
1390
+ */
1391
+ sendRichMessageDraft(
1392
+ richMessage: tg.InputRichMessage,
1393
+ extra?: tt.ExtraSendRichMessageDraft
1394
+ ) {
1395
+ this.assert(this.chat, 'sendRichMessageDraft')
1396
+ return this.telegram.sendRichMessageDraft(this.chat.id, richMessage, extra)
1397
+ }
1398
+
1399
+ /**
1400
+ * Reply to the current message with a rich message.
1401
+ * Convenience wrapper around {@link Context.sendRichMessage} that sets reply_parameters automatically.
1402
+ */
1403
+ replyWithRichMessageContent(
1404
+ richMessage: tg.InputRichMessage,
1405
+ extra?: tt.ExtraSendRichMessage
1406
+ ) {
1407
+ this.assert(this.chat, 'replyWithRichMessageContent')
1408
+ this.assert(this.msgId, 'replyWithRichMessageContent')
1409
+ return this.telegram.sendRichMessage(this.chat.id, richMessage, {
1410
+ reply_parameters: { message_id: this.msgId },
1411
+ ...extra,
1412
+ })
1413
+ }
1414
+
1415
+ /**
1416
+ * Send a rich message with combined text, inline keyboard, parse mode, and link preview options.
1417
+ *
1418
+ * @example
1419
+ * ctx.replyWithRichMessage({
1420
+ * text: '<b>Hello!</b> Choose an option:',
1421
+ * parseMode: 'HTML',
1422
+ * buttons: [
1423
+ * [{ text: 'Visit Website', url: 'https://example.com' }],
1424
+ * [{ text: 'Callback', callback_data: 'my_action' }],
1425
+ * ],
1426
+ * disableLinkPreview: true,
1427
+ * })
1428
+ */
1429
+ replyWithRichMessage(options: {
1430
+ text: string
1431
+ parseMode?: 'HTML' | 'Markdown' | 'MarkdownV2'
1432
+ buttons?: tg.InlineKeyboardButton[][]
1433
+ disableLinkPreview?: boolean
1434
+ extra?: tt.ExtraReplyMessage
1435
+ }) {
1436
+ const { text, parseMode = 'HTML', buttons, disableLinkPreview, extra } = options
1437
+ return this.reply(text, {
1438
+ parse_mode: parseMode,
1439
+ link_preview_options: disableLinkPreview ? { is_disabled: true } : undefined,
1440
+ reply_markup: buttons?.length
1441
+ ? { inline_keyboard: buttons }
1442
+ : undefined,
1443
+ ...extra,
1444
+ })
1445
+ }
1446
+
1447
+ /**
1448
+ * @see https://core.telegram.org/bots/api#deletemessage
1449
+ */
1450
+ deleteMessage(messageId?: number) {
1451
+ this.assert(this.chat, 'deleteMessage')
1452
+ if (typeof messageId !== 'undefined')
1453
+ return this.telegram.deleteMessage(this.chat.id, messageId)
1454
+
1455
+ this.assert(this.msgId, 'deleteMessage')
1456
+ return this.telegram.deleteMessage(this.chat.id, this.msgId)
1457
+ }
1458
+
1459
+ /**
1460
+ * Context-aware shorthand for {@link Telegram.deleteMessages}
1461
+ * @param messageIds Identifiers of 1-100 messages to delete. See deleteMessage for limitations on which messages can be deleted
1462
+ */
1463
+ deleteMessages(messageIds: number[]) {
1464
+ this.assert(this.chat, 'deleteMessages')
1465
+ return this.telegram.deleteMessages(this.chat.id, messageIds)
1466
+ }
1467
+
1468
+ /**
1469
+ * @see https://core.telegram.org/bots/api#forwardmessage
1470
+ */
1471
+ forwardMessage(
1472
+ chatId: string | number,
1473
+ extra?: Shorthand<'forwardMessage'>[2]
1474
+ ) {
1475
+ this.assert(this.chat, 'forwardMessage')
1476
+ this.assert(this.msgId, 'forwardMessage')
1477
+ return this.telegram.forwardMessage(chatId, this.chat.id, this.msgId, extra)
1478
+ }
1479
+
1480
+ /**
1481
+ * Shorthand for {@link Telegram.forwardMessages}
1482
+ * @see https://core.telegram.org/bots/api#forwardmessages
1483
+ */
1484
+ forwardMessages(
1485
+ chatId: string | number,
1486
+ messageIds: number[],
1487
+ extra?: Shorthand<'forwardMessages'>[2]
1488
+ ) {
1489
+ this.assert(this.chat, 'forwardMessages')
1490
+ return this.telegram.forwardMessages(
1491
+ chatId,
1492
+ this.chat.id,
1493
+ messageIds,
1494
+ extra
1495
+ )
1496
+ }
1497
+
1498
+ /**
1499
+ * @see https://core.telegram.org/bots/api#copymessage
1500
+ */
1501
+ copyMessage(chatId: string | number, extra?: tt.ExtraCopyMessage) {
1502
+ this.assert(this.chat, 'copyMessage')
1503
+ this.assert(this.msgId, 'copyMessage')
1504
+ return this.telegram.copyMessage(chatId, this.chat.id, this.msgId, extra)
1505
+ }
1506
+
1507
+ /**
1508
+ * Context-aware shorthand for {@link Telegram.copyMessages}
1509
+ * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername)
1510
+ * @param messageIds Identifiers of 1-100 messages in the chat from_chat_id to copy. The identifiers must be specified in a strictly increasing order.
1511
+ */
1512
+ copyMessages(
1513
+ chatId: number | string,
1514
+ messageIds: number[],
1515
+ extra?: tt.ExtraCopyMessages
1516
+ ) {
1517
+ this.assert(this.chat, 'copyMessages')
1518
+ return this.telegram.copyMessages(chatId, this.chat?.id, messageIds, extra)
1519
+ }
1520
+
1521
+ /**
1522
+ * @see https://core.telegram.org/bots/api#approvechatjoinrequest
1523
+ */
1524
+ approveChatJoinRequest(userId: number) {
1525
+ this.assert(this.chat, 'approveChatJoinRequest')
1526
+ return this.telegram.approveChatJoinRequest(this.chat.id, userId)
1527
+ }
1528
+
1529
+ /**
1530
+ * @see https://core.telegram.org/bots/api#declinechatjoinrequest
1531
+ */
1532
+ declineChatJoinRequest(userId: number) {
1533
+ this.assert(this.chat, 'declineChatJoinRequest')
1534
+ return this.telegram.declineChatJoinRequest(this.chat.id, userId)
1535
+ }
1536
+
1537
+ /**
1538
+ * @see https://core.telegram.org/bots/api#banchatsenderchat
1539
+ */
1540
+ banChatSenderChat(senderChatId: number) {
1541
+ this.assert(this.chat, 'banChatSenderChat')
1542
+ return this.telegram.banChatSenderChat(this.chat.id, senderChatId)
1543
+ }
1544
+
1545
+ /**
1546
+ * @see https://core.telegram.org/bots/api#unbanchatsenderchat
1547
+ */
1548
+ unbanChatSenderChat(senderChatId: number) {
1549
+ this.assert(this.chat, 'unbanChatSenderChat')
1550
+ return this.telegram.unbanChatSenderChat(this.chat.id, senderChatId)
1551
+ }
1552
+
1553
+ /**
1554
+ * Use this method to change the bot's menu button in the current private chat. Returns true on success.
1555
+ * @see https://core.telegram.org/bots/api#setchatmenubutton
1556
+ */
1557
+ setChatMenuButton(menuButton?: tg.MenuButton) {
1558
+ this.assert(this.chat, 'setChatMenuButton')
1559
+ return this.telegram.setChatMenuButton({ chatId: this.chat.id, menuButton })
1560
+ }
1561
+
1562
+ /**
1563
+ * Use this method to get the current value of the bot's menu button in the current private chat. Returns MenuButton on success.
1564
+ * @see https://core.telegram.org/bots/api#getchatmenubutton
1565
+ */
1566
+ getChatMenuButton() {
1567
+ this.assert(this.chat, 'getChatMenuButton')
1568
+ return this.telegram.getChatMenuButton({ chatId: this.chat.id })
1569
+ }
1570
+
1571
+ /**
1572
+ * @see https://core.telegram.org/bots/api#setmydefaultadministratorrights
1573
+ */
1574
+ setMyDefaultAdministratorRights(
1575
+ extra?: Parameters<Telegram['setMyDefaultAdministratorRights']>[0]
1576
+ ) {
1577
+ return this.telegram.setMyDefaultAdministratorRights(extra)
1578
+ }
1579
+
1580
+ /**
1581
+ * @see https://core.telegram.org/bots/api#getmydefaultadministratorrights
1582
+ */
1583
+ getMyDefaultAdministratorRights(
1584
+ extra?: Parameters<Telegram['getMyDefaultAdministratorRights']>[0]
1585
+ ) {
1586
+ return this.telegram.getMyDefaultAdministratorRights(extra)
1587
+ }
1588
+ }
1589
+
1590
+ export default Context
1591
+
1592
+ type UpdateTypes<U extends Deunionize<tg.Update>> = Extract<
1593
+ UnionKeys<U>,
1594
+ tt.UpdateType
1595
+ >
1596
+
1597
+ export type GetUpdateContent<U extends tg.Update> =
1598
+ U extends tg.Update.CallbackQueryUpdate
1599
+ ? U['callback_query']['message']
1600
+ : U[UpdateTypes<U>]
1601
+
1602
+ type Getter<U extends Deunionize<tg.Update>, P extends string> = PropOr<
1603
+ GetUpdateContent<U>,
1604
+ P
1605
+ >
1606
+
1607
+ interface Msg {
1608
+ isAccessible(): this is MaybeMessage<tg.Message>
1609
+ has<Ks extends UnionKeys<tg.Message>[]>(
1610
+ ...keys: Ks
1611
+ ): this is MaybeMessage<Keyed<tg.Message, Ks[number]>>
1612
+ }
1613
+
1614
+ const Msg: Msg = {
1615
+ isAccessible() {
1616
+ return 'date' in this && this.date !== 0
1617
+ },
1618
+ has(...keys) {
1619
+ return keys.some(
1620
+ (key) =>
1621
+ // @ts-expect-error TS doesn't understand key
1622
+ this[key] != undefined
1623
+ )
1624
+ },
1625
+ }
1626
+
1627
+ export type MaybeMessage<
1628
+ M extends tg.MaybeInaccessibleMessage = tg.MaybeInaccessibleMessage,
1629
+ > = M & Msg
1630
+
1631
+ type GetMsg<U extends tg.Update> = U extends tg.Update.MessageUpdate
1632
+ ? U['message']
1633
+ : U extends tg.Update.ChannelPostUpdate
1634
+ ? U['channel_post']
1635
+ : U extends tg.Update.EditedChannelPostUpdate
1636
+ ? U['edited_channel_post']
1637
+ : U extends tg.Update.EditedMessageUpdate
1638
+ ? U['edited_message']
1639
+ : U extends tg.Update.CallbackQueryUpdate
1640
+ ? U['callback_query']['message']
1641
+ : undefined
1642
+
1643
+ function getMessageFromAnySource<U extends tg.Update>(ctx: Context<U>) {
1644
+ const msg =
1645
+ ctx.message ??
1646
+ ctx.editedMessage ??
1647
+ ctx.callbackQuery?.message ??
1648
+ ctx.channelPost ??
1649
+ ctx.editedChannelPost
1650
+ if (msg) return Object.assign(Object.create(Msg), msg)
1651
+ }
1652
+
1653
+ type GetUserFromAnySource<U extends tg.Update> =
1654
+ // check if it's a message type with `from`
1655
+ GetMsg<U> extends { from: tg.User }
1656
+ ? tg.User
1657
+ : U extends // these updates have `from`
1658
+ | tg.Update.CallbackQueryUpdate
1659
+ | tg.Update.InlineQueryUpdate
1660
+ | tg.Update.ShippingQueryUpdate
1661
+ | tg.Update.PreCheckoutQueryUpdate
1662
+ | tg.Update.ChosenInlineResultUpdate
1663
+ | tg.Update.ChatMemberUpdate
1664
+ | tg.Update.MyChatMemberUpdate
1665
+ | tg.Update.ChatJoinRequestUpdate
1666
+ // these updates have `user`
1667
+ | tg.Update.MessageReactionUpdate
1668
+ | tg.Update.PollAnswerUpdate
1669
+ | tg.Update.ChatBoostUpdate
1670
+ ? tg.User
1671
+ : undefined
1672
+
1673
+ function getUserFromAnySource<U extends tg.Update>(ctx: Context<U>) {
1674
+ if (ctx.callbackQuery) return ctx.callbackQuery.from
1675
+
1676
+ const msg = ctx.msg
1677
+ if (msg?.has('from')) return msg.from
1678
+
1679
+ return (
1680
+ (
1681
+ ctx.inlineQuery ??
1682
+ ctx.shippingQuery ??
1683
+ ctx.preCheckoutQuery ??
1684
+ ctx.chosenInlineResult ??
1685
+ ctx.chatMember ??
1686
+ ctx.myChatMember ??
1687
+ ctx.chatJoinRequest
1688
+ )?.from ??
1689
+ (ctx.messageReaction ?? ctx.pollAnswer ?? ctx.chatBoost?.boost.source)?.user
1690
+ )
1691
+ }
1692
+
1693
+ type GetMsgId<U extends tg.Update> = GetMsg<U> extends { message_id: number }
1694
+ ? number
1695
+ : U extends tg.Update.MessageReactionUpdate
1696
+ ? number
1697
+ : U extends tg.Update.MessageReactionCountUpdate
1698
+ ? number
1699
+ : undefined
1700
+
1701
+ function getMsgIdFromAnySource<U extends tg.Update>(ctx: Context<U>) {
1702
+ const msg = getMessageFromAnySource(ctx)
1703
+ return (msg ?? ctx.messageReaction ?? ctx.messageReactionCount)
1704
+ ?.message_id as GetMsgId<U>
1705
+ }
1706
+
1707
+ type GetText<U extends tg.Update> = GetMsg<U> extends tg.Message.TextMessage
1708
+ ? string
1709
+ : GetMsg<U> extends tg.Message
1710
+ ? string | undefined
1711
+ : U extends tg.Update.PollUpdate
1712
+ ? string | undefined
1713
+ : undefined
1714
+
1715
+ function getTextAndEntitiesFromAnySource<U extends tg.Update>(ctx: Context<U>) {
1716
+ const msg = ctx.msg
1717
+
1718
+ let text, entities
1719
+
1720
+ if (msg) {
1721
+ if ('text' in msg) (text = msg.text), (entities = msg.entities)
1722
+ else if ('caption' in msg)
1723
+ (text = msg.caption), (entities = msg.caption_entities)
1724
+ else if ('game' in msg)
1725
+ (text = msg.game.text), (entities = msg.game.text_entities)
1726
+ } else if (ctx.poll)
1727
+ (text = ctx.poll.explanation), (entities = ctx.poll.explanation_entities)
1728
+
1729
+ return [text, entities] as const
1730
+ }
1731
+
1732
+ const getThreadId = <U extends tg.Update>(ctx: Context<U>) => {
1733
+ const msg = ctx.msg
1734
+ return msg?.isAccessible()
1735
+ ? msg.is_topic_message
1736
+ ? msg.message_thread_id
1737
+ : undefined
1738
+ : undefined
1739
+ }