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