grammy 1.4.0 → 1.4.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/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.3-blue?logo=telegram&style=flat-square)](https://core.telegram.org/bots/api)
13
+ [![Bot API](https://img.shields.io/badge/Bot%20API-5.4-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-36-orange.svg?style=flat-square)](#contributors-)
15
+ [![All Contributors](https://img.shields.io/badge/all_contributors-40-orange.svg?style=flat-square)](#contributors-)
16
16
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
17
17
 
18
18
  <!-- deno-fmt-ignore-end -->
@@ -104,6 +104,8 @@ All grammY packages published by [@grammyjs](https://github.com/grammyjs) run na
104
104
 
105
105
  However, given that most bot developers are still using Node, all documentation is written Node-first. We may migrate it if Deno overtakes Node. If you are already on Deno today, we expect you to know what you're doing. You mainly have to adjust the imports to URL imports, and import from [`https://deno.land/x/grammy/mod.ts`](https://deno.land/x/grammy).
106
106
 
107
+ ## [Contribution Guide »](./CONTRIBUTING.md)
108
+
107
109
  ## Contributors ✨
108
110
 
109
111
  Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
@@ -140,7 +142,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
140
142
  <td align="center"><a href="https://github.com/deptyped"><img src="https://avatars.githubusercontent.com/u/26162440?v=4?s=100" width="100px;" alt=""/><br /><sub><b>deptyped</b></sub></a><br /><a href="#example-deptyped" title="Examples">💡</a> <a href="https://github.com/grammyjs/grammY/commits?author=deptyped" title="Documentation">📖</a> <a href="#tutorial-deptyped" title="Tutorials">✅</a> <a href="#question-deptyped" title="Answering Questions">💬</a></td>
141
143
  </tr>
142
144
  <tr>
143
- <td align="center"><a href="https://github.com/dzek69"><img src="https://avatars.githubusercontent.com/u/4936805?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jacek Nowacki</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=dzek69" title="Documentation">📖</a> <a href="https://github.com/grammyjs/grammY/commits?author=dzek69" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3Adzek69" title="Bug reports">🐛</a></td>
145
+ <td align="center"><a href="https://github.com/dzek69"><img src="https://avatars.githubusercontent.com/u/4936805?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jacek Nowacki</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=dzek69" title="Documentation">📖</a> <a href="https://github.com/grammyjs/grammY/commits?author=dzek69" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3Adzek69" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Adzek69" title="Reviewed Pull Requests">👀</a></td>
144
146
  <td align="center"><a href="https://blog.outv.im"><img src="https://avatars.githubusercontent.com/u/19144373?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Outvi V</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=outloudvi" title="Code">💻</a></td>
145
147
  <td align="center"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=eltociear" title="Documentation">📖</a></td>
146
148
  <td align="center"><a href="https://github.com/amberlionk"><img src="https://avatars.githubusercontent.com/u/29119723?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yevhen Denesiuk</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Aamberlionk" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3Aamberlionk" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=amberlionk" title="Code">💻</a></td>
@@ -159,6 +161,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
159
161
  </tr>
160
162
  <tr>
161
163
  <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></td>
164
+ <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>
165
+ <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>
166
+ <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></td>
167
+ <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></td>
162
168
  </tr>
163
169
  </table>
164
170
 
@@ -168,5 +174,3 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
168
174
  <!-- ALL-CONTRIBUTORS-LIST:END -->
169
175
 
170
176
  This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
171
-
172
- ## [Contribution Guide »](./CONTRIBUTING.md)
package/out/bot.js CHANGED
@@ -248,14 +248,14 @@ a known bot info object.");
248
248
  async start(options) {
249
249
  var _a, _b;
250
250
  // Perform setup
251
- await this.init();
251
+ await withRetries(() => this.init());
252
252
  if (this.pollingRunning) {
253
253
  debug("Simple long polling already running!");
254
254
  return;
255
255
  }
256
- await this.api.deleteWebhook({
256
+ await withRetries(() => this.api.deleteWebhook({
257
257
  drop_pending_updates: options === null || options === void 0 ? void 0 : options.drop_pending_updates,
258
- });
258
+ }));
259
259
  // Prevent common misuse that causes memory leak
260
260
  this.use = () => {
261
261
  throw new Error(`It looks like you are registering more listeners \
@@ -390,4 +390,30 @@ you can circumvent this protection against memory leaks.`);
390
390
  }
391
391
  }
392
392
  exports.Bot = Bot;
393
+ async function withRetries(task) {
394
+ let success = false;
395
+ while (!success) {
396
+ try {
397
+ await task();
398
+ success = true;
399
+ }
400
+ catch (error) {
401
+ debugErr(error);
402
+ if (error instanceof error_js_1.HttpError)
403
+ continue;
404
+ if (error instanceof error_js_1.GrammyError) {
405
+ if (error.error_code >= 500)
406
+ continue;
407
+ if (error.error_code === 429) {
408
+ const retryAfter = error.parameters.retry_after;
409
+ if (retryAfter !== undefined) {
410
+ await new Promise((resolve) => setTimeout(resolve, 1000 * retryAfter));
411
+ }
412
+ continue;
413
+ }
414
+ }
415
+ throw error;
416
+ }
417
+ }
418
+ }
393
419
  const shim_node_js_1 = require("./shim.node.js");
package/out/composer.js CHANGED
@@ -554,7 +554,9 @@ class Composer {
554
554
  return this.lazy(async (ctx) => {
555
555
  var _a;
556
556
  const route = await router(ctx);
557
- return route === undefined ? [] : (_a = routeHandlers[route]) !== null && _a !== void 0 ? _a : fallback;
557
+ return (_a = (route === undefined || !routeHandlers[route]
558
+ ? fallback
559
+ : routeHandlers[route])) !== null && _a !== void 0 ? _a : [];
558
560
  });
559
561
  }
560
562
  /**
@@ -637,7 +639,7 @@ exports.Composer = Composer;
637
639
  function triggerFn(trigger) {
638
640
  return toArray(trigger).map((t) => typeof t === "string"
639
641
  ? (txt) => (txt === t ? t : null)
640
- : (txt) => t.exec(txt));
642
+ : (txt) => txt.match(t));
641
643
  }
642
644
  function match(ctx, content, triggers) {
643
645
  for (const t of triggers) {
@@ -0,0 +1,44 @@
1
+ import type { IncomingMessage, ServerResponse } from "http";
2
+ /**
3
+ * HTTP Web frameworks for which grammY provides compatible callback out of the
4
+ * box.
5
+ */
6
+ export declare type SupportedFrameworks = "express" | "http" | "https" | "koa" | "fastify" | "worktop" | "callback" | "aws-lambda";
7
+ export declare const defaultFramework: SupportedFrameworks;
8
+ export declare const frameworkAdapters: {
9
+ express: (req: any, res: any) => {
10
+ update: Promise<any>;
11
+ end: () => any;
12
+ respond: (json: string) => void;
13
+ };
14
+ http: (req: IncomingMessage, res: ServerResponse) => {
15
+ update: Promise<any>;
16
+ end: () => void;
17
+ respond: (json: string) => void;
18
+ };
19
+ https: (req: IncomingMessage, res: ServerResponse) => {
20
+ update: Promise<any>;
21
+ end: () => void;
22
+ respond: (json: string) => void;
23
+ };
24
+ koa: (ctx: any) => {
25
+ update: Promise<any>;
26
+ end: () => string;
27
+ respond: (json: string) => void;
28
+ };
29
+ fastify: (req: any, reply: any) => {
30
+ update: Promise<any>;
31
+ end: () => any;
32
+ respond: (json: string) => any;
33
+ };
34
+ worktop: (req: any, res: any) => {
35
+ update: Promise<any>;
36
+ end: () => any;
37
+ respond: (json: string) => any;
38
+ };
39
+ "aws-lambda": (event: any, _context: any, callback: any) => {
40
+ update: any;
41
+ end: () => any;
42
+ respond: (json: string) => any;
43
+ };
44
+ };
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.frameworkAdapters = exports.defaultFramework = void 0;
4
+ exports.defaultFramework = "express";
5
+ exports.frameworkAdapters = {
6
+ express: (req, res) => ({
7
+ update: Promise.resolve(req.body),
8
+ end: () => res.end(),
9
+ respond: (json) => {
10
+ res.set("Content-Type", "application/json");
11
+ res.send(json);
12
+ },
13
+ }),
14
+ http: (req, res) => ({
15
+ update: new Promise((resolve) => {
16
+ const chunks = [];
17
+ req
18
+ .on("data", (chunk) => chunks.push(chunk))
19
+ .on("end", () => {
20
+ const raw = Buffer.concat(chunks).toString("utf-8");
21
+ resolve(JSON.parse(raw));
22
+ });
23
+ }),
24
+ end: () => res.end(),
25
+ respond: (json) => {
26
+ return res
27
+ .writeHead(200, { "Content-Type": "application/json" })
28
+ .end(json);
29
+ },
30
+ }),
31
+ https: (req, res) => ({
32
+ update: new Promise((resolve) => {
33
+ const chunks = [];
34
+ req
35
+ .on("data", (chunk) => chunks.push(chunk))
36
+ .on("end", () => {
37
+ const raw = Buffer.concat(chunks).toString("utf-8");
38
+ resolve(JSON.parse(raw));
39
+ });
40
+ }),
41
+ end: () => res.end(),
42
+ respond: (json) => {
43
+ return res
44
+ .writeHead(200, { "Content-Type": "application/json" })
45
+ .end(json);
46
+ },
47
+ }),
48
+ koa: (ctx) => ({
49
+ update: Promise.resolve(ctx.request.body),
50
+ end: () => (ctx.body = ""),
51
+ respond: (json) => {
52
+ ctx.set("Content-Type", "application/json");
53
+ ctx.response.body = json;
54
+ },
55
+ }),
56
+ fastify: (req, reply) => ({
57
+ update: Promise.resolve(req.body),
58
+ end: () => reply.send({}),
59
+ respond: (json) => reply.send(json),
60
+ }),
61
+ worktop: (req, res) => ({
62
+ update: Promise.resolve(req.body.json()),
63
+ end: () => res.end(),
64
+ respond: (json) => res.send(200, json),
65
+ }),
66
+ "aws-lambda": (event, _context, callback) => ({
67
+ update: JSON.parse(event.body),
68
+ end: () => callback(null, { statusCode: 200 }),
69
+ respond: (json) => callback(null, {
70
+ statusCode: 200,
71
+ body: json,
72
+ }),
73
+ }),
74
+ // please open a PR if you want to add another
75
+ };
@@ -57,32 +57,32 @@ class ApiClient {
57
57
  this.hasUsedWebhookReply = true;
58
58
  const config = (0, payload_js_1.createJsonPayload)({ ...payload, method });
59
59
  await this.webhookReplyEnvelope.send(config.body);
60
+ // deno-lint-ignore no-explicit-any
60
61
  return { ok: true, result: true };
61
62
  }
62
63
  else {
63
64
  const p = payload !== null && payload !== void 0 ? payload : {};
64
- const config = formDataRequired
65
- ? (0, payload_js_1.createFormDataPayload)(p)
66
- : (0, payload_js_1.createJsonPayload)(p);
67
- let res;
68
- try {
69
- res = await (0, shim_node_js_1.fetch)(url, {
65
+ const sensLogs = this.options.sensitiveLogs;
66
+ const abortController = new shim_node_js_1.AbortController();
67
+ const abort = combineAborts(abortController, signal);
68
+ const res = await new Promise((resolve, reject) => {
69
+ function onStreamError(err) {
70
+ abort();
71
+ reject(err);
72
+ }
73
+ const onHttpError = toHttpError(method, sensLogs, reject);
74
+ const config = formDataRequired
75
+ ? (0, payload_js_1.createFormDataPayload)(p, onStreamError)
76
+ : (0, payload_js_1.createJsonPayload)(p);
77
+ const opts = {
70
78
  ...this.options.baseFetchConfig,
71
- signal,
79
+ signal: abortController.signal,
72
80
  ...config,
73
- });
74
- }
75
- catch (err) {
76
- let msg = `Network request for '${method}' failed!`;
77
- if (isTelegramError(err)) {
78
- msg += ` (${err.status}: ${err.statusText})`;
79
- }
80
- if (this.options.sensitiveLogs && err instanceof Error) {
81
- msg += ` ${err.message}`;
82
- }
83
- throw new error_js_1.HttpError(msg, err);
84
- }
85
- return await res.json();
81
+ };
82
+ (0, shim_node_js_1.fetch)(url, opts).then((res) => res.json()).then(resolve)
83
+ .catch(onHttpError);
84
+ });
85
+ return res;
86
86
  }
87
87
  }
88
88
  });
@@ -167,4 +167,28 @@ function isTelegramError(err) {
167
167
  "status" in err &&
168
168
  "statusText" in err);
169
169
  }
170
+ function toHttpError(method, sensitiveLogs, reject) {
171
+ return (err) => {
172
+ let msg = `Network request for '${method}' failed!`;
173
+ if (isTelegramError(err))
174
+ msg += ` (${err.status}: ${err.statusText})`;
175
+ if (sensitiveLogs && err instanceof Error)
176
+ msg += ` ${err.message}`;
177
+ reject(new error_js_1.HttpError(msg, err));
178
+ };
179
+ }
180
+ function combineAborts(abortController, signal) {
181
+ if (signal === undefined)
182
+ return () => abortController.abort();
183
+ const sig = signal;
184
+ function abort() {
185
+ abortController.abort();
186
+ sig.removeEventListener("abort", abort);
187
+ }
188
+ if (sig.aborted)
189
+ abort();
190
+ else
191
+ sig.addEventListener("abort", abort);
192
+ return abort;
193
+ }
170
194
  const shim_node_js_1 = require("../shim.node.js");
@@ -30,7 +30,7 @@ export declare function createJsonPayload(payload: Record<string, unknown>): {
30
30
  *
31
31
  * @param payload The payload to wrap
32
32
  */
33
- export declare function createFormDataPayload(payload: Record<string, unknown>): {
33
+ export declare function createFormDataPayload(payload: Record<string, unknown>, onError: (err: unknown) => void): {
34
34
  method: string;
35
35
  headers: {
36
36
  "content-type": string;
@@ -46,6 +46,14 @@ function createJsonPayload(payload) {
46
46
  };
47
47
  }
48
48
  exports.createJsonPayload = createJsonPayload;
49
+ async function* protectItr(itr, onError) {
50
+ try {
51
+ yield* itr;
52
+ }
53
+ catch (err) {
54
+ onError(err);
55
+ }
56
+ }
49
57
  /**
50
58
  * Turns a payload into an options object that can be passed to a `fetch` call
51
59
  * by setting the necessary headers and method. Note that this method creates a
@@ -54,15 +62,18 @@ exports.createJsonPayload = createJsonPayload;
54
62
  *
55
63
  * @param payload The payload to wrap
56
64
  */
57
- function createFormDataPayload(payload) {
65
+ function createFormDataPayload(payload, onError) {
58
66
  const boundary = createBoundary();
67
+ const itr = payloadToMultipartItr(payload, boundary);
68
+ const safeItr = protectItr(itr, onError);
69
+ const stream = (0, platform_node_js_1.itrToStream)(safeItr);
59
70
  return {
60
71
  method: "POST",
61
72
  headers: {
62
73
  "content-type": `multipart/form-data; boundary=${boundary}`,
63
74
  connection: "keep-alive",
64
75
  },
65
- body: (0, platform_node_js_1.itrToStream)(payloadToMultipartItr(payload, boundary)),
76
+ body: stream,
66
77
  };
67
78
  }
68
79
  exports.createFormDataPayload = createFormDataPayload;
package/out/filter.d.ts CHANGED
@@ -82,6 +82,9 @@ declare const UPDATE_KEYS: {
82
82
  readonly underline: {};
83
83
  readonly strikethrough: {};
84
84
  readonly code: {};
85
+ readonly pre: {};
86
+ readonly text_link: {};
87
+ readonly text_mention: {};
85
88
  };
86
89
  readonly caption_entities: {
87
90
  readonly mention: {};
@@ -96,6 +99,9 @@ declare const UPDATE_KEYS: {
96
99
  readonly underline: {};
97
100
  readonly strikethrough: {};
98
101
  readonly code: {};
102
+ readonly pre: {};
103
+ readonly text_link: {};
104
+ readonly text_mention: {};
99
105
  };
100
106
  readonly caption: {};
101
107
  };
@@ -155,6 +161,9 @@ declare const UPDATE_KEYS: {
155
161
  readonly underline: {};
156
162
  readonly strikethrough: {};
157
163
  readonly code: {};
164
+ readonly pre: {};
165
+ readonly text_link: {};
166
+ readonly text_mention: {};
158
167
  };
159
168
  readonly caption_entities: {
160
169
  readonly mention: {};
@@ -169,6 +178,9 @@ declare const UPDATE_KEYS: {
169
178
  readonly underline: {};
170
179
  readonly strikethrough: {};
171
180
  readonly code: {};
181
+ readonly pre: {};
182
+ readonly text_link: {};
183
+ readonly text_mention: {};
172
184
  };
173
185
  readonly caption: {};
174
186
  };
@@ -214,6 +226,9 @@ declare const UPDATE_KEYS: {
214
226
  readonly underline: {};
215
227
  readonly strikethrough: {};
216
228
  readonly code: {};
229
+ readonly pre: {};
230
+ readonly text_link: {};
231
+ readonly text_mention: {};
217
232
  };
218
233
  readonly caption_entities: {
219
234
  readonly mention: {};
@@ -228,6 +243,9 @@ declare const UPDATE_KEYS: {
228
243
  readonly underline: {};
229
244
  readonly strikethrough: {};
230
245
  readonly code: {};
246
+ readonly pre: {};
247
+ readonly text_link: {};
248
+ readonly text_mention: {};
231
249
  };
232
250
  readonly caption: {};
233
251
  };
@@ -273,6 +291,9 @@ declare const UPDATE_KEYS: {
273
291
  readonly underline: {};
274
292
  readonly strikethrough: {};
275
293
  readonly code: {};
294
+ readonly pre: {};
295
+ readonly text_link: {};
296
+ readonly text_mention: {};
276
297
  };
277
298
  readonly caption_entities: {
278
299
  readonly mention: {};
@@ -287,6 +308,9 @@ declare const UPDATE_KEYS: {
287
308
  readonly underline: {};
288
309
  readonly strikethrough: {};
289
310
  readonly code: {};
311
+ readonly pre: {};
312
+ readonly text_link: {};
313
+ readonly text_mention: {};
290
314
  };
291
315
  readonly caption: {};
292
316
  };
package/out/filter.js CHANGED
@@ -206,6 +206,9 @@ const ENTITY_KEYS = {
206
206
  underline: {},
207
207
  strikethrough: {},
208
208
  code: {},
209
+ pre: {},
210
+ text_link: {},
211
+ text_mention: {},
209
212
  };
210
213
  const USER_KEYS = {
211
214
  me: {},
@@ -3,6 +3,7 @@ import { InputFileProxy } from "@grammyjs/types";
3
3
  import { Agent } from "https";
4
4
  import { Readable } from "stream";
5
5
  import type { ReadStream } from "fs";
6
+ import { URL } from "url";
6
7
  export * from "@grammyjs/types";
7
8
  export { debug } from "debug";
8
9
  export declare const itrToStream: (itr: AsyncIterable<Uint8Array>) => Readable;
@@ -11,6 +12,14 @@ export declare const baseFetchConfig: {
11
12
  compress: boolean;
12
13
  agent: Agent;
13
14
  };
15
+ /** Something that looks like a URL. */
16
+ interface URLLike {
17
+ /**
18
+ * Identifier of the resouce. Must be in a format that can be parsed by the
19
+ * URL constructor.
20
+ */
21
+ url: string;
22
+ }
14
23
  export declare const inputFileData: unique symbol;
15
24
  /**
16
25
  * An `InputFile` wraps a number of different sources for [sending
@@ -20,7 +29,8 @@ export declare const inputFileData: unique symbol;
20
29
  * Reference](https://core.telegram.org/bots/api#inputfile).
21
30
  */
22
31
  export declare class InputFile {
23
- readonly [inputFileData]: ConstructorParameters<typeof InputFile>[0];
32
+ private consumed;
33
+ private readonly fileData;
24
34
  /**
25
35
  * Optional name of the constructed `InputFile` instance.
26
36
  *
@@ -35,7 +45,8 @@ export declare class InputFile {
35
45
  * @param file A path to a local file or a `Buffer` or a `fs.ReadStream` that specifies the file data
36
46
  * @param filename Optional name of the file
37
47
  */
38
- constructor(file: string | Uint8Array | ReadStream | AsyncIterable<Uint8Array>, filename?: string);
48
+ constructor(file: string | URL | URLLike | Uint8Array | ReadStream | AsyncIterable<Uint8Array>, filename?: string);
49
+ get [inputFileData](): string | Uint8Array | AsyncIterable<Uint8Array> | ReadStream;
39
50
  }
40
51
  declare type GrammyTypes = InputFileProxy<InputFile>;
41
52
  /** Wrapper type to bundle all methods of the Telegram API */
@@ -9,12 +9,12 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
9
9
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
10
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
11
  };
12
- var _a;
13
12
  Object.defineProperty(exports, "__esModule", { value: true });
14
13
  exports.InputFile = exports.inputFileData = exports.baseFetchConfig = exports.streamFile = exports.itrToStream = exports.debug = void 0;
15
14
  const https_1 = require("https");
16
15
  const path_1 = require("path");
17
16
  const stream_1 = require("stream");
17
+ const url_1 = require("url");
18
18
  // === Export all API types
19
19
  __exportStar(require("@grammyjs/types"), exports);
20
20
  // === Export debug
@@ -50,7 +50,13 @@ class InputFile {
50
50
  * @param filename Optional name of the file
51
51
  */
52
52
  constructor(file, filename) {
53
- Object.defineProperty(this, _a, {
53
+ Object.defineProperty(this, "consumed", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: false
58
+ });
59
+ Object.defineProperty(this, "fileData", {
54
60
  enumerable: true,
55
61
  configurable: true,
56
62
  writable: true,
@@ -69,12 +75,37 @@ class InputFile {
69
75
  writable: true,
70
76
  value: void 0
71
77
  });
72
- this[exports.inputFileData] = file;
78
+ this.fileData = file;
73
79
  if (filename === undefined && typeof file === "string") {
74
80
  filename = (0, path_1.basename)(file);
75
81
  }
76
82
  this.filename = filename;
77
83
  }
84
+ get [exports.inputFileData]() {
85
+ if (this.consumed) {
86
+ throw new Error("Cannot reuse InputFile data source!");
87
+ }
88
+ let data = this.fileData;
89
+ if (typeof data === "object" && ("url" in data || data instanceof url_1.URL)) {
90
+ data = fetchFile(data instanceof url_1.URL ? data : data.url);
91
+ }
92
+ else if (typeof data !== "string" && (!(data instanceof Uint8Array))) {
93
+ this.consumed = false;
94
+ }
95
+ return data;
96
+ }
78
97
  }
79
98
  exports.InputFile = InputFile;
80
- _a = exports.inputFileData;
99
+ async function* fetchFile(url) {
100
+ const { body } = await (0, shim_node_js_1.fetch)(url);
101
+ if (body === null) {
102
+ throw new Error(`Download failed, no response body from '${url}'`);
103
+ }
104
+ for await (const chunk of body) {
105
+ if (typeof chunk === "string") {
106
+ throw new Error(`Could not transfer file, received string data instead of bytes from '${url}'`);
107
+ }
108
+ yield chunk;
109
+ }
110
+ }
111
+ const shim_node_js_1 = require("./shim.node.js");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "grammy",
3
3
  "description": "grammY core package ported to Node.js",
4
- "version": "1.4.0",
4
+ "version": "1.4.1",
5
5
  "author": "KnorpelSenf",
6
6
  "license": "MIT",
7
7
  "engines": {
@@ -14,6 +14,7 @@
14
14
  },
15
15
  "scripts": {
16
16
  "prepare": "npm run backport",
17
+ "cache": "deno cache src/mod.ts",
17
18
  "lint": "deno lint --config deno.json",
18
19
  "fmt": "deno fmt --config deno.json",
19
20
  "test": "deno test ./test/",