grammy 1.4.2 → 1.4.3

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
@@ -12,7 +12,7 @@ _<h2 align="center"> [:mag: Documentation](https://grammy.dev) | [:page_with_cur
12
12
 
13
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-40-orange.svg?style=flat-square)](#contributors-)
15
+ [![All Contributors](https://img.shields.io/badge/all_contributors-43-orange.svg?style=flat-square)](#contributors-)
16
16
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
17
17
 
18
18
  <!-- deno-fmt-ignore-end -->
@@ -100,7 +100,7 @@ Here are some more resources to support you:
100
100
 
101
101
  ## Deno Support
102
102
 
103
- All grammY packages published by [@grammyjs](https://github.com/grammyjs) run natively in Deno. We are compiling every codebase to still run on Node.
103
+ All grammY packages published by [@grammyjs](https://github.com/grammyjs) run natively on Deno. We are compiling every codebase to still run on Node.
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
 
@@ -126,7 +126,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
126
126
  <tr>
127
127
  <td align="center"><a href="https://edjopato.de/"><img src="https://avatars.githubusercontent.com/u/7953011?v=4?s=100" width="100px;" alt=""/><br /><sub><b>EdJoPaTo</b></sub></a><br /><a href="#plugin-EdJoPaTo" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/grammyjs/grammY/commits?author=EdJoPaTo" title="Documentation">📖</a> <a href="#ideas-EdJoPaTo" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AEdJoPaTo" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3AEdJoPaTo" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=EdJoPaTo" title="Code">💻</a> <a href="#question-EdJoPaTo" title="Answering Questions">💬</a></td>
128
128
  <td align="center"><a href="https://github.com/Amir-Zouerami"><img src="https://avatars.githubusercontent.com/u/53701884?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amir Zouerami</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Amir-Zouerami" title="Documentation">📖</a> <a href="#plugin-Amir-Zouerami" title="Plugin/utility libraries">🔌</a></td>
129
- <td align="center"><a href="https://github.com/rojserbest"><img src="https://avatars.githubusercontent.com/u/49933115?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Roj</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=rojserbest" title="Documentation">📖</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Arojserbest" title="Reviewed Pull Requests">👀</a> <a href="#infra-rojserbest" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
129
+ <td align="center"><a href="https://github.com/rojserbest"><img src="https://avatars.githubusercontent.com/u/49933115?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Roj</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=rojserbest" title="Documentation">📖</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Arojserbest" title="Reviewed Pull Requests">👀</a> <a href="#infra-rojserbest" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#translation-rojserbest" title="Translation">🌍</a> <a href="https://github.com/grammyjs/grammY/commits?author=rojserbest" title="Code">💻</a></td>
130
130
  <td align="center"><a href="https://github.com/jokasimr"><img src="https://avatars.githubusercontent.com/u/20954731?v=4?s=100" width="100px;" alt=""/><br /><sub><b>jokasimr</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Ajokasimr" title="Bug reports">🐛</a></td>
131
131
  <td align="center"><a href="https://github.com/CikiMomogi"><img src="https://avatars.githubusercontent.com/u/74030149?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ciki Momogi</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=CikiMomogi" title="Documentation">📖</a></td>
132
132
  <td align="center"><a href="https://github.com/AndreoliBR"><img src="https://avatars.githubusercontent.com/u/15970011?v=4?s=100" width="100px;" alt=""/><br /><sub><b>AndreoliBR</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AAndreoliBR" title="Reviewed Pull Requests">👀</a></td>
@@ -142,7 +142,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
142
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>
143
143
  </tr>
144
144
  <tr>
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>
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> <a href="#ideas-dzek69" title="Ideas, Planning, & Feedback">🤔</a></td>
146
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>
147
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>
148
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>
@@ -154,17 +154,22 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
154
154
  <td align="center"><a href="https://github.com/chimit"><img src="https://avatars.githubusercontent.com/u/839349?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chimit</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=chimit" title="Documentation">📖</a></td>
155
155
  <td align="center"><a href="https://github.com/CalsiBotDev"><img src="https://avatars.githubusercontent.com/u/55633371?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Calsi</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=CalsiBotDev" title="Documentation">📖</a></td>
156
156
  <td align="center"><a href="https://zohren.xyz"><img src="https://avatars.githubusercontent.com/u/15788906?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonas Zohren</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Ajfowl" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=jfowl" title="Code">💻</a></td>
157
- <td align="center"><a href="https://zhemu.buzz/"><img src="https://avatars.githubusercontent.com/u/56839018?v=4?s=100" width="100px;" alt=""/><br /><sub><b>linbuxiao</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=linbuxiao" title="Documentation">📖</a></td>
158
- <td align="center"><a href="https://github.com/JiquanWang99"><img src="https://avatars.githubusercontent.com/u/63894579?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JiquanWang99</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=JiquanWang99" title="Documentation">📖</a></td>
157
+ <td align="center"><a href="https://zhemu.buzz/"><img src="https://avatars.githubusercontent.com/u/56839018?v=4?s=100" width="100px;" alt=""/><br /><sub><b>linbuxiao</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=linbuxiao" title="Documentation">📖</a> <a href="#translation-linbuxiao" title="Translation">🌍</a></td>
158
+ <td align="center"><a href="https://github.com/JiquanWang99"><img src="https://avatars.githubusercontent.com/u/63894579?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JiquanWang99</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=JiquanWang99" title="Documentation">📖</a> <a href="#translation-JiquanWang99" title="Translation">🌍</a></td>
159
159
  <td align="center"><a href="http://bor691.ir/"><img src="https://avatars.githubusercontent.com/u/4184939?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Borhan Hafez</b></sub></a><br /><a href="#plugin-zumoshi" title="Plugin/utility libraries">🔌</a></td>
160
- <td align="center"><a href="https://blog.limx.dev/"><img src="https://avatars.githubusercontent.com/u/6434137?v=4?s=100" width="100px;" alt=""/><br /><sub><b>WingLim</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=WingLim" title="Documentation">📖</a></td>
160
+ <td align="center"><a href="https://blog.limx.dev/"><img src="https://avatars.githubusercontent.com/u/6434137?v=4?s=100" width="100px;" alt=""/><br /><sub><b>WingLim</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=WingLim" title="Documentation">📖</a> <a href="#translation-WingLim" title="Translation">🌍</a></td>
161
161
  </tr>
162
162
  <tr>
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>
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> <a href="#translation-taotie111" title="Translation">🌍</a></td>
164
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
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
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>
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> <a href="#translation-kidonng" title="Translation">🌍</a></td>
168
+ <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>
169
+ <td align="center"><a href="https://kikobeats.com/"><img src="https://avatars.githubusercontent.com/u/2096101?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kiko Beats</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Kikobeats" title="Documentation">📖</a></td>
170
+ </tr>
171
+ <tr>
172
+ <td align="center"><a href="http://///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////kraftwerk28.pp.ua"><img src="https://avatars.githubusercontent.com/u/31807671?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vsevolod</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=kraftwerk28" title="Code">💻</a> <a href="#ideas-kraftwerk28" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Akraftwerk28" title="Reviewed Pull Requests">👀</a></td>
168
173
  </tr>
169
174
  </table>
170
175
 
@@ -0,0 +1,39 @@
1
+ import type { IncomingMessage, ServerResponse } from "http";
2
+ export declare const adapters: {
3
+ http: (req: IncomingMessage, res: ServerResponse) => {
4
+ update: Promise<any>;
5
+ end: () => void;
6
+ respond: (json: string) => void;
7
+ };
8
+ https: (req: IncomingMessage, res: ServerResponse) => {
9
+ update: Promise<any>;
10
+ end: () => void;
11
+ respond: (json: string) => void;
12
+ };
13
+ express: (req: any, res: any) => {
14
+ update: Promise<any>;
15
+ end: () => any;
16
+ respond: (json: string) => void;
17
+ };
18
+ koa: (ctx: any) => {
19
+ update: Promise<any>;
20
+ end: () => void;
21
+ respond: (json: string) => void;
22
+ };
23
+ fastify: (req: any, reply: any) => {
24
+ update: Promise<any>;
25
+ end: () => any;
26
+ respond: (json: string) => any;
27
+ };
28
+ worktop: (req: any, res: any) => {
29
+ update: Promise<any>;
30
+ end: () => any;
31
+ respond: (json: string) => any;
32
+ };
33
+ "aws-lambda": (event: any, _context: any, callback: any) => {
34
+ update: any;
35
+ end: () => any;
36
+ respond: (json: string) => any;
37
+ };
38
+ };
39
+ export declare const defaultAdapter = "express";
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultAdapter = exports.adapters = void 0;
4
+ /** Node.js native 'http' and 'https' modules */
5
+ const http = (req, res) => ({
6
+ update: new Promise((resolve, reject) => {
7
+ const chunks = [];
8
+ req.on("data", (chunk) => chunks.push(chunk)).once("end", () => {
9
+ const raw = Buffer.concat(chunks).toString("utf-8");
10
+ resolve(JSON.parse(raw));
11
+ }).once("error", reject);
12
+ }),
13
+ end: () => res.end(),
14
+ respond: (json) => res.writeHead(200, { "Content-Type": "application/json" }).end(json),
15
+ });
16
+ /** express web framework */
17
+ const express = (req, res) => ({
18
+ update: Promise.resolve(req.body),
19
+ end: () => res.end(),
20
+ respond: (json) => {
21
+ res.set("Content-Type", "application/json");
22
+ res.send(json);
23
+ },
24
+ });
25
+ /** koa web framework */
26
+ const koa = (ctx) => ({
27
+ update: Promise.resolve(ctx.request.body),
28
+ end: () => {
29
+ ctx.body = "";
30
+ },
31
+ respond: (json) => {
32
+ ctx.set("Content-Type", "application/json");
33
+ ctx.response.body = json;
34
+ },
35
+ });
36
+ /** fastify web framework */
37
+ const fastify = (req, reply) => ({
38
+ update: Promise.resolve(req.body),
39
+ end: () => reply.status(200).send(),
40
+ respond: (json) => reply.send(json),
41
+ });
42
+ /** worktop CloudFlare workers framework */
43
+ const worktop = (req, res) => ({
44
+ update: Promise.resolve(req.body.json()),
45
+ end: () => res.end(),
46
+ respond: (json) => res.send(200, json),
47
+ });
48
+ /** AWS lambda serverless functions */
49
+ const awsLambda = (event, _context, callback) => ({
50
+ update: JSON.parse(event.body),
51
+ end: () => callback(null, { statusCode: 200 }),
52
+ respond: (json) => callback(null, { statusCode: 200, body: json }),
53
+ });
54
+ // please open a PR if you want to add another
55
+ exports.adapters = {
56
+ http,
57
+ https: http,
58
+ express,
59
+ koa,
60
+ fastify,
61
+ worktop,
62
+ "aws-lambda": awsLambda,
63
+ };
64
+ exports.defaultAdapter = "express";
@@ -1,10 +1,81 @@
1
+ /// <reference types="node" />
1
2
  import { Bot } from "../bot.js";
3
+ import { Update } from "../platform.node.js";
2
4
  import { Context } from "../context.js";
5
+ declare const adapters: {
6
+ callback: FrameworkAdapter;
7
+ http: (req: import("http").IncomingMessage, res: import("http").ServerResponse) => {
8
+ update: Promise<any>;
9
+ end: () => void;
10
+ respond: (json: string) => void;
11
+ };
12
+ https: (req: import("http").IncomingMessage, res: import("http").ServerResponse) => {
13
+ update: Promise<any>;
14
+ end: () => void;
15
+ respond: (json: string) => void;
16
+ };
17
+ express: (req: any, res: any) => {
18
+ update: Promise<any>;
19
+ end: () => any;
20
+ respond: (json: string) => void;
21
+ };
22
+ koa: (ctx: any) => {
23
+ update: Promise<any>;
24
+ end: () => void;
25
+ respond: (json: string) => void;
26
+ };
27
+ fastify: (req: any, reply: any) => {
28
+ update: Promise<any>;
29
+ end: () => any;
30
+ respond: (json: string) => any;
31
+ };
32
+ worktop: (req: any, res: any) => {
33
+ update: Promise<any>;
34
+ end: () => any;
35
+ respond: (json: string) => any;
36
+ };
37
+ "aws-lambda": (event: any, _context: any, callback: any) => {
38
+ update: any;
39
+ end: () => any;
40
+ respond: (json: string) => any;
41
+ };
42
+ };
3
43
  /**
4
44
  * HTTP Web frameworks for which grammY provides compatible callback out of the
5
45
  * box.
6
46
  */
7
- declare type SupportedFrameworks = "express" | "http" | "https" | "koa" | "oak" | "fastify" | "worktop" | "callback" | "aws-lambda";
47
+ declare type SupportedFrameworks = keyof typeof adapters;
48
+ /**
49
+ * Abstraction over a request-response cycle, provding access to the update, as
50
+ * well as a mechanism for responding to the request and to end it.
51
+ */
52
+ interface ReqResHandler {
53
+ /**
54
+ * The update object sent from Telegram, usually resolves the request's JSON
55
+ * body
56
+ */
57
+ update: Promise<Update>;
58
+ /**
59
+ * Ends the request immediately without body, called after every request
60
+ * unless a webhook reply was performed
61
+ */
62
+ end?: () => void;
63
+ /**
64
+ * Sends the specified JSON as a payload in the body, used for webhook
65
+ * replies
66
+ */
67
+ respond: (json: string) => unknown;
68
+ /**
69
+ * Some frameworks (e.g. Deno's std/http `listenAndServe`) assume
70
+ * that handler returns something
71
+ */
72
+ handlerReturn?: any;
73
+ }
74
+ /**
75
+ * Middleware for a web framework. Creates a request-response handler for a
76
+ * request. The handler will be used to integrate with the compatible framework.
77
+ */
78
+ export declare type FrameworkAdapter = (...args: any[]) => ReqResHandler;
8
79
  /**
9
80
  * Creates a callback function that you can pass to a web framework (such as
10
81
  * express) if you want to run your bot via webhooks. Use it like this:
@@ -24,5 +95,5 @@ declare type SupportedFrameworks = "express" | "http" | "https" | "koa" | "oak"
24
95
  * @param onTimeout An optional strategy to handle timeouts (default: 'throw')
25
96
  * @param timeoutMilliseconds An optional number of timeout milliseconds (default: 10_000)
26
97
  */
27
- export declare function webhookCallback<C extends Context = Context>(bot: Bot<C>, framework?: SupportedFrameworks, onTimeout?: "throw" | "return" | ((...args: any[]) => unknown), timeoutMilliseconds?: number): (...args: any[]) => Promise<void>;
98
+ export declare function webhookCallback<C extends Context = Context>(bot: Bot<C>, adapter?: SupportedFrameworks | FrameworkAdapter, onTimeout?: "throw" | "return" | ((...args: any[]) => unknown), timeoutMilliseconds?: number): (...args: any[]) => Promise<any>;
28
99
  export {};
@@ -2,60 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.webhookCallback = void 0;
4
4
  const platform_node_js_1 = require("../platform.node.js");
5
+ const frameworks_node_js_1 = require("./frameworks.node.js");
5
6
  const debugErr = (0, platform_node_js_1.debug)("grammy:error");
6
- const standard = (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
- },
7
+ const callbackAdapter = (update, callback) => ({
8
+ update: Promise.resolve(update),
9
+ respond: callback,
13
10
  });
14
- // Integrations with popular frameworks
15
- const frameworkAdapters = {
16
- express: standard,
17
- http: standard,
18
- https: standard,
19
- koa: (ctx) => ({
20
- update: Promise.resolve(ctx.request.body),
21
- end: () => (ctx.body = ""),
22
- respond: (json) => {
23
- ctx.set("Content-Type", "application/json");
24
- ctx.response.body = json;
25
- },
26
- }),
27
- oak: (ctx) => ({
28
- update: ctx.request.body({ type: "json" }).value,
29
- end: () => (ctx.response.status = 200),
30
- respond: (json) => {
31
- ctx.response.type = "json";
32
- ctx.response.body = json;
33
- },
34
- }),
35
- fastify: (req, reply) => ({
36
- update: Promise.resolve(req.body),
37
- end: () => reply.send({}),
38
- respond: (json) => reply.send(json),
39
- }),
40
- worktop: (req, res) => ({
41
- update: Promise.resolve(req.body.json()),
42
- end: () => res.end(),
43
- respond: (json) => res.send(200, json),
44
- }),
45
- callback: (update, callback) => ({
46
- update: update,
47
- respond: callback,
48
- }),
49
- "aws-lambda": (event, _context, callback) => ({
50
- update: JSON.parse(event.body),
51
- end: () => callback(null, { statusCode: 200 }),
52
- respond: (json) => callback(null, {
53
- statusCode: 200,
54
- body: json,
55
- }),
56
- }),
57
- // please open a PR if you want to add another
58
- };
11
+ const adapters = { ...frameworks_node_js_1.adapters, callback: callbackAdapter };
59
12
  /**
60
13
  * Creates a callback function that you can pass to a web framework (such as
61
14
  * express) if you want to run your bot via webhooks. Use it like this:
@@ -75,21 +28,14 @@ const frameworkAdapters = {
75
28
  * @param onTimeout An optional strategy to handle timeouts (default: 'throw')
76
29
  * @param timeoutMilliseconds An optional number of timeout milliseconds (default: 10_000)
77
30
  */
78
- function webhookCallback(bot, framework = "express", onTimeout = "throw", timeoutMilliseconds = 10000) {
79
- var _a;
80
- const server = (_a = frameworkAdapters[framework]) !== null && _a !== void 0 ? _a : standard;
31
+ function webhookCallback(bot, adapter = frameworks_node_js_1.defaultAdapter, onTimeout = "throw", timeoutMilliseconds = 10000) {
81
32
  let firstUpdate = true;
82
33
  let initialized = false;
83
34
  let initCall;
35
+ const server = typeof adapter === "string"
36
+ ? adapters[adapter]
37
+ : adapter;
84
38
  return async (...args) => {
85
- const { update, respond, end } = server(...args);
86
- let usedWebhookReply = false;
87
- const webhookReplyEnvelope = {
88
- send: async (json) => {
89
- usedWebhookReply = true;
90
- await respond(json);
91
- },
92
- };
93
39
  if (!initialized) {
94
40
  if (firstUpdate) {
95
41
  initCall = bot.init();
@@ -98,11 +44,20 @@ function webhookCallback(bot, framework = "express", onTimeout = "throw", timeou
98
44
  await initCall;
99
45
  initialized = true;
100
46
  }
47
+ const { update, respond, end, handlerReturn } = server(...args);
48
+ let usedWebhookReply = false;
49
+ const webhookReplyEnvelope = {
50
+ async send(json) {
51
+ usedWebhookReply = true;
52
+ await respond(json);
53
+ },
54
+ };
101
55
  await timeoutIfNecessary(bot.handleUpdate(await update, webhookReplyEnvelope), typeof onTimeout === "function"
102
56
  ? () => onTimeout(...args)
103
57
  : onTimeout, timeoutMilliseconds);
104
58
  if (end !== undefined && !usedWebhookReply)
105
59
  end();
60
+ return handlerReturn;
106
61
  };
107
62
  }
108
63
  exports.webhookCallback = webhookCallback;
@@ -11,7 +11,7 @@ function concatTransformer(prev, trans) {
11
11
  }
12
12
  class ApiClient {
13
13
  constructor(token, options = {}, webhookReplyEnvelope = {}) {
14
- var _a, _b, _c, _d, _e;
14
+ var _a, _b, _c, _d;
15
15
  Object.defineProperty(this, "token", {
16
16
  enumerable: true,
17
17
  configurable: true,
@@ -57,7 +57,6 @@ 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
61
60
  return { ok: true, result: true };
62
61
  }
63
62
  else {
@@ -86,12 +85,16 @@ class ApiClient {
86
85
  }
87
86
  }
88
87
  });
88
+ const apiRoot = (_a = options.apiRoot) !== null && _a !== void 0 ? _a : "https://api.telegram.org";
89
89
  this.options = {
90
- apiRoot: (_a = options.apiRoot) !== null && _a !== void 0 ? _a : "https://api.telegram.org",
90
+ apiRoot,
91
91
  buildUrl: (_b = options.buildUrl) !== null && _b !== void 0 ? _b : ((root, token, method) => `${root}/bot${token}/${method}`),
92
- baseFetchConfig: (_c = options.baseFetchConfig) !== null && _c !== void 0 ? _c : platform_node_js_1.baseFetchConfig,
93
- canUseWebhookReply: (_d = options.canUseWebhookReply) !== null && _d !== void 0 ? _d : (() => false),
94
- sensitiveLogs: (_e = options.sensitiveLogs) !== null && _e !== void 0 ? _e : false,
92
+ baseFetchConfig: {
93
+ ...(0, platform_node_js_1.baseFetchConfig)(apiRoot),
94
+ ...options.baseFetchConfig,
95
+ },
96
+ canUseWebhookReply: (_c = options.canUseWebhookReply) !== null && _c !== void 0 ? _c : (() => false),
97
+ sensitiveLogs: (_d = options.sensitiveLogs) !== null && _d !== void 0 ? _d : false,
95
98
  };
96
99
  if (this.options.apiRoot.endsWith("/")) {
97
100
  throw new Error(`Remove the trailing '/' from the 'apiRoot' option (use '${this.options.apiRoot.substr(0, this.options.apiRoot.length - 1)}' instead of '${this.options.apiRoot}')`);
@@ -154,8 +154,7 @@ function valuePart(key, value) {
154
154
  }
155
155
  /** Turns an InputFile into a generator of `Uint8Array`s */
156
156
  async function* filePart(id, origin, input) {
157
- var _a;
158
- const filename = (_a = input.filename) !== null && _a !== void 0 ? _a : `${origin}.${getExt(origin)}`;
157
+ const filename = input.filename || `${origin}.${getExt(origin)}`;
159
158
  if (filename.includes("\r") || filename.includes("\n")) {
160
159
  throw new Error(`File paths cannot contain carriage-return (\\r) \
161
160
  or newline (\\n) characters! Filename for property '${origin}' was:
@@ -164,14 +163,11 @@ ${filename}
164
163
  """`);
165
164
  }
166
165
  yield enc.encode(`content-disposition:form-data;name="${id}";filename=${filename}\r\n\r\n`);
167
- const fileData = input[platform_node_js_1.inputFileData];
168
- // handle buffers, file paths, and streams:
169
- if (fileData instanceof Uint8Array)
170
- yield fileData;
171
- else if (typeof fileData === "string")
172
- yield* await (0, platform_node_js_1.streamFile)(fileData);
166
+ const data = await input[platform_node_js_1.toRaw]();
167
+ if (data instanceof Uint8Array)
168
+ yield data;
173
169
  else
174
- yield* fileData;
170
+ yield* data;
175
171
  }
176
172
  /** Returns the default file extension for an API property name */
177
173
  function getExt(key) {
@@ -1,16 +1,23 @@
1
1
  /// <reference types="node" />
2
2
  import { InputFileProxy } from "@grammyjs/types";
3
- import { Agent } from "https";
3
+ import { Agent as HttpAgent } from "http";
4
+ import { Agent as HttpsAgent } from "https";
4
5
  import { Readable } from "stream";
5
6
  import type { ReadStream } from "fs";
6
7
  import { URL } from "url";
7
8
  export * from "@grammyjs/types";
8
- export { debug } from "debug";
9
+ import { debug as d } from "debug";
10
+ export { d as debug };
9
11
  export declare const itrToStream: (itr: AsyncIterable<Uint8Array>) => Readable;
10
- export { createReadStream as streamFile } from "fs";
11
- export declare const baseFetchConfig: {
12
+ export declare function baseFetchConfig(apiRoot: string): {
12
13
  compress: boolean;
13
- agent: Agent;
14
+ agent: HttpsAgent;
15
+ } | {
16
+ agent: HttpAgent;
17
+ compress?: undefined;
18
+ } | {
19
+ compress?: undefined;
20
+ agent?: undefined;
14
21
  };
15
22
  /** Something that looks like a URL. */
16
23
  interface URLLike {
@@ -20,7 +27,7 @@ interface URLLike {
20
27
  */
21
28
  url: string;
22
29
  }
23
- export declare const inputFileData: unique symbol;
30
+ export declare const toRaw: unique symbol;
24
31
  /**
25
32
  * An `InputFile` wraps a number of different sources for [sending
26
33
  * files](https://grammy.dev/guide/files.html#uploading-your-own-file).
@@ -45,8 +52,9 @@ export declare class InputFile {
45
52
  * @param file A path to a local file or a `Buffer` or a `fs.ReadStream` that specifies the file data
46
53
  * @param filename Optional name of the file
47
54
  */
48
- constructor(file: string | URL | URLLike | Uint8Array | ReadStream | AsyncIterable<Uint8Array>, filename?: string);
49
- get [inputFileData](): string | Uint8Array | AsyncIterable<Uint8Array> | ReadStream;
55
+ constructor(file: string | URL | URLLike | Uint8Array | ReadStream | Iterable<Uint8Array> | AsyncIterable<Uint8Array>, filename?: string);
56
+ private guessFilename;
57
+ [toRaw](): Uint8Array | Iterable<Uint8Array> | AsyncIterable<Uint8Array>;
50
58
  }
51
59
  declare type GrammyTypes = InputFileProxy<InputFile>;
52
60
  /** Wrapper type to bundle all methods of the Telegram API */
@@ -10,31 +10,38 @@ 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
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.InputFile = exports.inputFileData = exports.baseFetchConfig = exports.streamFile = exports.itrToStream = exports.debug = void 0;
13
+ exports.InputFile = exports.toRaw = exports.baseFetchConfig = exports.itrToStream = exports.debug = void 0;
14
+ const http_1 = require("http");
14
15
  const https_1 = require("https");
15
16
  const path_1 = require("path");
16
17
  const stream_1 = require("stream");
17
18
  const url_1 = require("url");
19
+ const fs_1 = require("fs");
18
20
  // === Export all API types
19
21
  __exportStar(require("@grammyjs/types"), exports);
20
22
  // === Export debug
21
- var debug_1 = require("debug");
23
+ const debug_1 = require("debug");
22
24
  Object.defineProperty(exports, "debug", { enumerable: true, get: function () { return debug_1.debug; } });
25
+ const debug = (0, debug_1.debug)("grammy:warn");
23
26
  // === Export system-specific operations
24
27
  // Turn an AsyncIterable<Uint8Array> into a stream
25
28
  const itrToStream = (itr) => stream_1.Readable.from(itr, { objectMode: false });
26
29
  exports.itrToStream = itrToStream;
27
- // Turn a file path into an AsyncIterable<Uint8Array>
28
- var fs_1 = require("fs");
29
- Object.defineProperty(exports, "streamFile", { enumerable: true, get: function () { return fs_1.createReadStream; } });
30
30
  // === Base configuration for `fetch` calls
31
- exports.baseFetchConfig = {
32
- compress: true,
33
- agent: new https_1.Agent({ keepAlive: true }),
34
- };
31
+ function baseFetchConfig(apiRoot) {
32
+ if (apiRoot.startsWith("https:")) {
33
+ return { compress: true, agent: new https_1.Agent({ keepAlive: true }) };
34
+ }
35
+ else if (apiRoot.startsWith("http:")) {
36
+ return { agent: new http_1.Agent({ keepAlive: true }) };
37
+ }
38
+ else
39
+ return {};
40
+ }
41
+ exports.baseFetchConfig = baseFetchConfig;
35
42
  // === InputFile handling and File augmenting
36
43
  // Accessor for file data in `InputFile` instances
37
- exports.inputFileData = Symbol("InputFile data");
44
+ exports.toRaw = Symbol("InputFile data");
38
45
  /**
39
46
  * An `InputFile` wraps a number of different sources for [sending
40
47
  * files](https://grammy.dev/guide/files.html#uploading-your-own-file).
@@ -76,31 +83,50 @@ class InputFile {
76
83
  value: void 0
77
84
  });
78
85
  this.fileData = file;
79
- if (filename === undefined && typeof file === "string") {
80
- filename = (0, path_1.basename)(file);
81
- }
86
+ filename !== null && filename !== void 0 ? filename : (filename = this.guessFilename(file));
82
87
  this.filename = filename;
88
+ if (typeof file === "string" &&
89
+ (file.startsWith("http:") || file.startsWith("https:"))) {
90
+ debug(`InputFile received the local file path '${file}' that looks like a URL. Is this a mistake?`);
91
+ }
92
+ }
93
+ guessFilename(file) {
94
+ if (typeof file === "string")
95
+ return (0, path_1.basename)(file);
96
+ if (typeof file !== "object")
97
+ return undefined;
98
+ if ("url" in file)
99
+ return (0, path_1.basename)(file.url);
100
+ if (!(file instanceof url_1.URL))
101
+ return undefined;
102
+ return (0, path_1.basename)(file.pathname) || (0, path_1.basename)(file.hostname);
83
103
  }
84
- get [exports.inputFileData]() {
104
+ [exports.toRaw]() {
85
105
  if (this.consumed) {
86
106
  throw new Error("Cannot reuse InputFile data source!");
87
107
  }
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;
108
+ const data = this.fileData;
109
+ // Handle local files
110
+ if (typeof data === "string")
111
+ return (0, fs_1.createReadStream)(data);
112
+ // Handle URLs and URLLike objects
113
+ if (data instanceof url_1.URL) {
114
+ return data.protocol === "file" // node-fetch does not support file URLs
115
+ ? (0, fs_1.createReadStream)(data.pathname)
116
+ : fetchFile(data);
94
117
  }
118
+ if ("url" in data)
119
+ return fetchFile(data.url);
120
+ // Mark streams and iterators as consumed
121
+ if (!(data instanceof Uint8Array))
122
+ this.consumed = true;
123
+ // Return buffers and byte streams as-is
95
124
  return data;
96
125
  }
97
126
  }
98
127
  exports.InputFile = InputFile;
99
128
  async function* fetchFile(url) {
100
129
  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
130
  for await (const chunk of body) {
105
131
  if (typeof chunk === "string") {
106
132
  throw new Error(`Could not transfer file, received string data instead of bytes from '${url}'`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "grammy",
3
- "description": "grammY core package ported to Node.js",
4
- "version": "1.4.2",
3
+ "description": "The Telegram Bot Framework.",
4
+ "version": "1.4.3",
5
5
  "author": "KnorpelSenf",
6
6
  "license": "MIT",
7
7
  "engines": {
@@ -18,18 +18,21 @@
18
18
  "lint": "deno lint --config deno.json",
19
19
  "fmt": "deno fmt --config deno.json",
20
20
  "test": "deno test ./test/",
21
- "backport": "deno2node tsconfig.json"
21
+ "bundle": "cd bundling && ./bundle-all.sh",
22
+ "backport": "deno2node tsconfig.json",
23
+ "contribs": "all-contributors"
22
24
  },
23
25
  "dependencies": {
24
26
  "@grammyjs/types": "^2.3.1",
25
27
  "abort-controller": "^3.0.0",
26
- "debug": "^4.3.2",
28
+ "debug": "^4.3.3",
27
29
  "node-fetch": "^2.6.5"
28
30
  },
29
31
  "devDependencies": {
30
32
  "@types/debug": "^4.1.7",
31
- "@types/node": "^12.20.33",
33
+ "@types/node": "^12.20.36",
32
34
  "@types/node-fetch": "^2.5.12",
35
+ "all-contributors-cli": "^6.20.0",
33
36
  "deno2node": "^1.0.0"
34
37
  },
35
38
  "files": [
@@ -40,6 +43,10 @@
40
43
  "keywords": [
41
44
  "telegram",
42
45
  "bot",
43
- "api"
46
+ "api",
47
+ "client",
48
+ "framework",
49
+ "library",
50
+ "grammy"
44
51
  ]
45
52
  }