@tgify/tgify 0.1.0

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 (168) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +356 -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 +100 -0
  10. package/lib/cli.mjs +105 -0
  11. package/lib/composer.js +582 -0
  12. package/lib/context.js +1219 -0
  13. package/lib/core/helpers/args.js +57 -0
  14. package/lib/core/helpers/check.js +55 -0
  15. package/lib/core/helpers/compact.js +16 -0
  16. package/lib/core/helpers/deunionize.js +12 -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 +330 -0
  20. package/lib/core/network/error.js +21 -0
  21. package/lib/core/network/multipart-stream.js +71 -0
  22. package/lib/core/network/polling.js +87 -0
  23. package/lib/core/network/webhook.js +54 -0
  24. package/lib/core/types/typegram.js +27 -0
  25. package/lib/filters.js +69 -0
  26. package/lib/format.js +38 -0
  27. package/lib/future.js +149 -0
  28. package/lib/index.js +58 -0
  29. package/lib/input.js +61 -0
  30. package/lib/markup.js +121 -0
  31. package/lib/middleware.js +2 -0
  32. package/lib/reactions.js +84 -0
  33. package/lib/router.js +46 -0
  34. package/lib/scenes/base.js +39 -0
  35. package/lib/scenes/context.js +104 -0
  36. package/lib/scenes/index.js +21 -0
  37. package/lib/scenes/stage.js +49 -0
  38. package/lib/scenes/wizard/context.js +31 -0
  39. package/lib/scenes/wizard/index.js +45 -0
  40. package/lib/scenes.js +17 -0
  41. package/lib/session.js +166 -0
  42. package/lib/telegraf.js +256 -0
  43. package/lib/telegram-types.js +6 -0
  44. package/lib/telegram.js +1240 -0
  45. package/lib/types.js +2 -0
  46. package/lib/utils.js +5 -0
  47. package/markup.d.ts +1 -0
  48. package/markup.js +1 -0
  49. package/package.json +140 -0
  50. package/scenes.d.ts +1 -0
  51. package/scenes.js +1 -0
  52. package/session.d.ts +1 -0
  53. package/session.js +1 -0
  54. package/src/button.ts +182 -0
  55. package/src/composer.ts +1008 -0
  56. package/src/context.ts +1661 -0
  57. package/src/core/helpers/args.ts +63 -0
  58. package/src/core/helpers/check.ts +71 -0
  59. package/src/core/helpers/compact.ts +18 -0
  60. package/src/core/helpers/deunionize.ts +26 -0
  61. package/src/core/helpers/formatting.ts +119 -0
  62. package/src/core/helpers/util.ts +96 -0
  63. package/src/core/network/client.ts +396 -0
  64. package/src/core/network/error.ts +29 -0
  65. package/src/core/network/multipart-stream.ts +45 -0
  66. package/src/core/network/polling.ts +94 -0
  67. package/src/core/network/webhook.ts +58 -0
  68. package/src/core/types/typegram.ts +54 -0
  69. package/src/filters.ts +109 -0
  70. package/src/format.ts +110 -0
  71. package/src/future.ts +213 -0
  72. package/src/index.ts +17 -0
  73. package/src/input.ts +59 -0
  74. package/src/markup.ts +142 -0
  75. package/src/middleware.ts +24 -0
  76. package/src/reactions.ts +118 -0
  77. package/src/router.ts +55 -0
  78. package/src/scenes/base.ts +52 -0
  79. package/src/scenes/context.ts +136 -0
  80. package/src/scenes/index.ts +21 -0
  81. package/src/scenes/stage.ts +71 -0
  82. package/src/scenes/wizard/context.ts +58 -0
  83. package/src/scenes/wizard/index.ts +63 -0
  84. package/src/scenes.ts +1 -0
  85. package/src/session.ts +204 -0
  86. package/src/telegraf.ts +354 -0
  87. package/src/telegram-types.ts +219 -0
  88. package/src/telegram.ts +1635 -0
  89. package/src/types.ts +2 -0
  90. package/src/utils.ts +1 -0
  91. package/types.d.ts +1 -0
  92. package/types.js +1 -0
  93. package/typings/button.d.ts +36 -0
  94. package/typings/button.d.ts.map +1 -0
  95. package/typings/composer.d.ts +227 -0
  96. package/typings/composer.d.ts.map +1 -0
  97. package/typings/context.d.ts +655 -0
  98. package/typings/context.d.ts.map +1 -0
  99. package/typings/core/helpers/args.d.ts +11 -0
  100. package/typings/core/helpers/args.d.ts.map +1 -0
  101. package/typings/core/helpers/check.d.ts +56 -0
  102. package/typings/core/helpers/check.d.ts.map +1 -0
  103. package/typings/core/helpers/compact.d.ts +4 -0
  104. package/typings/core/helpers/compact.d.ts.map +1 -0
  105. package/typings/core/helpers/deunionize.d.ts +18 -0
  106. package/typings/core/helpers/deunionize.d.ts.map +1 -0
  107. package/typings/core/helpers/formatting.d.ts +30 -0
  108. package/typings/core/helpers/formatting.d.ts.map +1 -0
  109. package/typings/core/helpers/util.d.ts +26 -0
  110. package/typings/core/helpers/util.d.ts.map +1 -0
  111. package/typings/core/network/client.d.ts +53 -0
  112. package/typings/core/network/client.d.ts.map +1 -0
  113. package/typings/core/network/error.d.ts +16 -0
  114. package/typings/core/network/error.d.ts.map +1 -0
  115. package/typings/core/network/multipart-stream.d.ts +16 -0
  116. package/typings/core/network/multipart-stream.d.ts.map +1 -0
  117. package/typings/core/network/polling.d.ts +16 -0
  118. package/typings/core/network/polling.d.ts.map +1 -0
  119. package/typings/core/network/webhook.d.ts +6 -0
  120. package/typings/core/network/webhook.d.ts.map +1 -0
  121. package/typings/core/types/typegram.d.ts +42 -0
  122. package/typings/core/types/typegram.d.ts.map +1 -0
  123. package/typings/filters.d.ts +18 -0
  124. package/typings/filters.d.ts.map +1 -0
  125. package/typings/format.d.ts +22 -0
  126. package/typings/format.d.ts.map +1 -0
  127. package/typings/future.d.ts +12 -0
  128. package/typings/future.d.ts.map +1 -0
  129. package/typings/index.d.ts +15 -0
  130. package/typings/index.d.ts.map +1 -0
  131. package/typings/input.d.ts +50 -0
  132. package/typings/input.d.ts.map +1 -0
  133. package/typings/markup.d.ts +27 -0
  134. package/typings/markup.d.ts.map +1 -0
  135. package/typings/middleware.d.ts +8 -0
  136. package/typings/middleware.d.ts.map +1 -0
  137. package/typings/reactions.d.ts +32 -0
  138. package/typings/reactions.d.ts.map +1 -0
  139. package/typings/router.d.ts +21 -0
  140. package/typings/router.d.ts.map +1 -0
  141. package/typings/scenes/base.d.ts +22 -0
  142. package/typings/scenes/base.d.ts.map +1 -0
  143. package/typings/scenes/context.d.ts +36 -0
  144. package/typings/scenes/context.d.ts.map +1 -0
  145. package/typings/scenes/index.d.ts +11 -0
  146. package/typings/scenes/index.d.ts.map +1 -0
  147. package/typings/scenes/stage.d.ts +24 -0
  148. package/typings/scenes/stage.d.ts.map +1 -0
  149. package/typings/scenes/wizard/context.d.ts +29 -0
  150. package/typings/scenes/wizard/context.d.ts.map +1 -0
  151. package/typings/scenes/wizard/index.d.ts +16 -0
  152. package/typings/scenes/wizard/index.d.ts.map +1 -0
  153. package/typings/scenes.d.ts +2 -0
  154. package/typings/scenes.d.ts.map +1 -0
  155. package/typings/session.d.ts +55 -0
  156. package/typings/session.d.ts.map +1 -0
  157. package/typings/telegraf.d.ts +115 -0
  158. package/typings/telegraf.d.ts.map +1 -0
  159. package/typings/telegram-types.d.ts +117 -0
  160. package/typings/telegram-types.d.ts.map +1 -0
  161. package/typings/telegram.d.ts +675 -0
  162. package/typings/telegram.d.ts.map +1 -0
  163. package/typings/types.d.ts +3 -0
  164. package/typings/types.d.ts.map +1 -0
  165. package/typings/utils.d.ts +2 -0
  166. package/typings/utils.d.ts.map +1 -0
  167. package/utils.d.ts +1 -0
  168. package/utils.js +1 -0
package/src/context.ts ADDED
@@ -0,0 +1,1661 @@
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
+ * @see https://core.telegram.org/bots/api#deletemessage
1371
+ */
1372
+ deleteMessage(messageId?: number) {
1373
+ this.assert(this.chat, 'deleteMessage')
1374
+ if (typeof messageId !== 'undefined')
1375
+ return this.telegram.deleteMessage(this.chat.id, messageId)
1376
+
1377
+ this.assert(this.msgId, 'deleteMessage')
1378
+ return this.telegram.deleteMessage(this.chat.id, this.msgId)
1379
+ }
1380
+
1381
+ /**
1382
+ * Context-aware shorthand for {@link Telegram.deleteMessages}
1383
+ * @param messageIds Identifiers of 1-100 messages to delete. See deleteMessage for limitations on which messages can be deleted
1384
+ */
1385
+ deleteMessages(messageIds: number[]) {
1386
+ this.assert(this.chat, 'deleteMessages')
1387
+ return this.telegram.deleteMessages(this.chat.id, messageIds)
1388
+ }
1389
+
1390
+ /**
1391
+ * @see https://core.telegram.org/bots/api#forwardmessage
1392
+ */
1393
+ forwardMessage(
1394
+ chatId: string | number,
1395
+ extra?: Shorthand<'forwardMessage'>[2]
1396
+ ) {
1397
+ this.assert(this.chat, 'forwardMessage')
1398
+ this.assert(this.msgId, 'forwardMessage')
1399
+ return this.telegram.forwardMessage(chatId, this.chat.id, this.msgId, extra)
1400
+ }
1401
+
1402
+ /**
1403
+ * Shorthand for {@link Telegram.forwardMessages}
1404
+ * @see https://core.telegram.org/bots/api#forwardmessages
1405
+ */
1406
+ forwardMessages(
1407
+ chatId: string | number,
1408
+ messageIds: number[],
1409
+ extra?: Shorthand<'forwardMessages'>[2]
1410
+ ) {
1411
+ this.assert(this.chat, 'forwardMessages')
1412
+ return this.telegram.forwardMessages(
1413
+ chatId,
1414
+ this.chat.id,
1415
+ messageIds,
1416
+ extra
1417
+ )
1418
+ }
1419
+
1420
+ /**
1421
+ * @see https://core.telegram.org/bots/api#copymessage
1422
+ */
1423
+ copyMessage(chatId: string | number, extra?: tt.ExtraCopyMessage) {
1424
+ this.assert(this.chat, 'copyMessage')
1425
+ this.assert(this.msgId, 'copyMessage')
1426
+ return this.telegram.copyMessage(chatId, this.chat.id, this.msgId, extra)
1427
+ }
1428
+
1429
+ /**
1430
+ * Context-aware shorthand for {@link Telegram.copyMessages}
1431
+ * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername)
1432
+ * @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.
1433
+ */
1434
+ copyMessages(
1435
+ chatId: number | string,
1436
+ messageIds: number[],
1437
+ extra?: tt.ExtraCopyMessages
1438
+ ) {
1439
+ this.assert(this.chat, 'copyMessages')
1440
+ return this.telegram.copyMessages(chatId, this.chat?.id, messageIds, extra)
1441
+ }
1442
+
1443
+ /**
1444
+ * @see https://core.telegram.org/bots/api#approvechatjoinrequest
1445
+ */
1446
+ approveChatJoinRequest(userId: number) {
1447
+ this.assert(this.chat, 'approveChatJoinRequest')
1448
+ return this.telegram.approveChatJoinRequest(this.chat.id, userId)
1449
+ }
1450
+
1451
+ /**
1452
+ * @see https://core.telegram.org/bots/api#declinechatjoinrequest
1453
+ */
1454
+ declineChatJoinRequest(userId: number) {
1455
+ this.assert(this.chat, 'declineChatJoinRequest')
1456
+ return this.telegram.declineChatJoinRequest(this.chat.id, userId)
1457
+ }
1458
+
1459
+ /**
1460
+ * @see https://core.telegram.org/bots/api#banchatsenderchat
1461
+ */
1462
+ banChatSenderChat(senderChatId: number) {
1463
+ this.assert(this.chat, 'banChatSenderChat')
1464
+ return this.telegram.banChatSenderChat(this.chat.id, senderChatId)
1465
+ }
1466
+
1467
+ /**
1468
+ * @see https://core.telegram.org/bots/api#unbanchatsenderchat
1469
+ */
1470
+ unbanChatSenderChat(senderChatId: number) {
1471
+ this.assert(this.chat, 'unbanChatSenderChat')
1472
+ return this.telegram.unbanChatSenderChat(this.chat.id, senderChatId)
1473
+ }
1474
+
1475
+ /**
1476
+ * Use this method to change the bot's menu button in the current private chat. Returns true on success.
1477
+ * @see https://core.telegram.org/bots/api#setchatmenubutton
1478
+ */
1479
+ setChatMenuButton(menuButton?: tg.MenuButton) {
1480
+ this.assert(this.chat, 'setChatMenuButton')
1481
+ return this.telegram.setChatMenuButton({ chatId: this.chat.id, menuButton })
1482
+ }
1483
+
1484
+ /**
1485
+ * Use this method to get the current value of the bot's menu button in the current private chat. Returns MenuButton on success.
1486
+ * @see https://core.telegram.org/bots/api#getchatmenubutton
1487
+ */
1488
+ getChatMenuButton() {
1489
+ this.assert(this.chat, 'getChatMenuButton')
1490
+ return this.telegram.getChatMenuButton({ chatId: this.chat.id })
1491
+ }
1492
+
1493
+ /**
1494
+ * @see https://core.telegram.org/bots/api#setmydefaultadministratorrights
1495
+ */
1496
+ setMyDefaultAdministratorRights(
1497
+ extra?: Parameters<Telegram['setMyDefaultAdministratorRights']>[0]
1498
+ ) {
1499
+ return this.telegram.setMyDefaultAdministratorRights(extra)
1500
+ }
1501
+
1502
+ /**
1503
+ * @see https://core.telegram.org/bots/api#getmydefaultadministratorrights
1504
+ */
1505
+ getMyDefaultAdministratorRights(
1506
+ extra?: Parameters<Telegram['getMyDefaultAdministratorRights']>[0]
1507
+ ) {
1508
+ return this.telegram.getMyDefaultAdministratorRights(extra)
1509
+ }
1510
+ }
1511
+
1512
+ export default Context
1513
+
1514
+ type UpdateTypes<U extends Deunionize<tg.Update>> = Extract<
1515
+ UnionKeys<U>,
1516
+ tt.UpdateType
1517
+ >
1518
+
1519
+ export type GetUpdateContent<U extends tg.Update> =
1520
+ U extends tg.Update.CallbackQueryUpdate
1521
+ ? U['callback_query']['message']
1522
+ : U[UpdateTypes<U>]
1523
+
1524
+ type Getter<U extends Deunionize<tg.Update>, P extends string> = PropOr<
1525
+ GetUpdateContent<U>,
1526
+ P
1527
+ >
1528
+
1529
+ interface Msg {
1530
+ isAccessible(): this is MaybeMessage<tg.Message>
1531
+ has<Ks extends UnionKeys<tg.Message>[]>(
1532
+ ...keys: Ks
1533
+ ): this is MaybeMessage<Keyed<tg.Message, Ks[number]>>
1534
+ }
1535
+
1536
+ const Msg: Msg = {
1537
+ isAccessible(): this is MaybeMessage<tg.Message> {
1538
+ return 'date' in this && this.date !== 0
1539
+ },
1540
+ has(...keys): this is MaybeMessage<Keyed<tg.Message, any>> {
1541
+ return keys.some(
1542
+ (key) =>
1543
+ // @ts-expect-error TS doesn't understand key
1544
+ this[key] != undefined
1545
+ )
1546
+ },
1547
+ }
1548
+
1549
+ export type MaybeMessage<
1550
+ M extends tg.MaybeInaccessibleMessage = tg.MaybeInaccessibleMessage,
1551
+ > = M & Msg
1552
+
1553
+ type GetMsg<U extends tg.Update> = U extends tg.Update.MessageUpdate
1554
+ ? U['message']
1555
+ : U extends tg.Update.ChannelPostUpdate
1556
+ ? U['channel_post']
1557
+ : U extends tg.Update.EditedChannelPostUpdate
1558
+ ? U['edited_channel_post']
1559
+ : U extends tg.Update.EditedMessageUpdate
1560
+ ? U['edited_message']
1561
+ : U extends tg.Update.CallbackQueryUpdate
1562
+ ? U['callback_query']['message']
1563
+ : undefined
1564
+
1565
+ function getMessageFromAnySource<U extends tg.Update>(ctx: Context<U>) {
1566
+ const msg =
1567
+ ctx.message ??
1568
+ ctx.editedMessage ??
1569
+ ctx.callbackQuery?.message ??
1570
+ ctx.channelPost ??
1571
+ ctx.editedChannelPost
1572
+ if (msg) return Object.assign(Object.create(Msg), msg)
1573
+ }
1574
+
1575
+ type GetUserFromAnySource<U extends tg.Update> =
1576
+ // check if it's a message type with `from`
1577
+ GetMsg<U> extends { from: tg.User }
1578
+ ? tg.User
1579
+ : U extends // these updates have `from`
1580
+ | tg.Update.CallbackQueryUpdate
1581
+ | tg.Update.InlineQueryUpdate
1582
+ | tg.Update.ShippingQueryUpdate
1583
+ | tg.Update.PreCheckoutQueryUpdate
1584
+ | tg.Update.ChosenInlineResultUpdate
1585
+ | tg.Update.ChatMemberUpdate
1586
+ | tg.Update.MyChatMemberUpdate
1587
+ | tg.Update.ChatJoinRequestUpdate
1588
+ // these updates have `user`
1589
+ | tg.Update.MessageReactionUpdate
1590
+ | tg.Update.PollAnswerUpdate
1591
+ | tg.Update.ChatBoostUpdate
1592
+ ? tg.User
1593
+ : undefined
1594
+
1595
+ function getUserFromAnySource<U extends tg.Update>(ctx: Context<U>) {
1596
+ if (ctx.callbackQuery) return ctx.callbackQuery.from
1597
+
1598
+ const msg = ctx.msg
1599
+ if (msg?.has('from')) return msg.from
1600
+
1601
+ return (
1602
+ (
1603
+ ctx.inlineQuery ??
1604
+ ctx.shippingQuery ??
1605
+ ctx.preCheckoutQuery ??
1606
+ ctx.chosenInlineResult ??
1607
+ ctx.chatMember ??
1608
+ ctx.myChatMember ??
1609
+ ctx.chatJoinRequest
1610
+ )?.from ??
1611
+ (ctx.messageReaction ?? ctx.pollAnswer ?? ctx.chatBoost?.boost.source)?.user
1612
+ )
1613
+ }
1614
+
1615
+ type GetMsgId<U extends tg.Update> = GetMsg<U> extends { message_id: number }
1616
+ ? number
1617
+ : U extends tg.Update.MessageReactionUpdate
1618
+ ? number
1619
+ : U extends tg.Update.MessageReactionCountUpdate
1620
+ ? number
1621
+ : undefined
1622
+
1623
+ function getMsgIdFromAnySource<U extends tg.Update>(ctx: Context<U>) {
1624
+ const msg = getMessageFromAnySource(ctx)
1625
+ return (msg ?? ctx.messageReaction ?? ctx.messageReactionCount)
1626
+ ?.message_id as GetMsgId<U>
1627
+ }
1628
+
1629
+ type GetText<U extends tg.Update> = GetMsg<U> extends tg.Message.TextMessage
1630
+ ? string
1631
+ : GetMsg<U> extends tg.Message
1632
+ ? string | undefined
1633
+ : U extends tg.Update.PollUpdate
1634
+ ? string | undefined
1635
+ : undefined
1636
+
1637
+ function getTextAndEntitiesFromAnySource<U extends tg.Update>(ctx: Context<U>) {
1638
+ const msg = ctx.msg
1639
+
1640
+ let text, entities
1641
+
1642
+ if (msg) {
1643
+ if ('text' in msg) (text = msg.text), (entities = msg.entities)
1644
+ else if ('caption' in msg)
1645
+ (text = msg.caption), (entities = msg.caption_entities)
1646
+ else if ('game' in msg)
1647
+ (text = msg.game.text), (entities = msg.game.text_entities)
1648
+ } else if (ctx.poll)
1649
+ (text = ctx.poll.explanation), (entities = ctx.poll.explanation_entities)
1650
+
1651
+ return [text, entities] as const
1652
+ }
1653
+
1654
+ const getThreadId = <U extends tg.Update>(ctx: Context<U>) => {
1655
+ const msg = ctx.msg
1656
+ return msg?.isAccessible()
1657
+ ? msg.is_topic_message
1658
+ ? msg.message_thread_id
1659
+ : undefined
1660
+ : undefined
1661
+ }