grammy 1.6.1 β†’ 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 KnorpelSenf
3
+ Copyright (c) 2022 KnorpelSenf
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -10,9 +10,9 @@ _<h2 align="center"> [:mag: Documentation](https://grammy.dev) | [:page_with_cur
10
10
 
11
11
  <!-- deno-fmt-ignore-start -->
12
12
 
13
- [![Bot API](https://img.shields.io/badge/Bot%20API-5.5-blue?logo=telegram&style=flat-square)](https://core.telegram.org/bots/api)
13
+ [![Bot API](https://img.shields.io/badge/Bot%20API-5.7-blue?logo=telegram&style=flat-square)](https://core.telegram.org/bots/api)
14
14
  [![npm](https://img.shields.io/npm/v/grammy?logo=npm&style=flat-square)](https://www.npmjs.org/package/grammy) <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
15
- [![All Contributors](https://img.shields.io/badge/all_contributors-48-orange.svg?style=flat-square)](#contributors-)
15
+ [![All Contributors](https://img.shields.io/badge/all_contributors-50-orange.svg?style=flat-square)](#contributors-)
16
16
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
17
17
 
18
18
  <!-- deno-fmt-ignore-end -->
@@ -176,7 +176,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
176
176
  <tr>
177
177
  <td align="center"><a href="https://github.com/taotie111"><img src="https://avatars.githubusercontent.com/u/44166322?v=4?s=100" width="100px;" alt=""/><br /><sub><b>taotie111</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=taotie111" title="Documentation">πŸ“–</a> <a href="#translation-taotie111" title="Translation">🌍</a></td>
178
178
  <td align="center"><a href="https://www.linkedin.com/in/merlin-brandes-42328717a/"><img src="https://avatars.githubusercontent.com/u/14237330?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Merlin</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=FatalMerlin" title="Documentation">πŸ“–</a></td>
179
- <td align="center"><a href="https://darve.sh"><img src="https://avatars.githubusercontent.com/u/22394081?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Darvesh</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Adarvesh" title="Bug reports">πŸ›</a> <a href="https://github.com/grammyjs/grammY/commits?author=darvesh" title="Code">πŸ’»</a></td>
179
+ <td align="center"><a href="https://darve.sh"><img src="https://avatars.githubusercontent.com/u/22394081?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Darvesh</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Adarvesh" title="Bug reports">πŸ›</a> <a href="https://github.com/grammyjs/grammY/commits?author=darvesh" title="Code">πŸ’»</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Adarvesh" title="Reviewed Pull Requests">πŸ‘€</a></td>
180
180
  <td align="center"><a href="http://telegram.me/dcdunkan"><img src="https://avatars.githubusercontent.com/u/70066170?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dcdunkan</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Adcdunkan" title="Bug reports">πŸ›</a> <a href="https://github.com/grammyjs/grammY/commits?author=dcdunkan" title="Code">πŸ’»</a> <a href="#plugin-dcdunkan" title="Plugin/utility libraries">πŸ”Œ</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Adcdunkan" title="Reviewed Pull Requests">πŸ‘€</a> <a href="https://github.com/grammyjs/grammY/commits?author=dcdunkan" title="Documentation">πŸ“–</a></td>
181
181
  <td align="center"><a href="https://xuann.wang/"><img src="https://avatars.githubusercontent.com/u/44045911?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kid</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=kidonng" title="Documentation">πŸ“–</a> <a href="#translation-kidonng" title="Translation">🌍</a></td>
182
182
  <td align="center"><a href="http://slava.fomin.io/"><img src="https://avatars.githubusercontent.com/u/1702725?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Slava Fomin II</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aslavafomin" title="Bug reports">πŸ›</a> <a href="https://github.com/grammyjs/grammY/commits?author=slavafomin" title="Documentation">πŸ“–</a></td>
@@ -189,6 +189,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
189
189
  <td align="center"><a href="http://glukki.ru"><img src="https://avatars.githubusercontent.com/u/140462?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vitaliy Meshchaninov</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aglukki" title="Bug reports">πŸ›</a> <a href="https://github.com/grammyjs/grammY/commits?author=glukki" title="Code">πŸ’»</a></td>
190
190
  <td align="center"><a href="https://github.com/dilyanpalauzov"><img src="https://avatars.githubusercontent.com/u/4992947?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Дилян ΠŸΠ°Π»Π°ΡƒΠ·ΠΎΠ²</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Adilyanpalauzov" title="Bug reports">πŸ›</a> <a href="https://github.com/grammyjs/grammY/commits?author=dilyanpalauzov" title="Code">πŸ’»</a></td>
191
191
  <td align="center"><a href="https://github.com/lmx-Hexagram"><img src="https://avatars.githubusercontent.com/u/52130356?v=4?s=100" width="100px;" alt=""/><br /><sub><b>lmx-Hexagram</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=lmx-Hexagram" title="Documentation">πŸ“–</a></td>
192
+ <td align="center"><a href="https://github.com/IlyaSemenov"><img src="https://avatars.githubusercontent.com/u/128121?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ilya Semenov</b></sub></a><br /><a href="#ideas-IlyaSemenov" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AIlyaSemenov" title="Reviewed Pull Requests">πŸ‘€</a></td>
193
+ </tr>
194
+ <tr>
195
+ <td align="center"><a href="https://github.com/abdollahzadehAli"><img src="https://avatars.githubusercontent.com/u/96317431?v=4?s=100" width="100px;" alt=""/><br /><sub><b>abdollahzadehAli</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=abdollahzadehAli" title="Documentation">πŸ“–</a> <a href="#example-abdollahzadehAli" title="Examples">πŸ’‘</a></td>
192
196
  </tr>
193
197
  </table>
194
198
 
package/out/bot.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { BotError, Composer } from "./composer.js";
2
2
  import { Context } from "./context.js";
3
3
  import { Api } from "./core/api.js";
4
- import { ApiClientOptions, WebhookReplyEnvelope } from "./core/client.js";
5
- import { Update, UserFromGetMe } from "./platform.node.js";
4
+ import { type ApiClientOptions, type WebhookReplyEnvelope } from "./core/client.js";
5
+ import { type Update, type UserFromGetMe } from "./platform.node.js";
6
6
  /**
7
7
  * Options that can be specified when running the bot via simple long polling.
8
8
  */
@@ -153,11 +153,30 @@ export declare class Bot<C extends Context = Context, A extends Api = Api> exten
153
153
  */
154
154
  set botInfo(botInfo: UserFromGetMe);
155
155
  get botInfo(): UserFromGetMe;
156
+ /**
157
+ * Checks if the bot has been initialized. A bot is initialized if the bot
158
+ * information is set. The bot information can either be set automatically
159
+ * by calling `bot.init`, or manually through the bot constructor. Note that
160
+ * usually, initialization is done automatically and you do not have to care
161
+ * about this method.
162
+ *
163
+ * @returns true if the bot is initialized, and false otherwise
164
+ */
165
+ isInited(): boolean;
156
166
  /**
157
167
  * Initializes the bot, i.e. fetches information about the bot itself. This
158
- * method is called automatically, you don't have to call it manually.
168
+ * method is called automatically, you usually don't have to call it
169
+ * manually.
159
170
  */
160
171
  init(): Promise<void>;
172
+ /**
173
+ * Internal. Do not call. Handles an update batch sequentially by supplying
174
+ * it one-by-one to the middleware. Handles middleware errors and stores the
175
+ * last update identifier that was being tried to handle.
176
+ *
177
+ * @param updates An array of updates to handle
178
+ */
179
+ private handleUpdates;
161
180
  /**
162
181
  * This is an internal method that you probably will not ever need to call.
163
182
  * It is used whenever a new update arrives from the Telegram servers that
@@ -238,4 +257,23 @@ export declare class Bot<C extends Context = Context, A extends Api = Api> exten
238
257
  * @param errorHandler A function that handles potential middleware errors
239
258
  */
240
259
  catch(errorHandler: ErrorHandler<C>): void;
260
+ /**
261
+ * Internal. Do not call. Enters a loop that will perform long polling until
262
+ * the bot is stopped.
263
+ */
264
+ private loop;
265
+ /**
266
+ * Internal. Do not call. Reliably fetches an update batch via `getUpdates`.
267
+ * Handles all known errors. Returns `undefined` if the bot is stopped and
268
+ * the call gets cancelled.
269
+ *
270
+ * @param options Polling options
271
+ * @returns An array of updates, or `undefined` if the bot is stopped.
272
+ */
273
+ private fetchUpdates;
274
+ /**
275
+ * Internal. Do not call. Handles an error that occurred during long
276
+ * polling.
277
+ */
278
+ private handlePollingError;
241
279
  }
package/out/bot.js CHANGED
@@ -50,85 +50,25 @@ class Bot extends composer_js_1.Composer {
50
50
  constructor(token, config) {
51
51
  var _a;
52
52
  super();
53
- Object.defineProperty(this, "token", {
54
- enumerable: true,
55
- configurable: true,
56
- writable: true,
57
- value: token
58
- });
59
- Object.defineProperty(this, "pollingRunning", {
60
- enumerable: true,
61
- configurable: true,
62
- writable: true,
63
- value: false
64
- });
65
- Object.defineProperty(this, "pollingAbortController", {
66
- enumerable: true,
67
- configurable: true,
68
- writable: true,
69
- value: void 0
70
- });
71
- Object.defineProperty(this, "lastTriedUpdateId", {
72
- enumerable: true,
73
- configurable: true,
74
- writable: true,
75
- value: 0
76
- });
77
- /**
78
- * Gives you full access to the Telegram Bot API.
79
- * ```ts
80
- * // This is how to call the Bot API methods:
81
- * bot.api.sendMessage(chat_id, 'Hello, grammY!')
82
- * ```
83
- *
84
- * Use this only outside of your middleware. If you have access to `ctx`,
85
- * then using `ctx.api` instead of `bot.api` is preferred.
86
- */
87
- Object.defineProperty(this, "api", {
88
- enumerable: true,
89
- configurable: true,
90
- writable: true,
91
- value: void 0
92
- });
93
- Object.defineProperty(this, "me", {
94
- enumerable: true,
95
- configurable: true,
96
- writable: true,
97
- value: void 0
98
- });
99
- Object.defineProperty(this, "clientConfig", {
100
- enumerable: true,
101
- configurable: true,
102
- writable: true,
103
- value: void 0
104
- });
105
- Object.defineProperty(this, "ContextConstructor", {
106
- enumerable: true,
107
- configurable: true,
108
- writable: true,
109
- value: void 0
110
- });
53
+ this.token = token;
54
+ this.pollingRunning = false;
55
+ this.lastTriedUpdateId = 0;
111
56
  /**
112
57
  * Holds the bot's error handler that is invoked whenever middleware throws
113
58
  * (rejects). If you set your own error handler via `bot.catch`, all that
114
59
  * happens is that this variable is assigned.
115
60
  */
116
- Object.defineProperty(this, "errorHandler", {
117
- enumerable: true,
118
- configurable: true,
119
- writable: true,
120
- value: async (err) => {
121
- var _a, _b;
122
- console.error("Error in middleware while handling update", (_b = (_a = err.ctx) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.update_id, err.error);
123
- console.error("No error handler was set!");
124
- console.error("Set your own error handler with `bot.catch = ...`");
125
- if (this.pollingRunning) {
126
- console.error("Stopping bot");
127
- await this.stop();
128
- }
129
- throw err;
61
+ this.errorHandler = async (err) => {
62
+ var _a, _b;
63
+ console.error("Error in middleware while handling update", (_b = (_a = err.ctx) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.update_id, err.error);
64
+ console.error("No error handler was set!");
65
+ console.error("Set your own error handler with `bot.catch = ...`");
66
+ if (this.pollingRunning) {
67
+ console.error("Stopping bot");
68
+ await this.stop();
130
69
  }
131
- });
70
+ throw err;
71
+ };
132
72
  if (!token)
133
73
  throw new Error("Empty token!");
134
74
  this.me = config === null || config === void 0 ? void 0 : config.botInfo;
@@ -157,12 +97,25 @@ class Bot extends composer_js_1.Composer {
157
97
  }
158
98
  return this.me;
159
99
  }
100
+ /**
101
+ * Checks if the bot has been initialized. A bot is initialized if the bot
102
+ * information is set. The bot information can either be set automatically
103
+ * by calling `bot.init`, or manually through the bot constructor. Note that
104
+ * usually, initialization is done automatically and you do not have to care
105
+ * about this method.
106
+ *
107
+ * @returns true if the bot is initialized, and false otherwise
108
+ */
109
+ isInited() {
110
+ return this.me !== undefined;
111
+ }
160
112
  /**
161
113
  * Initializes the bot, i.e. fetches information about the bot itself. This
162
- * method is called automatically, you don't have to call it manually.
114
+ * method is called automatically, you usually don't have to call it
115
+ * manually.
163
116
  */
164
117
  async init() {
165
- if (this.me === undefined) {
118
+ if (!this.isInited()) {
166
119
  debug("Initializing bot");
167
120
  const me = await this.api.getMe();
168
121
  if (this.me === undefined)
@@ -170,11 +123,34 @@ class Bot extends composer_js_1.Composer {
170
123
  else
171
124
  debug("Bot info was set manually by now, will not overwrite");
172
125
  }
173
- else {
174
- debug("Bot already initialized!");
175
- }
176
126
  debug(`I am ${this.me.username}!`);
177
127
  }
128
+ /**
129
+ * Internal. Do not call. Handles an update batch sequentially by supplying
130
+ * it one-by-one to the middleware. Handles middleware errors and stores the
131
+ * last update identifier that was being tried to handle.
132
+ *
133
+ * @param updates An array of updates to handle
134
+ */
135
+ async handleUpdates(updates) {
136
+ // handle updates sequentially (!)
137
+ for (const update of updates) {
138
+ this.lastTriedUpdateId = update.update_id;
139
+ try {
140
+ await this.handleUpdate(update);
141
+ }
142
+ catch (err) {
143
+ // should always be true
144
+ if (err instanceof composer_js_1.BotError) {
145
+ await this.errorHandler(err);
146
+ }
147
+ else {
148
+ console.error("FATAL: grammY unable to handle:", err);
149
+ throw err;
150
+ }
151
+ }
152
+ }
153
+ }
178
154
  /**
179
155
  * This is an internal method that you probably will not ever need to call.
180
156
  * It is used whenever a new update arrives from the Telegram servers that
@@ -246,9 +222,10 @@ a known bot info object.");
246
222
  * @param options Options to use for simple long polling
247
223
  */
248
224
  async start(options) {
249
- var _a, _b;
225
+ var _a;
250
226
  // Perform setup
251
- await withRetries(() => this.init());
227
+ if (!this.isInited())
228
+ await withRetries(() => this.init());
252
229
  if (this.pollingRunning) {
253
230
  debug("Simple long polling already running!");
254
231
  return;
@@ -272,76 +249,8 @@ you can circumvent this protection against memory leaks.`);
272
249
  };
273
250
  // Start polling
274
251
  debug("Starting simple long polling");
275
- this.pollingRunning = true;
276
- this.pollingAbortController = new shim_node_js_1.AbortController();
277
- const limit = options === null || options === void 0 ? void 0 : options.limit;
278
- const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 30; // seconds
279
- let allowed_updates = options === null || options === void 0 ? void 0 : options.allowed_updates;
280
- try {
281
- (_b = options === null || options === void 0 ? void 0 : options.onStart) === null || _b === void 0 ? void 0 : _b.call(options, this.botInfo);
282
- }
283
- catch (error) {
284
- this.pollingRunning = false;
285
- this.pollingAbortController = undefined;
286
- throw error;
287
- }
288
- const handleErr = async (error) => {
289
- if (!this.pollingRunning)
290
- throw error;
291
- else if (error instanceof error_js_1.GrammyError) {
292
- debugErr(error.message);
293
- if (error.error_code === 401) {
294
- debugErr("Make sure you are using the bot token you obtained from @BotFather (https://t.me/BotFather).");
295
- throw error;
296
- }
297
- else if (error.error_code === 409) {
298
- debugErr("Consider revoking the bot token if you believe that no other instance is running.");
299
- throw error;
300
- }
301
- }
302
- else
303
- debugErr(error);
304
- debugErr("Call to getUpdates failed, retrying in 3 seconds ...");
305
- await new Promise((r) => setTimeout(r, 3000));
306
- };
307
- while (this.pollingRunning) {
308
- // fetch updates
309
- const offset = this.lastTriedUpdateId + 1;
310
- let updates = undefined;
311
- do {
312
- try {
313
- updates = await this.api.getUpdates({ offset, limit, timeout, allowed_updates }, this.pollingAbortController.signal);
314
- }
315
- catch (error) {
316
- if (this.pollingRunning)
317
- await handleErr(error);
318
- else
319
- debug("Pending getUpdates request cancelled");
320
- }
321
- } while (updates === undefined && this.pollingRunning);
322
- if (updates === undefined)
323
- break;
324
- // handle them sequentially (!)
325
- for (const update of updates) {
326
- this.lastTriedUpdateId = update.update_id;
327
- try {
328
- await this.handleUpdate(update);
329
- }
330
- catch (err) {
331
- // should always be true
332
- if (err instanceof composer_js_1.BotError) {
333
- await this.errorHandler(err);
334
- }
335
- else {
336
- console.error("FATAL: grammY unable to handle:", err);
337
- throw err;
338
- }
339
- }
340
- }
341
- // Telegram uses the last setting if `allowed_updates` is omitted so
342
- // we can save same traffic by only sending it in the first request
343
- allowed_updates = undefined;
344
- }
252
+ (_a = options === null || options === void 0 ? void 0 : options.onStart) === null || _a === void 0 ? void 0 : _a.call(options, this.botInfo);
253
+ await this.loop(options);
345
254
  debug("Middleware is done running");
346
255
  }
347
256
  /**
@@ -391,8 +300,90 @@ you can circumvent this protection against memory leaks.`);
391
300
  catch(errorHandler) {
392
301
  this.errorHandler = errorHandler;
393
302
  }
303
+ /**
304
+ * Internal. Do not call. Enters a loop that will perform long polling until
305
+ * the bot is stopped.
306
+ */
307
+ async loop(options) {
308
+ var _a;
309
+ this.pollingRunning = true;
310
+ this.pollingAbortController = new shim_node_js_1.AbortController();
311
+ const limit = options === null || options === void 0 ? void 0 : options.limit;
312
+ const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 30; // seconds
313
+ let allowed_updates = options === null || options === void 0 ? void 0 : options.allowed_updates;
314
+ while (this.pollingRunning) {
315
+ // fetch updates
316
+ const updates = await this.fetchUpdates({ limit, timeout, allowed_updates });
317
+ // check if polling stopped
318
+ if (updates === undefined)
319
+ break;
320
+ // handle updates
321
+ await this.handleUpdates(updates);
322
+ // Telegram uses the last setting if `allowed_updates` is omitted so
323
+ // we can save same traffic by only sending it in the first request
324
+ allowed_updates = undefined;
325
+ }
326
+ }
327
+ /**
328
+ * Internal. Do not call. Reliably fetches an update batch via `getUpdates`.
329
+ * Handles all known errors. Returns `undefined` if the bot is stopped and
330
+ * the call gets cancelled.
331
+ *
332
+ * @param options Polling options
333
+ * @returns An array of updates, or `undefined` if the bot is stopped.
334
+ */
335
+ async fetchUpdates({ limit, timeout, allowed_updates }) {
336
+ var _a;
337
+ const offset = this.lastTriedUpdateId + 1;
338
+ let updates = undefined;
339
+ do {
340
+ try {
341
+ updates = await this.api.getUpdates({ offset, limit, timeout, allowed_updates }, (_a = this.pollingAbortController) === null || _a === void 0 ? void 0 : _a.signal);
342
+ }
343
+ catch (error) {
344
+ await this.handlePollingError(error);
345
+ }
346
+ } while (updates === undefined && this.pollingRunning);
347
+ return updates;
348
+ }
349
+ /**
350
+ * Internal. Do not call. Handles an error that occurred during long
351
+ * polling.
352
+ */
353
+ async handlePollingError(error) {
354
+ var _a;
355
+ if (!this.pollingRunning) {
356
+ debug("Pending getUpdates request cancelled");
357
+ return;
358
+ }
359
+ let sleepSeconds = 3;
360
+ if (error instanceof error_js_1.GrammyError) {
361
+ debugErr(error.message);
362
+ if (error.error_code === 401) {
363
+ debugErr("Make sure you are using the bot token you obtained from @BotFather (https://t.me/BotFather).");
364
+ throw error;
365
+ }
366
+ else if (error.error_code === 409) {
367
+ debugErr("Consider revoking the bot token if you believe that no other instance is running.");
368
+ throw error;
369
+ }
370
+ else if (error.error_code === 429) {
371
+ debugErr("Bot API server is closing.");
372
+ sleepSeconds = (_a = error.parameters.retry_after) !== null && _a !== void 0 ? _a : sleepSeconds;
373
+ }
374
+ }
375
+ else
376
+ debugErr(error);
377
+ debugErr(`Call to getUpdates failed, retrying in ${sleepSeconds} seconds ...`);
378
+ await sleep(sleepSeconds);
379
+ }
394
380
  }
395
381
  exports.Bot = Bot;
382
+ /**
383
+ * Performs a network call task, retrying upon known errors until success.
384
+ *
385
+ * @param task Async task to perform
386
+ */
396
387
  async function withRetries(task) {
397
388
  let success = false;
398
389
  while (!success) {
@@ -409,9 +400,8 @@ async function withRetries(task) {
409
400
  continue;
410
401
  if (error.error_code === 429) {
411
402
  const retryAfter = error.parameters.retry_after;
412
- if (retryAfter !== undefined) {
413
- await new Promise((resolve) => setTimeout(resolve, 1000 * retryAfter));
414
- }
403
+ if (retryAfter !== undefined)
404
+ await sleep(retryAfter);
415
405
  continue;
416
406
  }
417
407
  }
@@ -419,4 +409,10 @@ async function withRetries(task) {
419
409
  }
420
410
  }
421
411
  }
412
+ /**
413
+ * Returns a new promise that resolves after the specified number of seconds.
414
+ */
415
+ function sleep(seconds) {
416
+ return new Promise((r) => setTimeout(r, 1000 * seconds));
417
+ }
422
418
  const shim_node_js_1 = require("./shim.node.js");
package/out/composer.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Context } from "./context.js";
2
- import { Filter, FilterQuery } from "./filter.js";
1
+ import { type Context } from "./context.js";
2
+ import { type Filter, type FilterQuery } from "./filter.js";
3
3
  declare type MaybePromise<T> = T | Promise<T>;
4
4
  declare type MaybeArray<T> = T | T[];
5
5
  declare type StringWithSuggestions<S extends string> = (string & {}) | S;
package/out/composer.js CHANGED
@@ -11,18 +11,8 @@ const filter_js_1 = require("./filter.js");
11
11
  class BotError extends Error {
12
12
  constructor(error, ctx) {
13
13
  super(generateBotErrorMessage(error));
14
- Object.defineProperty(this, "error", {
15
- enumerable: true,
16
- configurable: true,
17
- writable: true,
18
- value: error
19
- });
20
- Object.defineProperty(this, "ctx", {
21
- enumerable: true,
22
- configurable: true,
23
- writable: true,
24
- value: ctx
25
- });
14
+ this.error = error;
15
+ this.ctx = ctx;
26
16
  this.name = "BotError";
27
17
  if (error instanceof Error)
28
18
  this.stack = error.stack;
@@ -109,12 +99,6 @@ class Composer {
109
99
  * @param middleware The middleware to compose
110
100
  */
111
101
  constructor(...middleware) {
112
- Object.defineProperty(this, "handler", {
113
- enumerable: true,
114
- configurable: true,
115
- writable: true,
116
- value: void 0
117
- });
118
102
  this.handler = middleware.length === 0
119
103
  ? pass
120
104
  : middleware.map(flatten).reduce(concat);
package/out/context.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Api, Other as OtherApi } from "./core/api.js";
2
- import { Methods, RawApi } from "./core/client.js";
3
- import { Chat, ChatPermissions, InlineQueryResult, InputFile, InputMedia, InputMediaAudio, InputMediaDocument, InputMediaPhoto, InputMediaVideo, LabeledPrice, Message, PassportElementError, Update, User, UserFromGetMe } from "./platform.node.js";
1
+ import { type Api, type Other as OtherApi } from "./core/api.js";
2
+ import { type Methods, type RawApi } from "./core/client.js";
3
+ import { type Chat, type ChatPermissions, type InlineQueryResult, type InputFile, type InputMedia, type InputMediaAudio, type InputMediaDocument, type InputMediaPhoto, type InputMediaVideo, type LabeledPrice, type Message, type PassportElementError, type Update, type User, type UserFromGetMe } from "./platform.node.js";
4
4
  declare type Other<M extends Methods<RawApi>, X extends string = never> = OtherApi<RawApi, M, X>;
5
5
  declare type SnakeToCamelCase<S extends string> = S extends `${infer L}_${infer R}` ? `${L}${Capitalize<SnakeToCamelCase<R>>}` : S;
6
6
  export declare type AliasProps<U> = {
@@ -10,7 +10,7 @@ declare type RenamedUpdate = AliasProps<Omit<Update, "update_id">>;
10
10
  /**
11
11
  * When your bot receives a message, Telegram sends an update object to your
12
12
  * bot. The update contains information about the chat, the user, and of course
13
- * the message itself. There a numerous other updates, too:
13
+ * the message itself. There are numerous other updates, too:
14
14
  * https://core.telegram.org/bots/api#update
15
15
  *
16
16
  * When grammY receives an update, it wraps this update into a context object
@@ -735,7 +735,7 @@ export declare class Context implements RenamedUpdate {
735
735
  */
736
736
  deleteMessage(signal?: AbortSignal): Promise<true>;
737
737
  /**
738
- * Context-aware alias for `api.sendSticker`. Use this method to send static .WEBP or animated .TGS stickers. On success, the sent Message is returned.
738
+ * Context-aware alias for `api.sendSticker`. Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned.
739
739
  *
740
740
  * @param sticker Sticker to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a .WEBP file from the Internet, or upload a new one using multipart/form-data.
741
741
  * @param other Optional remaining parameters, confer the official reference below
package/out/context.js CHANGED
@@ -4,7 +4,7 @@ exports.Context = void 0;
4
4
  /**
5
5
  * When your bot receives a message, Telegram sends an update object to your
6
6
  * bot. The update contains information about the chat, the user, and of course
7
- * the message itself. There a numerous other updates, too:
7
+ * the message itself. There are numerous other updates, too:
8
8
  * https://core.telegram.org/bots/api#update
9
9
  *
10
10
  * When grammY receives an update, it wraps this update into a context object
@@ -53,34 +53,9 @@ class Context {
53
53
  * Information about the bot itself.
54
54
  */
55
55
  me) {
56
- Object.defineProperty(this, "update", {
57
- enumerable: true,
58
- configurable: true,
59
- writable: true,
60
- value: update
61
- });
62
- Object.defineProperty(this, "api", {
63
- enumerable: true,
64
- configurable: true,
65
- writable: true,
66
- value: api
67
- });
68
- Object.defineProperty(this, "me", {
69
- enumerable: true,
70
- configurable: true,
71
- writable: true,
72
- value: me
73
- });
74
- /**
75
- * Used by some middleware to store information about how a certain string
76
- * or regular expression was matched.
77
- */
78
- Object.defineProperty(this, "match", {
79
- enumerable: true,
80
- configurable: true,
81
- writable: true,
82
- value: void 0
83
- });
56
+ this.update = update;
57
+ this.api = api;
58
+ this.me = me;
84
59
  }
85
60
  // UPDATE SHORTCUTS
86
61
  /** Alias for `ctx.update.message` */
@@ -940,7 +915,7 @@ class Context {
940
915
  return this.api.deleteMessage(orThrow(this.chat, "deleteMessage").id, orThrow(this.msg, "deleteMessage").message_id, signal);
941
916
  }
942
917
  /**
943
- * Context-aware alias for `api.sendSticker`. Use this method to send static .WEBP or animated .TGS stickers. On success, the sent Message is returned.
918
+ * Context-aware alias for `api.sendSticker`. Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned.
944
919
  *
945
920
  * @param sticker Sticker to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a .WEBP file from the Internet, or upload a new one using multipart/form-data.
946
921
  * @param other Optional remaining parameters, confer the official reference below
@@ -1,14 +1,15 @@
1
- import type { IncomingMessage, ServerResponse } from "http";
1
+ /// <reference types="node" />
2
+ import { type IncomingMessage, type ServerResponse } from "http";
2
3
  export declare const adapters: {
3
4
  http: (req: IncomingMessage, res: ServerResponse) => {
4
5
  update: Promise<any>;
5
- end: () => void;
6
- respond: (json: string) => void;
6
+ end: () => ServerResponse;
7
+ respond: (json: string) => ServerResponse;
7
8
  };
8
9
  https: (req: IncomingMessage, res: ServerResponse) => {
9
10
  update: Promise<any>;
10
- end: () => void;
11
- respond: (json: string) => void;
11
+ end: () => ServerResponse;
12
+ respond: (json: string) => ServerResponse;
12
13
  };
13
14
  express: (req: any, res: any) => {
14
15
  update: Promise<any>;
@@ -1,4 +1,4 @@
1
- import { InlineKeyboardButton, KeyboardButton, LoginUrl } from "../platform.node.js";
1
+ import { type InlineKeyboardButton, type KeyboardButton, type LoginUrl } from "../platform.node.js";
2
2
  /**
3
3
  * Use this class to simplify building a custom keyboard (something like this:
4
4
  * https://core.telegram.org/bots#keyboards).