grammy 1.6.2 → 1.7.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.
package/README.md CHANGED
@@ -10,7 +10,7 @@ _<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.6-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
15
  [![All Contributors](https://img.shields.io/badge/all_contributors-50-orange.svg?style=flat-square)](#contributors-)
16
16
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
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
  */
@@ -169,6 +169,14 @@ export declare class Bot<C extends Context = Context, A extends Api = Api> exten
169
169
  * manually.
170
170
  */
171
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;
172
180
  /**
173
181
  * This is an internal method that you probably will not ever need to call.
174
182
  * It is used whenever a new update arrives from the Telegram servers that
@@ -249,4 +257,23 @@ export declare class Bot<C extends Context = Context, A extends Api = Api> exten
249
257
  * @param errorHandler A function that handles potential middleware errors
250
258
  */
251
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;
252
279
  }
package/out/bot.js CHANGED
@@ -185,6 +185,32 @@ class Bot extends composer_js_1.Composer {
185
185
  }
186
186
  debug(`I am ${this.me.username}!`);
187
187
  }
188
+ /**
189
+ * Internal. Do not call. Handles an update batch sequentially by supplying
190
+ * it one-by-one to the middleware. Handles middleware errors and stores the
191
+ * last update identifier that was being tried to handle.
192
+ *
193
+ * @param updates An array of updates to handle
194
+ */
195
+ async handleUpdates(updates) {
196
+ // handle updates sequentially (!)
197
+ for (const update of updates) {
198
+ this.lastTriedUpdateId = update.update_id;
199
+ try {
200
+ await this.handleUpdate(update);
201
+ }
202
+ catch (err) {
203
+ // should always be true
204
+ if (err instanceof composer_js_1.BotError) {
205
+ await this.errorHandler(err);
206
+ }
207
+ else {
208
+ console.error("FATAL: grammY unable to handle:", err);
209
+ throw err;
210
+ }
211
+ }
212
+ }
213
+ }
188
214
  /**
189
215
  * This is an internal method that you probably will not ever need to call.
190
216
  * It is used whenever a new update arrives from the Telegram servers that
@@ -256,7 +282,7 @@ a known bot info object.");
256
282
  * @param options Options to use for simple long polling
257
283
  */
258
284
  async start(options) {
259
- var _a, _b;
285
+ var _a;
260
286
  // Perform setup
261
287
  if (!this.isInited())
262
288
  await withRetries(() => this.init());
@@ -283,76 +309,8 @@ you can circumvent this protection against memory leaks.`);
283
309
  };
284
310
  // Start polling
285
311
  debug("Starting simple long polling");
286
- this.pollingRunning = true;
287
- this.pollingAbortController = new shim_node_js_1.AbortController();
288
- const limit = options === null || options === void 0 ? void 0 : options.limit;
289
- const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 30; // seconds
290
- let allowed_updates = options === null || options === void 0 ? void 0 : options.allowed_updates;
291
- try {
292
- (_b = options === null || options === void 0 ? void 0 : options.onStart) === null || _b === void 0 ? void 0 : _b.call(options, this.botInfo);
293
- }
294
- catch (error) {
295
- this.pollingRunning = false;
296
- this.pollingAbortController = undefined;
297
- throw error;
298
- }
299
- const handleErr = async (error) => {
300
- if (!this.pollingRunning)
301
- throw error;
302
- else if (error instanceof error_js_1.GrammyError) {
303
- debugErr(error.message);
304
- if (error.error_code === 401) {
305
- debugErr("Make sure you are using the bot token you obtained from @BotFather (https://t.me/BotFather).");
306
- throw error;
307
- }
308
- else if (error.error_code === 409) {
309
- debugErr("Consider revoking the bot token if you believe that no other instance is running.");
310
- throw error;
311
- }
312
- }
313
- else
314
- debugErr(error);
315
- debugErr("Call to getUpdates failed, retrying in 3 seconds ...");
316
- await new Promise((r) => setTimeout(r, 3000));
317
- };
318
- while (this.pollingRunning) {
319
- // fetch updates
320
- const offset = this.lastTriedUpdateId + 1;
321
- let updates = undefined;
322
- do {
323
- try {
324
- updates = await this.api.getUpdates({ offset, limit, timeout, allowed_updates }, this.pollingAbortController.signal);
325
- }
326
- catch (error) {
327
- if (this.pollingRunning)
328
- await handleErr(error);
329
- else
330
- debug("Pending getUpdates request cancelled");
331
- }
332
- } while (updates === undefined && this.pollingRunning);
333
- if (updates === undefined)
334
- break;
335
- // handle them sequentially (!)
336
- for (const update of updates) {
337
- this.lastTriedUpdateId = update.update_id;
338
- try {
339
- await this.handleUpdate(update);
340
- }
341
- catch (err) {
342
- // should always be true
343
- if (err instanceof composer_js_1.BotError) {
344
- await this.errorHandler(err);
345
- }
346
- else {
347
- console.error("FATAL: grammY unable to handle:", err);
348
- throw err;
349
- }
350
- }
351
- }
352
- // Telegram uses the last setting if `allowed_updates` is omitted so
353
- // we can save same traffic by only sending it in the first request
354
- allowed_updates = undefined;
355
- }
312
+ (_a = options === null || options === void 0 ? void 0 : options.onStart) === null || _a === void 0 ? void 0 : _a.call(options, this.botInfo);
313
+ await this.loop(options);
356
314
  debug("Middleware is done running");
357
315
  }
358
316
  /**
@@ -402,8 +360,90 @@ you can circumvent this protection against memory leaks.`);
402
360
  catch(errorHandler) {
403
361
  this.errorHandler = errorHandler;
404
362
  }
363
+ /**
364
+ * Internal. Do not call. Enters a loop that will perform long polling until
365
+ * the bot is stopped.
366
+ */
367
+ async loop(options) {
368
+ var _a;
369
+ this.pollingRunning = true;
370
+ this.pollingAbortController = new shim_node_js_1.AbortController();
371
+ const limit = options === null || options === void 0 ? void 0 : options.limit;
372
+ const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 30; // seconds
373
+ let allowed_updates = options === null || options === void 0 ? void 0 : options.allowed_updates;
374
+ while (this.pollingRunning) {
375
+ // fetch updates
376
+ const updates = await this.fetchUpdates({ limit, timeout, allowed_updates });
377
+ // check if polling stopped
378
+ if (updates === undefined)
379
+ break;
380
+ // handle updates
381
+ await this.handleUpdates(updates);
382
+ // Telegram uses the last setting if `allowed_updates` is omitted so
383
+ // we can save same traffic by only sending it in the first request
384
+ allowed_updates = undefined;
385
+ }
386
+ }
387
+ /**
388
+ * Internal. Do not call. Reliably fetches an update batch via `getUpdates`.
389
+ * Handles all known errors. Returns `undefined` if the bot is stopped and
390
+ * the call gets cancelled.
391
+ *
392
+ * @param options Polling options
393
+ * @returns An array of updates, or `undefined` if the bot is stopped.
394
+ */
395
+ async fetchUpdates({ limit, timeout, allowed_updates }) {
396
+ var _a;
397
+ const offset = this.lastTriedUpdateId + 1;
398
+ let updates = undefined;
399
+ do {
400
+ try {
401
+ updates = await this.api.getUpdates({ offset, limit, timeout, allowed_updates }, (_a = this.pollingAbortController) === null || _a === void 0 ? void 0 : _a.signal);
402
+ }
403
+ catch (error) {
404
+ await this.handlePollingError(error);
405
+ }
406
+ } while (updates === undefined && this.pollingRunning);
407
+ return updates;
408
+ }
409
+ /**
410
+ * Internal. Do not call. Handles an error that occurred during long
411
+ * polling.
412
+ */
413
+ async handlePollingError(error) {
414
+ var _a;
415
+ if (!this.pollingRunning) {
416
+ debug("Pending getUpdates request cancelled");
417
+ return;
418
+ }
419
+ let sleepSeconds = 3;
420
+ if (error instanceof error_js_1.GrammyError) {
421
+ debugErr(error.message);
422
+ if (error.error_code === 401) {
423
+ debugErr("Make sure you are using the bot token you obtained from @BotFather (https://t.me/BotFather).");
424
+ throw error;
425
+ }
426
+ else if (error.error_code === 409) {
427
+ debugErr("Consider revoking the bot token if you believe that no other instance is running.");
428
+ throw error;
429
+ }
430
+ else if (error.error_code === 429) {
431
+ debugErr("Bot API server is closing.");
432
+ sleepSeconds = (_a = error.parameters.retry_after) !== null && _a !== void 0 ? _a : sleepSeconds;
433
+ }
434
+ }
435
+ else
436
+ debugErr(error);
437
+ debugErr(`Call to getUpdates failed, retrying in ${sleepSeconds} seconds ...`);
438
+ await sleep(sleepSeconds);
439
+ }
405
440
  }
406
441
  exports.Bot = Bot;
442
+ /**
443
+ * Performs a network call task, retrying upon known errors until success.
444
+ *
445
+ * @param task Async task to perform
446
+ */
407
447
  async function withRetries(task) {
408
448
  let success = false;
409
449
  while (!success) {
@@ -420,9 +460,8 @@ async function withRetries(task) {
420
460
  continue;
421
461
  if (error.error_code === 429) {
422
462
  const retryAfter = error.parameters.retry_after;
423
- if (retryAfter !== undefined) {
424
- await new Promise((resolve) => setTimeout(resolve, 1000 * retryAfter));
425
- }
463
+ if (retryAfter !== undefined)
464
+ await sleep(retryAfter);
426
465
  continue;
427
466
  }
428
467
  }
@@ -430,4 +469,10 @@ async function withRetries(task) {
430
469
  }
431
470
  }
432
471
  }
472
+ /**
473
+ * Returns a new promise that resolves after the specified number of seconds.
474
+ */
475
+ function sleep(seconds) {
476
+ return new Promise((r) => setTimeout(r, 1000 * seconds));
477
+ }
433
478
  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/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> = {
@@ -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
@@ -940,7 +940,7 @@ class Context {
940
940
  return this.api.deleteMessage(orThrow(this.chat, "deleteMessage").id, orThrow(this.msg, "deleteMessage").message_id, signal);
941
941
  }
942
942
  /**
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.
943
+ * 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
944
  *
945
945
  * @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
946
  * @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).
@@ -1,5 +1,5 @@
1
- import { Context } from "../context.js";
2
- import { MiddlewareFn } from "../composer.js";
1
+ import { type Context } from "../context.js";
2
+ import { type MiddlewareFn } from "../composer.js";
3
3
  declare type MaybePromise<T> = Promise<T> | T;
4
4
  /**
5
5
  * A session flavor is a context flavor that holds session data under
@@ -1,18 +1,18 @@
1
1
  /// <reference types="node" />
2
- import { Bot } from "../bot.js";
3
- import { Update } from "../platform.node.js";
4
- import { Context } from "../context.js";
2
+ import { type Bot } from "../bot.js";
3
+ import { type Update } from "../platform.node.js";
4
+ import { type Context } from "../context.js";
5
5
  declare const adapters: {
6
6
  callback: FrameworkAdapter;
7
7
  http: (req: import("http").IncomingMessage, res: import("http").ServerResponse) => {
8
8
  update: Promise<any>;
9
- end: () => void;
10
- respond: (json: string) => void;
9
+ end: () => import("http").ServerResponse;
10
+ respond: (json: string) => import("http").ServerResponse;
11
11
  };
12
12
  https: (req: import("http").IncomingMessage, res: import("http").ServerResponse) => {
13
13
  update: Promise<any>;
14
- end: () => void;
15
- respond: (json: string) => void;
14
+ end: () => import("http").ServerResponse;
15
+ respond: (json: string) => import("http").ServerResponse;
16
16
  };
17
17
  express: (req: any, res: any) => {
18
18
  update: Promise<any>;
@@ -31,6 +31,10 @@ declare const adapters: {
31
31
  };
32
32
  worktop: (req: any, res: any) => {
33
33
  update: Promise<any>;
34
+ /**
35
+ * Middleware for a web framework. Creates a request-response handler for a
36
+ * request. The handler will be used to integrate with the compatible framework.
37
+ */
34
38
  end: () => any;
35
39
  respond: (json: string) => any;
36
40
  };
package/out/core/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { BotCommand, ChatPermissions, InlineQueryResult, InputFile, InputMedia, InputMediaAudio, InputMediaDocument, InputMediaPhoto, InputMediaVideo, LabeledPrice, PassportElementError } from "../platform.node.js";
2
- import { ApiClientOptions, Methods, Payload, RawApi, Transformer, TransformerConsumer, WebhookReplyEnvelope } from "./client.js";
1
+ import { type BotCommand, type ChatPermissions, type InlineQueryResult, type InputFile, type InputMedia, type InputMediaAudio, type InputMediaDocument, type InputMediaPhoto, type InputMediaVideo, type LabeledPrice, type PassportElementError } from "../platform.node.js";
2
+ import { type ApiClientOptions, type Methods, type Payload, type RawApi, type Transformer, type TransformerConsumer, type WebhookReplyEnvelope } from "./client.js";
3
3
  declare type AlwaysOmittedInOther = "chat_id";
4
4
  /**
5
5
  * Helper type to derive remaining properties of a given API method call M,
@@ -589,7 +589,7 @@ export declare class Api<R extends RawApi = RawApi> {
589
589
  *
590
590
  * **Official reference:** https://core.telegram.org/bots/api#setchatdescription
591
591
  */
592
- setChatDescription(chat_id: number | string, description: string | undefined, signal?: AbortSignal): Promise<true>;
592
+ setChatDescription(chat_id: number | string, description?: string, signal?: AbortSignal): Promise<true>;
593
593
  /**
594
594
  * Use this method to add a message to the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns True on success.
595
595
  *
@@ -845,7 +845,7 @@ export declare class Api<R extends RawApi = RawApi> {
845
845
  */
846
846
  deleteMessage(chat_id: number | string, message_id: number, signal?: AbortSignal): Promise<true>;
847
847
  /**
848
- * Use this method to send static .WEBP or animated .TGS stickers. On success, the sent Message is returned.
848
+ * Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned.
849
849
  *
850
850
  * @param chat_id Unique identifier for the target chat or username of the target channel (in the format @channelusername)
851
851
  * @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.
@@ -875,7 +875,7 @@ export declare class Api<R extends RawApi = RawApi> {
875
875
  */
876
876
  uploadStickerFile(user_id: number, png_sticker: InputFile, signal?: AbortSignal): Promise<import("@grammyjs/types/manage").File>;
877
877
  /**
878
- * Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. You must use exactly one of the fields png_sticker or tgs_sticker. Returns True on success.
878
+ * Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker. Returns True on success.
879
879
  *
880
880
  * @param user_id User identifier of created sticker set owner
881
881
  * @param name Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., animals). Can contain only english letters, digits and underscores. Must begin with a letter, can't contain consecutive underscores and must end in “_by_<bot username>”. <bot_username> is case insensitive. 1-64 characters.
@@ -888,7 +888,7 @@ export declare class Api<R extends RawApi = RawApi> {
888
888
  */
889
889
  createNewStickerSet(user_id: number, name: string, title: string, emojis: string, other?: Other<R, "createNewStickerSet", "user_id" | "name" | "title" | "emojis">, signal?: AbortSignal): Promise<true>;
890
890
  /**
891
- * Use this method to add a new sticker to a set created by the bot. You must use exactly one of the fields png_sticker or tgs_sticker. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns True on success.
891
+ * Use this method to add a new sticker to a set created by the bot. You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns True on success.
892
892
  *
893
893
  * @param user_id User identifier of sticker set owner
894
894
  * @param name Sticker set name
@@ -919,16 +919,16 @@ export declare class Api<R extends RawApi = RawApi> {
919
919
  */
920
920
  deleteStickerFromSet(sticker: string, signal?: AbortSignal): Promise<true>;
921
921
  /**
922
- * Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success.
922
+ * Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Video thumbnails can be set only for video sticker sets only. Returns True on success.
923
923
  *
924
924
  * @param name Sticker set name
925
925
  * @param user_id User identifier of the sticker set owner
926
- * @param thumb A PNG image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a TGS animation with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/animated_stickers#technical-requirements for animated sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data.. Animated sticker set thumbnail can't be uploaded via HTTP URL.
926
+ * @param thumb A PNG image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a TGS animation with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements, or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files ». Animated sticker set thumbnails can't be uploaded via HTTP URL.
927
927
  * @param signal Optional `AbortSignal` to cancel the request
928
928
  *
929
929
  * **Official reference:** https://core.telegram.org/bots/api#setstickersetthumb
930
930
  */
931
- setStickerSetThumb(name: string, user_id: number, thumb: InputFile | string, signal?: AbortSignal): Promise<true>;
931
+ setStickerSetThumb(name: string, user_id: number, thumb?: InputFile | string, signal?: AbortSignal): Promise<true>;
932
932
  /**
933
933
  * Use this method to send answers to an inline query. On success, True is returned.
934
934
  * No more than 50 results per query are allowed.
package/out/core/api.js CHANGED
@@ -987,7 +987,7 @@ class Api {
987
987
  return this.raw.deleteMessage({ chat_id, message_id }, signal);
988
988
  }
989
989
  /**
990
- * Use this method to send static .WEBP or animated .TGS stickers. On success, the sent Message is returned.
990
+ * Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned.
991
991
  *
992
992
  * @param chat_id Unique identifier for the target chat or username of the target channel (in the format @channelusername)
993
993
  * @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.
@@ -1023,7 +1023,7 @@ class Api {
1023
1023
  return this.raw.uploadStickerFile({ user_id, png_sticker }, signal);
1024
1024
  }
1025
1025
  /**
1026
- * Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. You must use exactly one of the fields png_sticker or tgs_sticker. Returns True on success.
1026
+ * Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker. Returns True on success.
1027
1027
  *
1028
1028
  * @param user_id User identifier of created sticker set owner
1029
1029
  * @param name Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., animals). Can contain only english letters, digits and underscores. Must begin with a letter, can't contain consecutive underscores and must end in “_by_<bot username>”. <bot_username> is case insensitive. 1-64 characters.
@@ -1038,7 +1038,7 @@ class Api {
1038
1038
  return this.raw.createNewStickerSet({ user_id, name, title, emojis, ...other }, signal);
1039
1039
  }
1040
1040
  /**
1041
- * Use this method to add a new sticker to a set created by the bot. You must use exactly one of the fields png_sticker or tgs_sticker. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns True on success.
1041
+ * Use this method to add a new sticker to a set created by the bot. You must use exactly one of the fields png_sticker, tgs_sticker, or webm_sticker. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns True on success.
1042
1042
  *
1043
1043
  * @param user_id User identifier of sticker set owner
1044
1044
  * @param name Sticker set name
@@ -1075,11 +1075,11 @@ class Api {
1075
1075
  return this.raw.deleteStickerFromSet({ sticker }, signal);
1076
1076
  }
1077
1077
  /**
1078
- * Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success.
1078
+ * Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Video thumbnails can be set only for video sticker sets only. Returns True on success.
1079
1079
  *
1080
1080
  * @param name Sticker set name
1081
1081
  * @param user_id User identifier of the sticker set owner
1082
- * @param thumb A PNG image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a TGS animation with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/animated_stickers#technical-requirements for animated sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data.. Animated sticker set thumbnail can't be uploaded via HTTP URL.
1082
+ * @param thumb A PNG image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a TGS animation with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements, or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files ». Animated sticker set thumbnails can't be uploaded via HTTP URL.
1083
1083
  * @param signal Optional `AbortSignal` to cancel the request
1084
1084
  *
1085
1085
  * **Official reference:** https://core.telegram.org/bots/api#setstickersetthumb
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node-fetch" />
2
- import { ApiResponse, Opts, Telegram } from "../platform.node.js";
2
+ import { type ApiResponse, type Opts, type Telegram } from "../platform.node.js";
3
3
  export declare type Methods<R extends RawApi> = string & keyof R;
4
4
  /**
5
5
  * Represents the raw Telegram Bot API with all methods specified 1:1 as
@@ -1,4 +1,4 @@
1
- import { ApiError, ResponseParameters } from "../platform.node.js";
1
+ import { type ApiError, type ResponseParameters } from "../platform.node.js";
2
2
  /**
3
3
  * This class represents errors that are thrown by grammY because the Telegram
4
4
  * Bot API responded with an error.
package/out/filter.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { AliasProps, Context } from "./context.js";
2
- import { Update } from "./platform.node.js";
1
+ import { type AliasProps, type Context } from "./context.js";
2
+ import { type Update } from "./platform.node.js";
3
3
  declare type FilterFunction<C extends Context, D extends C> = (ctx: C) => ctx is D;
4
4
  /**
5
5
  * > This is an advanced function of grammY.
@@ -352,11 +352,11 @@ declare const UPDATE_KEYS: {
352
352
  };
353
353
  declare type KeyOf<T> = string & keyof T;
354
354
  declare type S = typeof UPDATE_KEYS;
355
- declare type L1 = KeyOf<S>;
356
- declare type L2<K extends L1 = L1> = K extends unknown ? `${K}:${KeyOf<S[K]>}` : never;
357
- declare type L3<K0 extends L1 = L1> = K0 extends unknown ? L3_<K0> : never;
358
- declare type L3_<K0 extends L1, K1 extends KeyOf<S[K0]> = KeyOf<S[K0]>> = K1 extends unknown ? `${K0}:${K1}:${KeyOf<S[K0][K1]>}` : never;
359
- declare type L123 = L1 | L2 | L3;
355
+ declare type L1S = KeyOf<S>;
356
+ declare type L2S<L1 extends L1S = L1S> = L1 extends unknown ? `${L1}:${KeyOf<S[L1]>}` : never;
357
+ declare type L3S<L1 extends L1S = L1S> = L1 extends unknown ? L3S_<L1> : never;
358
+ declare type L3S_<L1 extends L1S, L2 extends KeyOf<S[L1]> = KeyOf<S[L1]>> = L2 extends unknown ? `${L1}:${L2}:${KeyOf<S[L1][L2]>}` : never;
359
+ declare type L123 = L1S | L2S | L3S;
360
360
  declare type InjectShortcuts<Q extends L123 = L123> = Q extends `${infer R}:${infer S}:${infer T}` ? `${CollapseL1<R, L1Shortcuts>}:${CollapseL2<S, L2Shortcuts>}:${T}` : Q extends `${infer R}:${infer S}` ? `${CollapseL1<R, L1Shortcuts>}:${CollapseL2<S>}` : CollapseL1<Q>;
361
361
  declare type CollapseL1<Q extends string, L extends L1Shortcuts = Exclude<L1Shortcuts, "">> = Q | (L extends string ? Q extends typeof L1_SHORTCUTS[L][number] ? L : never : never);
362
362
  declare type CollapseL2<Q extends string, L extends L2Shortcuts = Exclude<L2Shortcuts, "">> = Q | (L extends string ? Q extends typeof L2_SHORTCUTS[L][number] ? L : never : never);
@@ -388,14 +388,17 @@ declare type NotUndefined = string | number | boolean | SomeObject;
388
388
  * Given a FilterQuery, returns an object that, when intersected with an Update,
389
389
  * marks those properties as required that are guaranteed to exist.
390
390
  */
391
- declare type RunQuery<Q extends string> = L1Combinations<Q, L1Parts<Q>>;
392
- declare type L1Combinations<Q extends string, L1 extends string> = Combine<L1Fields<Q, L1>, L1>;
393
- declare type L1Fields<Q extends string, L1 extends string> = L1 extends unknown ? Record<L1, L2Combinations<L2Parts<Q, L1>>> : never;
394
- declare type L2Combinations<L2 extends string> = [L2] extends [never] ? NotUndefined : Combine<L2Fields<L2>, L2>;
395
- declare type L2Fields<L2 extends string> = L2 extends unknown ? Record<L2 | Twins<L2>, NotUndefined> : never;
391
+ declare type RunQuery<Q extends string> = L1Discriminator<Q, L1Parts<Q>>;
392
+ declare type L1Parts<Q extends string> = Q extends `${infer L1}:${string}` ? L1 : Q;
393
+ declare type L2Parts<Q extends string, L1 extends string> = Q extends `${L1}:${infer L2}:${string}` ? L2 : Q extends `${L1}:${infer L2}` ? L2 : never;
394
+ declare type L1Discriminator<Q extends string, L1 extends string> = Combine<L1Fragment<Q, L1>, L1>;
395
+ declare type L1Fragment<Q extends string, L1 extends string> = L1 extends unknown ? Record<L1, L2Discriminator<L1, L2Parts<Q, L1>>> : never;
396
+ declare type L2Discriminator<L1 extends string, L2 extends string> = [L2] extends [
397
+ never
398
+ ] ? L2ShallowFragment<L1> : Combine<L2Fragment<L1, L2>, L2>;
399
+ declare type L2Fragment<L1 extends string, L2 extends string> = L2 extends unknown ? Record<L2 | AddTwins<L1, L2>, NotUndefined> : never;
400
+ declare type L2ShallowFragment<L1 extends string> = Record<AddTwins<L1, never>, NotUndefined>;
396
401
  declare type Combine<U, K extends string> = U extends unknown ? U & Partial<Record<Exclude<K, keyof U>, undefined>> : never;
397
- declare type L1Parts<Q extends string> = Q extends `${infer U}:${string}` ? U : Q;
398
- declare type L2Parts<Q extends string, P extends string> = Q extends `${P}:${infer U}:${string}` ? U : Q extends `${P}:${infer U}` ? U : never;
399
402
  /**
400
403
  * This type infers which properties will be present on the given context object
401
404
  * provided it matches the given filter query. If the filter query is a union
@@ -411,6 +414,7 @@ declare type FilteredContext<C extends Context, U extends Update> = C & Record<"
411
414
  interface Shortcuts<U extends Update> {
412
415
  msg: [U["callback_query"]] extends [SomeObject] ? U["callback_query"]["message"] : [U["message"]] extends [SomeObject] ? U["message"] : [U["edited_message"]] extends [SomeObject] ? U["edited_message"] : [U["channel_post"]] extends [SomeObject] ? U["channel_post"] : [U["edited_channel_post"]] extends [SomeObject] ? U["edited_channel_post"] : undefined;
413
416
  chat: [U["callback_query"]] extends [SomeObject] ? NonNullable<U["callback_query"]["message"]>["chat"] | undefined : [Shortcuts<U>["msg"]] extends [SomeObject] ? Shortcuts<U>["msg"]["chat"] : [U["my_chat_member"]] extends [SomeObject] ? U["my_chat_member"]["chat"] : [U["chat_member"]] extends [SomeObject] ? U["chat_member"]["chat"] : [U["chat_join_request"]] extends [SomeObject] ? U["chat_join_request"]["chat"] : undefined;
417
+ senderChat: [Shortcuts<U>["msg"]] extends [SomeObject] ? Shortcuts<U>["msg"]["sender_chat"] : undefined;
414
418
  from: [U["callback_query"]] extends [SomeObject] ? U["callback_query"]["from"] : [U["inline_query"]] extends [SomeObject] ? U["inline_query"]["from"] : [U["shipping_query"]] extends [SomeObject] ? U["shipping_query"]["from"] : [U["pre_checkout_query"]] extends [SomeObject] ? U["pre_checkout_query"]["from"] : [U["chosen_inline_result"]] extends [SomeObject] ? U["chosen_inline_result"]["from"] : [U["message"]] extends [SomeObject] ? NonNullable<U["message"]["from"]> : [U["edited_message"]] extends [SomeObject] ? NonNullable<U["edited_message"]["from"]> : [U["my_chat_member"]] extends [SomeObject] ? U["my_chat_member"]["from"] : [U["chat_member"]] extends [SomeObject] ? U["chat_member"]["from"] : [U["chat_join_request"]] extends [SomeObject] ? U["chat_join_request"]["from"] : undefined;
415
419
  }
416
420
  declare const L1_SHORTCUTS: {
@@ -425,16 +429,29 @@ declare const L2_SHORTCUTS: {
425
429
  };
426
430
  declare type L1Shortcuts = KeyOf<typeof L1_SHORTCUTS>;
427
431
  declare type L2Shortcuts = KeyOf<typeof L2_SHORTCUTS>;
428
- declare type ExpandShortcuts<Q extends string> = Q extends `${infer R}:${infer S}:${infer T}` ? `${ExpandL1<R>}:${ExpandL2<S>}:${T}` : Q extends `${infer R}:${infer S}` ? `${ExpandL1<R>}:${ExpandL2<S>}` : ExpandL1<Q>;
432
+ declare type ExpandShortcuts<Q extends string> = Q extends `${infer L1}:${infer L2}:${infer L3}` ? `${ExpandL1<L1>}:${ExpandL2<L2>}:${L3}` : Q extends `${infer L1}:${infer L2}` ? `${ExpandL1<L1>}:${ExpandL2<L2>}` : ExpandL1<Q>;
429
433
  declare type ExpandL1<S extends string> = S extends L1Shortcuts ? typeof L1_SHORTCUTS[S][number] : S;
430
434
  declare type ExpandL2<S extends string> = S extends L2Shortcuts ? typeof L2_SHORTCUTS[S][number] : S;
431
- declare type Twins<V extends string> = V extends KeyOf<Equivalents> ? Equivalents[V] : V;
432
- declare type Equivalents = {
435
+ declare type AddTwins<L1 extends string, L2 extends string> = TwinsFromL1<L1, L2> | TwinsFromL2<L1, L2>;
436
+ declare type TwinsFromL1<L1 extends string, L2 extends string> = L1 extends KeyOf<L1Equivalents> ? L1Equivalents[L1] : L2;
437
+ declare type L1Equivalents = {
438
+ message: "from";
439
+ edited_message: "from" | "edit_date";
440
+ channel_post: "sender_chat";
441
+ edited_channel_post: "sender_chat" | "edit_date";
442
+ };
443
+ declare type TwinsFromL2<L1 extends string, L2 extends string> = L1 extends KeyOf<L2Equivalents> ? L2 extends KeyOf<L2Equivalents[L1]> ? L2Equivalents[L1][L2] : L2 : L2;
444
+ declare type L2Equivalents = {
445
+ message: MessageEquivalents;
446
+ edited_message: MessageEquivalents;
447
+ channel_post: MessageEquivalents;
448
+ edited_channel_post: MessageEquivalents;
449
+ };
450
+ declare type MessageEquivalents = {
433
451
  animation: "document";
434
- entities: TextMessages;
452
+ entities: "text";
435
453
  caption: CaptionMessages;
436
454
  caption_entities: CaptionMessages;
437
455
  };
438
- declare type TextMessages = "text";
439
456
  declare type CaptionMessages = "animation" | "audio" | "document" | "photo" | "video" | "voice";
440
457
  export {};
package/out/mod.d.ts CHANGED
@@ -1,14 +1,11 @@
1
- export { Bot, BotError } from "./bot.js";
2
- export type { BotConfig, ErrorHandler, PollingOptions } from "./bot.js";
1
+ export { Bot, type BotConfig, BotError, type ErrorHandler, type PollingOptions, } from "./bot.js";
3
2
  export { InputFile } from "./platform.node.js";
4
3
  export { Context } from "./context.js";
5
4
  export * from "./convenience/keyboard.js";
6
5
  export * from "./convenience/session.js";
7
6
  export * from "./convenience/webhook.js";
8
- export { Composer } from "./composer.js";
9
- export type { Middleware, MiddlewareFn, MiddlewareObj, NextFunction, } from "./composer.js";
10
- export { matchFilter } from "./filter.js";
11
- export type { Filter, FilterQuery } from "./filter.js";
7
+ export { Composer, type Middleware, type MiddlewareFn, type MiddlewareObj, type NextFunction, } from "./composer.js";
8
+ export { type Filter, type FilterQuery, matchFilter } from "./filter.js";
12
9
  export { Api } from "./core/api.js";
13
- export type { ApiCallFn, ApiClientOptions, RawApi, TransformableApi, Transformer, WebhookReplyEnvelope, } from "./core/client.js";
10
+ export { type ApiCallFn, type ApiClientOptions, type RawApi, type TransformableApi, type Transformer, type WebhookReplyEnvelope, } from "./core/client.js";
14
11
  export { GrammyError, HttpError } from "./core/error.js";
@@ -1,9 +1,9 @@
1
1
  /// <reference types="node" />
2
- import { InputFileProxy } from "@grammyjs/types";
2
+ import { type InputFileProxy } from "@grammyjs/types";
3
3
  import { Agent as HttpAgent } from "http";
4
4
  import { Agent as HttpsAgent } from "https";
5
5
  import { Readable } from "stream";
6
- import type { ReadStream } from "fs";
6
+ import { type ReadStream } from "fs";
7
7
  import { URL } from "url";
8
8
  export * from "@grammyjs/types";
9
9
  import { debug as d } from "debug";
@@ -1,2 +1,2 @@
1
- export { AbortController, AbortSignal } from "abort-controller";
1
+ export { AbortController, type AbortSignal } from "abort-controller";
2
2
  export { default as fetch } from "node-fetch";
package/out/shim.node.js CHANGED
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetch = exports.AbortSignal = exports.AbortController = void 0;
3
+ exports.fetch = exports.AbortController = void 0;
4
4
  var abort_controller_1 = require("abort-controller");
5
5
  Object.defineProperty(exports, "AbortController", { enumerable: true, get: function () { return abort_controller_1.AbortController; } });
6
- Object.defineProperty(exports, "AbortSignal", { enumerable: true, get: function () { return abort_controller_1.AbortSignal; } });
7
6
  var node_fetch_1 = require("node-fetch");
8
7
  Object.defineProperty(exports, "fetch", { enumerable: true, get: function () { return node_fetch_1.default; } });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "grammy",
3
3
  "description": "The Telegram Bot Framework.",
4
- "version": "1.6.2",
4
+ "version": "1.7.0",
5
5
  "author": "KnorpelSenf",
6
6
  "license": "MIT",
7
7
  "engines": {
@@ -23,7 +23,7 @@
23
23
  "contribs": "all-contributors"
24
24
  },
25
25
  "dependencies": {
26
- "@grammyjs/types": "^2.5.1",
26
+ "@grammyjs/types": "^2.6.0",
27
27
  "abort-controller": "^3.0.0",
28
28
  "debug": "^4.3.3",
29
29
  "node-fetch": "^2.6.5"