initial commit
This commit is contained in:
21
node_modules/grammy/LICENSE
generated
vendored
Normal file
21
node_modules/grammy/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-2023 KnorpelSenf
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
290
node_modules/grammy/README.md
generated
vendored
Normal file
290
node_modules/grammy/README.md
generated
vendored
Normal file
@ -0,0 +1,290 @@
|
||||
<div align="center"><a href="https://grammy.dev"><img src="https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png" alt="grammY"></a></h1></div>
|
||||
|
||||
<div align="right">
|
||||
|
||||
# The Telegram Bot Framework.
|
||||
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
|
||||
<!-- deno-fmt-ignore-start -->
|
||||
|
||||
[](https://core.telegram.org/bots/api)
|
||||
[](https://deno.land/x/grammy)
|
||||
[](https://www.npmjs.org/package/grammy)
|
||||
[](#contributors-)
|
||||
|
||||
<!-- deno-fmt-ignore-end -->
|
||||
|
||||
## _[docs.](https://grammy.dev) [reference.](https://deno.land/x/grammy/mod.ts) [chat.](https://telegram.me/grammyjs) [news.](https://telegram.me/grammyjs_news)_
|
||||
|
||||
</div>
|
||||
|
||||
**grammY makes it easy to create Telegram bots.** Both for beginners and at scale.
|
||||
|
||||
You want grammY because it is easy to use. It is very powerful and always up to date. It has the best [documentation](https://grammy.dev) in town. It is extremely efficient and scales up effortlessly. It has a thriving ecosystem of plugins, a friendly community chat, seamless integrations with web frameworks and databases, and so much more.
|
||||
|
||||
Are you ready? 🤖🚀
|
||||
|
||||
Bots are written in [TypeScript](https://www.typescriptlang.org/) (or JavaScript) and run on [Node.js](https://nodejs.org/) or [Deno](#deno-support).
|
||||
|
||||
## Quickstart
|
||||
|
||||
> If you are new to Telegram bots, read the official [Introduction for Developers](https://core.telegram.org/bots) written by the Telegram team.
|
||||
|
||||
Visit [@BotFather](https://t.me/BotFather) and create a new bot. You will obtain a **bot token**.
|
||||
|
||||
Create a new directory and run
|
||||
|
||||
```bash
|
||||
npm install grammy
|
||||
```
|
||||
|
||||
inside it. Then create a file `bot.js` with this content:
|
||||
|
||||
```ts
|
||||
const { Bot } = require("grammy");
|
||||
|
||||
// Create a bot object
|
||||
const bot = new Bot(""); // <-- place your bot token in this string
|
||||
|
||||
// Register listeners to handle messages
|
||||
bot.on("message:text", (ctx) => ctx.reply("Echo: " + ctx.message.text));
|
||||
|
||||
// Start the bot (using long polling)
|
||||
bot.start();
|
||||
```
|
||||
|
||||
Now you can run the bot via
|
||||
|
||||
```bash
|
||||
node bot.js
|
||||
```
|
||||
|
||||
and it will echo all received text messages.
|
||||
|
||||
Congrats! You just wrote a Telegram bot :)
|
||||
|
||||
## Going Further
|
||||
|
||||
grammY has an excellent [documentation](https://grammy.dev), and an [API Reference](https://doc.deno.land/https://deno.land/x/grammy/mod.ts). It even integrates with your code editor, e.g. [VS Code](https://code.visualstudio.com/). You can hover over any element of grammY to get a detailed description of what that thing does or means.
|
||||
|
||||
If you are still stuck, just join the [Telegram chat](https://t.me/grammyjs) and ask for help. People are nice there and we appreciate your question, no matter what it is :)
|
||||
|
||||
Here are some more resources to support you:
|
||||
|
||||
## Resources
|
||||
|
||||
### [grammY website](https://grammy.dev)
|
||||
|
||||
—main project website and documentation.
|
||||
Gets you started and explains all concepts.
|
||||
|
||||
### [grammY API reference](https://doc.deno.land/https://deno.land/x/grammy/mod.ts)
|
||||
|
||||
—reference of everything that grammY exports.
|
||||
Useful to look up descriptions about any element of grammY.
|
||||
|
||||
### [grammY examples](https://github.com/grammyjs/examples)
|
||||
|
||||
—repository full of example bots.
|
||||
Includes a setup to easily run any of them.
|
||||
|
||||
### [Awesome grammY](https://github.com/grammyjs/awesome-grammY)
|
||||
|
||||
—list of awesome projects built with grammY.
|
||||
Helpful if you want to see some real-world usage.
|
||||
|
||||
### [grammY chat](https://t.me/grammyjs)
|
||||
|
||||
—The chat where you can ask any question about grammY or bots in general.
|
||||
We are also open for feedback, ideas, and contributions!
|
||||
|
||||
The Russian community chat can be found [here](https://t.me/grammyjs_ru).
|
||||
|
||||
### [grammY news](https://t.me/grammyjs_news)
|
||||
|
||||
—The channel where updates to grammY and the ecosystem are posted.
|
||||
We are also [on Twitter](https://twitter.com/grammy_js).
|
||||
|
||||
### [Telegram Bot API Reference](https://core.telegram.org/bots/api)
|
||||
|
||||
—documentation of the API that Telegram offers, and that grammY connects to under the hood.
|
||||
|
||||
## Deno Support
|
||||
|
||||
All grammY packages published by [@grammyjs](https://github.com/grammyjs) run natively on [Deno](https://deno.land). We are compiling every codebase to still run on Node.js.
|
||||
|
||||
However, given that most bot developers are still using Node.js, all documentation is written Node.js-first. We may migrate it if Deno overtakes Node.js. If you are already on Deno today, import grammY from [`https://deno.land/x/grammy/mod.ts`](https://deno.land/x/grammy).
|
||||
|
||||
You may also be interested in [why we support Deno](https://grammy.dev/resources/faq.html#why-do-you-support-deno).
|
||||
|
||||
## JavaScript Bundles
|
||||
|
||||
The grammY core package in this repository is available as a JavaScript bundle via <https://bundle.deno.dev/>.
|
||||
This lets you transpile all published versions including current `main` branch to standalone JavaScript files.
|
||||
For example, the most recent source on `main` is available from <https://bundle.deno.dev/https://raw.githubusercontent.com/grammyjs/grammY/main/src/mod.ts>.
|
||||
|
||||
Being compatible with browsers is especially useful for running bots on Cloudflare Workers.
|
||||
For this reason, we also include a web bundle in our npm package.
|
||||
You can simply do `import { Bot } from "grammy/web"`.
|
||||
|
||||
## [Contribution Guide »](./CONTRIBUTING.md)
|
||||
|
||||
## Contributors ✨
|
||||
|
||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/KnorpelSenf"><img src="https://avatars.githubusercontent.com/u/12952387?v=4?s=100" width="100px;" alt="KnorpelSenf"/><br /><sub><b>KnorpelSenf</b></sub></a><br /><a href="#ideas-KnorpelSenf" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/commits?author=KnorpelSenf" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/commits?author=KnorpelSenf" title="Documentation">📖</a> <a href="#design-KnorpelSenf" title="Design">🎨</a> <a href="#example-KnorpelSenf" title="Examples">💡</a> <a href="https://github.com/grammyjs/grammY/commits?author=KnorpelSenf" title="Tests">⚠️</a> <a href="#plugin-KnorpelSenf" title="Plugin/utility libraries">🔌</a> <a href="#platform-KnorpelSenf" title="Packaging/porting to new platform">📦</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AKnorpelSenf" title="Reviewed Pull Requests">👀</a> <a href="#mentoring-KnorpelSenf" title="Mentoring">🧑🏫</a> <a href="#projectManagement-KnorpelSenf" title="Project Management">📆</a> <a href="#infra-KnorpelSenf" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#audio-KnorpelSenf" title="Audio">🔊</a> <a href="#a11y-KnorpelSenf" title="Accessibility">️️️️♿️</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/HeeroML"><img src="https://avatars.githubusercontent.com/u/42873000?v=4?s=100" width="100px;" alt="Heero"/><br /><sub><b>Heero</b></sub></a><br /><a href="#plugin-HeeroML" title="Plugin/utility libraries">🔌</a> <a href="#userTesting-HeeroML" title="User Testing">📓</a> <a href="#example-HeeroML" title="Examples">💡</a> <a href="https://github.com/grammyjs/grammY/commits?author=HeeroML" title="Documentation">📖</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AHeeroML" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/commits?author=HeeroML" title="Code">💻</a> <a href="#ideas-HeeroML" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/wojpawlik"><img src="https://avatars.githubusercontent.com/u/23058303?v=4?s=100" width="100px;" alt="Wojciech Pawlik"/><br /><sub><b>Wojciech Pawlik</b></sub></a><br /><a href="#ideas-wojpawlik" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Awojpawlik" title="Reviewed Pull Requests">👀</a> <a href="#infra-wojpawlik" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#platform-wojpawlik" title="Packaging/porting to new platform">📦</a> <a href="#tool-wojpawlik" title="Tools">🔧</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/MegaITA"><img src="https://avatars.githubusercontent.com/u/32493080?v=4?s=100" width="100px;" alt="Alessandro Bertozzi"/><br /><sub><b>Alessandro Bertozzi</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=MegaITA" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://trgwii.no/"><img src="https://avatars.githubusercontent.com/u/11262022?v=4?s=100" width="100px;" alt="trgwii"/><br /><sub><b>trgwii</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=trgwii" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Atrgwii" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/KnightNiwrem"><img src="https://avatars.githubusercontent.com/u/9781814?v=4?s=100" width="100px;" alt="KnightNiwrem"/><br /><sub><b>KnightNiwrem</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=KnightNiwrem" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3AKnightNiwrem" title="Bug reports">🐛</a> <a href="#plugin-KnightNiwrem" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/grammyjs/grammY/commits?author=KnightNiwrem" title="Documentation">📖</a> <a href="#example-KnightNiwrem" title="Examples">💡</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AKnightNiwrem" title="Reviewed Pull Requests">👀</a> <a href="#mentoring-KnightNiwrem" title="Mentoring">🧑🏫</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://mkr.pw"><img src="https://avatars.githubusercontent.com/u/19621208?v=4?s=100" width="100px;" alt="Muthu Kumar"/><br /><sub><b>Muthu Kumar</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AMKRhere" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://edjopato.de/"><img src="https://avatars.githubusercontent.com/u/7953011?v=4?s=100" width="100px;" alt="EdJoPaTo"/><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></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Amir-Zouerami"><img src="https://avatars.githubusercontent.com/u/53701884?v=4?s=100" width="100px;" alt="Amir Zouerami"/><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> <a href="#example-Amir-Zouerami" title="Examples">💡</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/roj1512"><img src="https://avatars.githubusercontent.com/u/49933115?v=4?s=100" width="100px;" alt="Roj"/><br /><sub><b>Roj</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=roj1512" title="Documentation">📖</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Aroj1512" title="Reviewed Pull Requests">👀</a> <a href="#infra-roj1512" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#translation-roj1512" title="Translation">🌍</a> <a href="https://github.com/grammyjs/grammY/commits?author=roj1512" title="Code">💻</a> <a href="#ideas-roj1512" title="Ideas, Planning, & Feedback">🤔</a> <a href="#mentoring-roj1512" title="Mentoring">🧑🏫</a> <a href="#example-roj1512" title="Examples">💡</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/jokasimr"><img src="https://avatars.githubusercontent.com/u/20954731?v=4?s=100" width="100px;" alt="jokasimr"/><br /><sub><b>jokasimr</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Ajokasimr" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/CikiMomogi"><img src="https://avatars.githubusercontent.com/u/74030149?v=4?s=100" width="100px;" alt="Ciki Momogi"/><br /><sub><b>Ciki Momogi</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=CikiMomogi" title="Documentation">📖</a> <a href="#translation-CikiMomogi" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/AndreoliBR"><img src="https://avatars.githubusercontent.com/u/15970011?v=4?s=100" width="100px;" alt="AndreoliBR"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Loskir"><img src="https://avatars.githubusercontent.com/u/21295738?v=4?s=100" width="100px;" alt="Kirill Loskutov"/><br /><sub><b>Kirill Loskutov</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Loskir" title="Documentation">📖</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3ALoskir" title="Bug reports">🐛</a> <a href="#ideas-Loskir" title="Ideas, Planning, & Feedback">🤔</a> <a href="#design-Loskir" title="Design">🎨</a> <a href="#question-Loskir" title="Answering Questions">💬</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3ALoskir" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/commits?author=Loskir" title="Code">💻</a> <a href="#plugin-Loskir" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://lungers.com/"><img src="https://avatars.githubusercontent.com/u/32808683?v=4?s=100" width="100px;" alt="Andrew Lane"/><br /><sub><b>Andrew Lane</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3AAndrewLaneX" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AAndrewLaneX" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/code-withAshish"><img src="https://avatars.githubusercontent.com/u/73625149?v=4?s=100" width="100px;" alt="code-withAshish"/><br /><sub><b>code-withAshish</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=code-withAshish" title="Documentation">📖</a> <a href="#question-code-withAshish" title="Answering Questions">💬</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3Acode-withAshish" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Acode-withAshish" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://beta.ku-di.com/waptik"><img src="https://avatars.githubusercontent.com/u/1687551?v=4?s=100" width="100px;" alt="Stephane Mensah"/><br /><sub><b>Stephane Mensah</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Awaptik" title="Bug reports">🐛</a> <a href="#plugin-waptik" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Asaku01"><img src="https://avatars.githubusercontent.com/u/29716396?v=4?s=100" width="100px;" alt="Asaku01"/><br /><sub><b>Asaku01</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Asaku01" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/ppsimn"><img src="https://avatars.githubusercontent.com/u/88509883?v=4?s=100" width="100px;" alt="ppsimn"/><br /><sub><b>ppsimn</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Appsimn" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://satont.js.org/"><img src="https://avatars.githubusercontent.com/u/42675886?v=4?s=100" width="100px;" alt="Satont"/><br /><sub><b>Satont</b></sub></a><br /><a href="#plugin-Satont" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/grammyjs/grammY/commits?author=Satont" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/deptyped"><img src="https://avatars.githubusercontent.com/u/26162440?v=4?s=100" width="100px;" alt="deptyped"/><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="https://github.com/grammyjs/grammY/issues?q=author%3Adeptyped" title="Bug reports">🐛</a> <a href="#translation-deptyped" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/dzek69"><img src="https://avatars.githubusercontent.com/u/4936805?v=4?s=100" width="100px;" alt="Jacek Nowacki"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://blog.outv.im"><img src="https://avatars.githubusercontent.com/u/19144373?v=4?s=100" width="100px;" alt="Outvi V"/><br /><sub><b>Outvi V</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=outloudvi" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=eltociear" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/amberlionk"><img src="https://avatars.githubusercontent.com/u/29119723?v=4?s=100" width="100px;" alt="Yevhen Denesiuk"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/prazedotid"><img src="https://avatars.githubusercontent.com/u/19567624?v=4?s=100" width="100px;" alt="prastian"/><br /><sub><b>prastian</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aprazedotid" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=prazedotid" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://sayem.eu.org/"><img src="https://avatars.githubusercontent.com/u/14138401?v=4?s=100" width="100px;" alt="Sayem Chowdhury"/><br /><sub><b>Sayem Chowdhury</b></sub></a><br /><a href="#ideas-sayem314" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/kospra"><img src="https://avatars.githubusercontent.com/u/42740406?v=4?s=100" width="100px;" alt="kospra"/><br /><sub><b>kospra</b></sub></a><br /><a href="#ideas-kospra" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/commits?author=kospra" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/chimit"><img src="https://avatars.githubusercontent.com/u/839349?v=4?s=100" width="100px;" alt="Chimit"/><br /><sub><b>Chimit</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=chimit" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/CalsiBotDev"><img src="https://avatars.githubusercontent.com/u/55633371?v=4?s=100" width="100px;" alt="Calsi"/><br /><sub><b>Calsi</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=CalsiBotDev" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://zohren.xyz"><img src="https://avatars.githubusercontent.com/u/15788906?v=4?s=100" width="100px;" alt="Jonas Zohren"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://zhemu.buzz/"><img src="https://avatars.githubusercontent.com/u/56839018?v=4?s=100" width="100px;" alt="linbuxiao"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/JiquanWang99"><img src="https://avatars.githubusercontent.com/u/63894579?v=4?s=100" width="100px;" alt="JiquanWang99"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://bor691.ir/"><img src="https://avatars.githubusercontent.com/u/4184939?v=4?s=100" width="100px;" alt="Borhan Hafez"/><br /><sub><b>Borhan Hafez</b></sub></a><br /><a href="#plugin-zumoshi" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://blog.limx.dev/"><img src="https://avatars.githubusercontent.com/u/6434137?v=4?s=100" width="100px;" alt="WingLim"/><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> <a href="https://github.com/grammyjs/grammY/commits?author=WingLim" title="Code">💻</a> <a href="#plugin-WingLim" title="Plugin/utility libraries">🔌</a> <a href="#ideas-WingLim" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/taotie111"><img src="https://avatars.githubusercontent.com/u/44166322?v=4?s=100" width="100px;" alt="taotie111"/><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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><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="Merlin"/><br /><sub><b>Merlin</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=FatalMerlin" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://darve.sh"><img src="https://avatars.githubusercontent.com/u/22394081?v=4?s=100" width="100px;" alt="Darvesh"/><br /><sub><b>Darvesh</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Adarvesh" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=darvesh" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Adarvesh" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://telegram.me/dcdunkan"><img src="https://avatars.githubusercontent.com/u/70066170?v=4?s=100" width="100px;" alt="dcdunkan"/><br /><sub><b>dcdunkan</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Adcdunkan" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=dcdunkan" title="Code">💻</a> <a href="#plugin-dcdunkan" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Adcdunkan" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/commits?author=dcdunkan" title="Documentation">📖</a> <a href="#ideas-dcdunkan" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-dcdunkan" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#tool-dcdunkan" title="Tools">🔧</a> <a href="#mentoring-dcdunkan" title="Mentoring">🧑🏫</a> <a href="#maintenance-dcdunkan" title="Maintenance">🚧</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://xuann.wang/"><img src="https://avatars.githubusercontent.com/u/44045911?v=4?s=100" width="100px;" alt="Kid"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://slava.fomin.io/"><img src="https://avatars.githubusercontent.com/u/1702725?v=4?s=100" width="100px;" alt="Slava Fomin II"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://kikobeats.com/"><img src="https://avatars.githubusercontent.com/u/2096101?v=4?s=100" width="100px;" alt="Kiko Beats"/><br /><sub><b>Kiko Beats</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Kikobeats" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////kraftwerk28.pp.ua"><img src="https://avatars.githubusercontent.com/u/31807671?v=4?s=100" width="100px;" alt="Vsevolod"/><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>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/habemuscode"><img src="https://avatars.githubusercontent.com/u/34692207?v=4?s=100" width="100px;" alt="Habemuscode"/><br /><sub><b>Habemuscode</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Ahabemuscode" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/commits?author=habemuscode" title="Documentation">📖</a> <a href="#translation-habemuscode" title="Translation">🌍</a> <a href="#maintenance-habemuscode" title="Maintenance">🚧</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://borodutch.com/"><img src="https://avatars.githubusercontent.com/u/3192028?v=4?s=100" width="100px;" alt="Nikita Kolmogorov"/><br /><sub><b>Nikita Kolmogorov</b></sub></a><br /><a href="#plugin-backmeupplz" title="Plugin/utility libraries">🔌</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://glukki.ru"><img src="https://avatars.githubusercontent.com/u/140462?v=4?s=100" width="100px;" alt="Vitaliy Meshchaninov"/><br /><sub><b>Vitaliy Meshchaninov</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aglukki" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=glukki" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/dilyanpalauzov"><img src="https://avatars.githubusercontent.com/u/4992947?v=4?s=100" width="100px;" alt="Дилян Палаузов"/><br /><sub><b>Дилян Палаузов</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Adilyanpalauzov" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=dilyanpalauzov" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/lmx-Hexagram"><img src="https://avatars.githubusercontent.com/u/52130356?v=4?s=100" width="100px;" alt="lmx-Hexagram"/><br /><sub><b>lmx-Hexagram</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=lmx-Hexagram" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/IlyaSemenov"><img src="https://avatars.githubusercontent.com/u/128121?v=4?s=100" width="100px;" alt="Ilya Semenov"/><br /><sub><b>Ilya Semenov</b></sub></a><br /><a href="#ideas-IlyaSemenov" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AIlyaSemenov" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/commits?author=IlyaSemenov" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/abdollahzadehAli"><img src="https://avatars.githubusercontent.com/u/96317431?v=4?s=100" width="100px;" alt="abdollahzadehAli"/><br /><sub><b>abdollahzadehAli</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=abdollahzadehAli" title="Documentation">📖</a> <a href="#example-abdollahzadehAli" title="Examples">💡</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/MrSaeedNasiri"><img src="https://avatars.githubusercontent.com/u/17780289?v=4?s=100" width="100px;" alt="Saeed Nasiri"/><br /><sub><b>Saeed Nasiri</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=MrSaeedNasiri" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Scrip7"><img src="https://avatars.githubusercontent.com/u/37535505?v=4?s=100" width="100px;" alt="Hesoyam"/><br /><sub><b>Hesoyam</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Scrip7" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://yrz.am"><img src="https://avatars.githubusercontent.com/u/96742416?v=4?s=100" width="100px;" alt="yrzam"/><br /><sub><b>yrzam</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Ayrzam" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/drmikecrowe"><img src="https://avatars.githubusercontent.com/u/90312?v=4?s=100" width="100px;" alt="drmikecrowe"/><br /><sub><b>drmikecrowe</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Adrmikecrowe" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://rys.pw"><img src="https://avatars.githubusercontent.com/u/1641362?v=4?s=100" width="100px;" alt="Martin"/><br /><sub><b>Martin</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=C0rn3j" title="Documentation">📖</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3AC0rn3j" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AC0rn3j" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://pavelpolyakov.com/"><img src="https://avatars.githubusercontent.com/u/839290?v=4?s=100" width="100px;" alt="Pavel"/><br /><sub><b>Pavel</b></sub></a><br /><a href="#example-PavelPolyakov" title="Examples">💡</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://youtube.com/thorwebdev"><img src="https://avatars.githubusercontent.com/u/5748289?v=4?s=100" width="100px;" alt="Thor 雷神 Schaeff"/><br /><sub><b>Thor 雷神 Schaeff</b></sub></a><br /><a href="#example-thorwebdev" title="Examples">💡</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/x066it"><img src="https://avatars.githubusercontent.com/u/75589380?v=4?s=100" width="100px;" alt="x066it"/><br /><sub><b>x066it</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Ax066it" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Ax066it" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/kolay-v"><img src="https://avatars.githubusercontent.com/u/49853802?v=4?s=100" width="100px;" alt="kolay"/><br /><sub><b>kolay</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Akolay-v" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://enepom.com/"><img src="https://avatars.githubusercontent.com/u/2511553?v=4?s=100" width="100px;" alt="Evgeny Nepomnyashchiy"/><br /><sub><b>Evgeny Nepomnyashchiy</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Apizzaeater" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/anantakrishna"><img src="https://avatars.githubusercontent.com/u/6065071?v=4?s=100" width="100px;" alt="Ananta Krsna dasa"/><br /><sub><b>Ananta Krsna dasa</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=anantakrishna" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Mi3liX9"><img src="https://avatars.githubusercontent.com/u/26169870?v=4?s=100" width="100px;" alt="Mighty Ali"/><br /><sub><b>Mighty Ali</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Mi3liX9" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AMi3liX9" title="Reviewed Pull Requests">👀</a> <a href="#ideas-Mi3liX9" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://oott123.com"><img src="https://avatars.githubusercontent.com/u/905663?v=4?s=100" width="100px;" alt="三三"/><br /><sub><b>三三</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aoott123" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=oott123" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://roz.ninja"><img src="https://avatars.githubusercontent.com/u/3948961?v=4?s=100" width="100px;" alt="Roz"/><br /><sub><b>Roz</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aroziscoding" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=roziscoding" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Aroziscoding" title="Reviewed Pull Requests">👀</a> <a href="#infra-roziscoding" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#ideas-roziscoding" title="Ideas, Planning, & Feedback">🤔</a> <a href="#mentoring-roziscoding" title="Mentoring">🧑🏫</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/daniharo"><img src="https://avatars.githubusercontent.com/u/47931084?v=4?s=100" width="100px;" alt="Dani Haro"/><br /><sub><b>Dani Haro</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=daniharo" title="Code">💻</a> <a href="#plugin-daniharo" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/grammyjs/grammY/commits?author=daniharo" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Ryukaizen"><img src="https://avatars.githubusercontent.com/u/55140313?v=4?s=100" width="100px;" alt="Ryukaizen"/><br /><sub><b>Ryukaizen</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Ryukaizen" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/mcpeblocker"><img src="https://avatars.githubusercontent.com/u/59408255?v=4?s=100" width="100px;" alt="Alisher Ortiqov"/><br /><sub><b>Alisher Ortiqov</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=mcpeblocker" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/tonytkachenko"><img src="https://avatars.githubusercontent.com/u/103267335?v=4?s=100" width="100px;" alt="Tony Tkachenko"/><br /><sub><b>Tony Tkachenko</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=tonytkachenko" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/rainrisa"><img src="https://avatars.githubusercontent.com/u/108156134?v=4?s=100" width="100px;" alt="Ra"/><br /><sub><b>Ra</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=rainrisa" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/sartoshi-foot-dao"><img src="https://avatars.githubusercontent.com/u/99770068?v=4?s=100" width="100px;" alt="sartoshi-foot-dao"/><br /><sub><b>sartoshi-foot-dao</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=sartoshi-foot-dao" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/yn4v4s"><img src="https://avatars.githubusercontent.com/u/35275827?v=4?s=100" width="100px;" alt="Yoel Navas E."/><br /><sub><b>Yoel Navas E.</b></sub></a><br /><a href="#ideas-yn4v4s" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/vitorleo"><img src="https://avatars.githubusercontent.com/u/5118352?v=4?s=100" width="100px;" alt="Vitor Gomes"/><br /><sub><b>Vitor Gomes</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Avitorleo" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=vitorleo" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://xditya.me/"><img src="https://avatars.githubusercontent.com/u/58950863?v=4?s=100" width="100px;" alt="Aditya"/><br /><sub><b>Aditya</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Axditya" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Axditya" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://uditkaro.de"><img src="https://avatars.githubusercontent.com/u/30829387?v=4?s=100" width="100px;" alt="Udit Karode"/><br /><sub><b>Udit Karode</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Auditkarode" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://rockett.pw"><img src="https://avatars.githubusercontent.com/u/4586280?v=4?s=100" width="100px;" alt="Mike Rockétt"/><br /><sub><b>Mike Rockétt</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Amikerockett" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/issues?q=author%3Amikerockett" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/MrVSiK"><img src="https://avatars.githubusercontent.com/u/79159341?v=4?s=100" width="100px;" alt="Srinivasa IK Varanasi"/><br /><sub><b>Srinivasa IK Varanasi</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=MrVSiK" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/abdoo9"><img src="https://avatars.githubusercontent.com/u/63903814?v=4?s=100" width="100px;" alt="abdoo9"/><br /><sub><b>abdoo9</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aabdoo9" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=abdoo9" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="http://ak4zh.com"><img src="https://avatars.githubusercontent.com/u/26350053?v=4?s=100" width="100px;" alt="ak4zh"/><br /><sub><b>ak4zh</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Aak4zh" title="Reviewed Pull Requests">👀</a> <a href="#ideas-ak4zh" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/commits?author=ak4zh" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/nlapshin"><img src="https://avatars.githubusercontent.com/u/39495311?v=4?s=100" width="100px;" alt="Nikolay Lapshin"/><br /><sub><b>Nikolay Lapshin</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=nlapshin" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Aquathing"><img src="https://avatars.githubusercontent.com/u/81624781?v=4?s=100" width="100px;" alt="Aquatica"/><br /><sub><b>Aquatica</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Aquathing" title="Documentation">📖</a> <a href="#question-Aquathing" title="Answering Questions">💬</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/fadzikri"><img src="https://avatars.githubusercontent.com/u/109416385?v=4?s=100" width="100px;" alt="Fa Dzikri"/><br /><sub><b>Fa Dzikri</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Afadzikri" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/grammyjs/grammY/commits?author=fadzikri" title="Documentation">📖</a> <a href="#translation-fadzikri" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/solidprinciples"><img src="https://avatars.githubusercontent.com/u/7939765?v=4?s=100" width="100px;" alt="Chandler Lattin"/><br /><sub><b>Chandler Lattin</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=solidprinciples" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Asolidprinciples" title="Reviewed Pull Requests">👀</a> <a href="#plugin-solidprinciples" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/sparfenyuk"><img src="https://avatars.githubusercontent.com/u/134065?v=4?s=100" width="100px;" alt="Sergey Parfenyuk"/><br /><sub><b>Sergey Parfenyuk</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Asparfenyuk" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/felinto-dev"><img src="https://avatars.githubusercontent.com/u/32253743?v=4?s=100" width="100px;" alt="Émerson Felinto"/><br /><sub><b>Émerson Felinto</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Afelinto-dev" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/stPitty"><img src="https://avatars.githubusercontent.com/u/85024641?v=4?s=100" width="100px;" alt="Petr Stankin"/><br /><sub><b>Petr Stankin</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3AstPitty" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/ByMsx"><img src="https://avatars.githubusercontent.com/u/5565836?v=4?s=100" width="100px;" alt="Maxim Lebedev"/><br /><sub><b>Maxim Lebedev</b></sub></a><br /><a href="#ideas-ByMsx" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/commits?author=ByMsx" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Madnex"><img src="https://avatars.githubusercontent.com/u/14137610?v=4?s=100" width="100px;" alt="Madnex"/><br /><sub><b>Madnex</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Madnex" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/tup4ienko"><img src="https://avatars.githubusercontent.com/u/89318613?v=4?s=100" width="100px;" alt="Svyatoslav Tupchienko"/><br /><sub><b>Svyatoslav Tupchienko</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=tup4ienko" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/evermake"><img src="https://avatars.githubusercontent.com/u/53311479?v=4?s=100" width="100px;" alt="Vladislav Deryabkin"/><br /><sub><b>Vladislav Deryabkin</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aevermake" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=evermake" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Aevermake" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/kashyapndps00"><img src="https://avatars.githubusercontent.com/u/98746601?v=4?s=100" width="100px;" alt="Kashyap Sharma"/><br /><sub><b>Kashyap Sharma</b></sub></a><br /><a href="#example-kashyapndps00" title="Examples">💡</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/AlexOwl"><img src="https://avatars.githubusercontent.com/u/47189254?v=4?s=100" width="100px;" alt="AlexOwl"/><br /><sub><b>AlexOwl</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3AAlexOwl" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=AlexOwl" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://www.shrimadhavuk.me/"><img src="https://avatars.githubusercontent.com/u/6317196?v=4?s=100" width="100px;" alt="Shrimadhav U K"/><br /><sub><b>Shrimadhav U K</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=SpEcHiDe" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/binamralamsal"><img src="https://avatars.githubusercontent.com/u/61900781?v=4?s=100" width="100px;" alt="Binamra Lamsal"/><br /><sub><b>Binamra Lamsal</b></sub></a><br /><a href="#ideas-binamralamsal" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/gertminov"><img src="https://avatars.githubusercontent.com/u/78727928?v=4?s=100" width="100px;" alt="gertminov"/><br /><sub><b>gertminov</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=gertminov" title="Documentation">📖</a> <a href="#tutorial-gertminov" title="Tutorials">✅</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/amanape"><img src="https://avatars.githubusercontent.com/u/83104063?v=4?s=100" width="100px;" alt="Stephan Psaras"/><br /><sub><b>Stephan Psaras</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Aamanape" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/shevernitskiy"><img src="https://avatars.githubusercontent.com/u/28886342?v=4?s=100" width="100px;" alt="shevernitskiy"/><br /><sub><b>shevernitskiy</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Ashevernitskiy" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Ashevernitskiy" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/mrmaster009"><img src="https://avatars.githubusercontent.com/u/81420490?v=4?s=100" width="100px;" alt="mrmaster009"/><br /><sub><b>mrmaster009</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=mrmaster009" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://lwjerri.dev/"><img src="https://avatars.githubusercontent.com/u/50290430?v=4?s=100" width="100px;" alt="Andrey Zontov"/><br /><sub><b>Andrey Zontov</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3ALWJerri" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=LWJerri" title="Code">💻</a> <a href="#question-LWJerri" title="Answering Questions">💬</a> <a href="#ideas-LWJerri" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/commits?author=LWJerri" title="Documentation">📖</a> <a href="#translation-LWJerri" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/AbbassAlmusawi"><img src="https://avatars.githubusercontent.com/u/73327881?v=4?s=100" width="100px;" alt="Abbass Al-Musawi"/><br /><sub><b>Abbass Al-Musawi</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=AbbassAlmusawi" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/inji-gg"><img src="https://avatars.githubusercontent.com/u/5071242?v=4?s=100" width="100px;" alt="ArunR"/><br /><sub><b>ArunR</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Ainji-gg" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=inji-gg" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/ndatg"><img src="https://avatars.githubusercontent.com/u/108090198?v=4?s=100" width="100px;" alt="NDA"/><br /><sub><b>NDA</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Andatg" title="Bug reports">🐛</a> <a href="#ideas-ndatg" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/commits?author=ndatg" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/MatyiFKBT"><img src="https://avatars.githubusercontent.com/u/6183867?v=4?s=100" width="100px;" alt="MatyiFKBT"/><br /><sub><b>MatyiFKBT</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=MatyiFKBT" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://chrisandrew.cl"><img src="https://avatars.githubusercontent.com/u/368831?v=4?s=100" width="100px;" alt="Chris Andrew C. L."/><br /><sub><b>Chris Andrew C. L.</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Achrisandrewcl" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=chrisandrewcl" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Achrisandrewcl" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/kiyasov"><img src="https://avatars.githubusercontent.com/u/16527461?v=4?s=100" width="100px;" alt="Islam Kiiasov"/><br /><sub><b>Islam Kiiasov</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=kiyasov" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/ssistoza"><img src="https://avatars.githubusercontent.com/u/17445445?v=4?s=100" width="100px;" alt="Shane Avery Sistoza"/><br /><sub><b>Shane Avery Sistoza</b></sub></a><br /><a href="#ideas-ssistoza" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/grammyjs/grammY/commits?author=ssistoza" title="Code">💻</a> <a href="https://github.com/grammyjs/grammY/commits?author=ssistoza" title="Tests">⚠️</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/MaicolAntali"><img src="https://avatars.githubusercontent.com/u/79454487?v=4?s=100" width="100px;" alt="Maicol"/><br /><sub><b>Maicol</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=MaicolAntali" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/Nazar-Ant"><img src="https://avatars.githubusercontent.com/u/75927667?v=4?s=100" width="100px;" alt="Nazar Antoniuk"/><br /><sub><b>Nazar Antoniuk</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=Nazar-Ant" title="Documentation">📖</a> <a href="#translation-Nazar-Ant" title="Translation">🌍</a> <a href="#maintenance-Nazar-Ant" title="Maintenance">🚧</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/MajorLettuce"><img src="https://avatars.githubusercontent.com/u/3730149?v=4?s=100" width="100px;" alt="Aleksei Ivanov"/><br /><sub><b>Aleksei Ivanov</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3AMajorLettuce" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/PonomareVlad"><img src="https://avatars.githubusercontent.com/u/2877584?v=4?s=100" width="100px;" alt="Vladislav Ponomarev"/><br /><sub><b>Vladislav Ponomarev</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/commits?author=PonomareVlad" title="Tests">⚠️</a> <a href="https://github.com/grammyjs/grammY/commits?author=PonomareVlad" title="Code">💻</a> <a href="#platform-PonomareVlad" title="Packaging/porting to new platform">📦</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/louietyj"><img src="https://avatars.githubusercontent.com/u/11096034?v=4?s=100" width="100px;" alt="Louie Tan"/><br /><sub><b>Louie Tan</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/pulls?q=is%3Apr+reviewed-by%3Alouietyj" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="11.11%"><a href="https://github.com/lejovaar7"><img src="https://avatars.githubusercontent.com/u/26439842?v=4?s=100" width="100px;" alt="Leandro Vargas"/><br /><sub><b>Leandro Vargas</b></sub></a><br /><a href="https://github.com/grammyjs/grammY/issues?q=author%3Alejovaar7" title="Bug reports">🐛</a> <a href="https://github.com/grammyjs/grammY/commits?author=lejovaar7" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
|
||||
Contributions of any kind welcome!
|
292
node_modules/grammy/out/bot.d.ts
generated
vendored
Normal file
292
node_modules/grammy/out/bot.d.ts
generated
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
import { BotError, Composer, type Middleware } from "./composer.js";
|
||||
import { Context } from "./context.js";
|
||||
import { Api } from "./core/api.js";
|
||||
import { type ApiClientOptions, type WebhookReplyEnvelope } from "./core/client.js";
|
||||
import { type Filter, type FilterQuery } from "./filter.js";
|
||||
import { type Update, type UserFromGetMe } from "./types.js";
|
||||
export declare const DEFAULT_UPDATE_TYPES: readonly ["message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_join_request"];
|
||||
/**
|
||||
* Options that can be specified when running the bot via simple long polling.
|
||||
*/
|
||||
export interface PollingOptions {
|
||||
/**
|
||||
* Limits the number of updates to be retrieved per `getUpdates` call.
|
||||
* Values between 1-100 are accepted. Defaults to 100.
|
||||
*/
|
||||
limit?: number;
|
||||
/**
|
||||
* Timeout in seconds for long polling. grammY uses 30 seconds as a default
|
||||
* value.
|
||||
*/
|
||||
timeout?: number;
|
||||
/**
|
||||
* A list of the update types you want your bot to receive. For example,
|
||||
* specify [“message”, “edited_channel_post”, “callback_query”] to only
|
||||
* receive updates of these types. See Update for a complete list of
|
||||
* available update types. Specify an empty list to receive all update types
|
||||
* except chat_member (default). If not specified, the previous setting will
|
||||
* be used.
|
||||
*
|
||||
* Please note that this parameter doesn't affect updates created before the
|
||||
* call to the getUpdates, so unwanted updates may be received for a short
|
||||
* period of time.
|
||||
*/
|
||||
allowed_updates?: ReadonlyArray<Exclude<keyof Update, "update_id">>;
|
||||
/**
|
||||
* Pass True to drop all pending updates before starting the long polling.
|
||||
*/
|
||||
drop_pending_updates?: boolean;
|
||||
/**
|
||||
* A callback function that is useful for logging (or setting up middleware
|
||||
* if you did not do this before). It will be executed after the setup of
|
||||
* the bot has completed, and immediately before the first updates are being
|
||||
* fetched. The bot information `bot.botInfo` will be available when the
|
||||
* function is run. For convenience, the callback function receives the
|
||||
* value of `bot.botInfo` as an argument.
|
||||
*/
|
||||
onStart?: (botInfo: UserFromGetMe) => void | Promise<void>;
|
||||
}
|
||||
export { BotError };
|
||||
/**
|
||||
* Error handler that can be installed on a bot to catch error thrown by
|
||||
* middleware.
|
||||
*/
|
||||
export type ErrorHandler<C extends Context = Context> = (error: BotError<C>) => unknown;
|
||||
/**
|
||||
* Options to pass to the bot when creating it.
|
||||
*/
|
||||
export interface BotConfig<C extends Context> {
|
||||
/**
|
||||
* You can specify a number of advanced options under the `client` property.
|
||||
* The options will be passed to the grammY client—this is the part of
|
||||
* grammY that actually connects to the Telegram Bot API server in the end
|
||||
* when making HTTP requests.
|
||||
*/
|
||||
client?: ApiClientOptions;
|
||||
/**
|
||||
* grammY automatically calls `getMe` when starting up to make sure that
|
||||
* your bot has access to the bot's own information. If you restart your bot
|
||||
* often, for example because it is running in a serverless environment,
|
||||
* then you may want to skip this initial API call.
|
||||
*
|
||||
* Set this property of the options to pre-initialize the bot with cached
|
||||
* values. If you use this option, grammY will not attempt to make a `getMe`
|
||||
* call but use the provided data instead.
|
||||
*/
|
||||
botInfo?: UserFromGetMe;
|
||||
/**
|
||||
* Pass the constructor of a custom context object that will be used when
|
||||
* creating the context for each incoming update.
|
||||
*/
|
||||
ContextConstructor?: new (...args: ConstructorParameters<typeof Context>) => C;
|
||||
}
|
||||
/**
|
||||
* This is the single most important class of grammY. It represents your bot.
|
||||
*
|
||||
* First, you must create a bot by talking to @BotFather, check out
|
||||
* https://t.me/BotFather. Once it is ready, you obtain a secret token for your
|
||||
* bot. grammY will use that token to identify as your bot when talking to the
|
||||
* Telegram servers. Got the token? You are now ready to write some code and run
|
||||
* your bot!
|
||||
*
|
||||
* You should do three things to run your bot:
|
||||
* ```ts
|
||||
* // 1. Create a bot instance
|
||||
* const bot = new Bot('<secret-token>')
|
||||
* // 2. Listen for updates
|
||||
* bot.on('message:text', ctx => ctx.reply('You wrote: ' + ctx.message.text))
|
||||
* // 3. Launch it!
|
||||
* bot.start()
|
||||
* ```
|
||||
*/
|
||||
export declare class Bot<C extends Context = Context, A extends Api = Api> extends Composer<C> {
|
||||
readonly token: string;
|
||||
private pollingRunning;
|
||||
private pollingAbortController;
|
||||
private lastTriedUpdateId;
|
||||
/**
|
||||
* Gives you full access to the Telegram Bot API.
|
||||
* ```ts
|
||||
* // This is how to call the Bot API methods:
|
||||
* bot.api.sendMessage(chat_id, 'Hello, grammY!')
|
||||
* ```
|
||||
*
|
||||
* Use this only outside of your middleware. If you have access to `ctx`,
|
||||
* then using `ctx.api` instead of `bot.api` is preferred.
|
||||
*/
|
||||
readonly api: A;
|
||||
private me;
|
||||
private mePromise;
|
||||
private readonly clientConfig;
|
||||
private readonly ContextConstructor;
|
||||
/** Used to log a warning if some update types are not in allowed_updates */
|
||||
private observedUpdateTypes;
|
||||
/**
|
||||
* Holds the bot's error handler that is invoked whenever middleware throws
|
||||
* (rejects). If you set your own error handler via `bot.catch`, all that
|
||||
* happens is that this variable is assigned.
|
||||
*/
|
||||
errorHandler: ErrorHandler<C>;
|
||||
/**
|
||||
* Creates a new Bot with the given token.
|
||||
*
|
||||
* Remember that you can listen for messages by calling
|
||||
* ```ts
|
||||
* bot.on('message', ctx => { ... })
|
||||
* ```
|
||||
* or similar methods.
|
||||
*
|
||||
* The simplest way to start your bot is via simple long polling:
|
||||
* ```ts
|
||||
* bot.start()
|
||||
* ```
|
||||
*
|
||||
* @param token The bot's token as acquired from https://t.me/BotFather
|
||||
* @param config Optional configuration properties for the bot
|
||||
*/
|
||||
constructor(token: string, config?: BotConfig<C>);
|
||||
/**
|
||||
* Information about the bot itself as retrieved from `api.getMe()`. Only
|
||||
* available after the bot has been initialized via `await bot.init()`, or
|
||||
* after the value has been set manually.
|
||||
*
|
||||
* Starting the bot will always perform the initialization automatically,
|
||||
* unless a manual value is already set.
|
||||
*
|
||||
* Note that the recommended way to set a custom bot information object is
|
||||
* to pass it to the configuration object of the `new Bot()` instantiation,
|
||||
* rather than assigning this property.
|
||||
*/
|
||||
set botInfo(botInfo: UserFromGetMe);
|
||||
get botInfo(): UserFromGetMe;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
on<Q extends FilterQuery>(filter: Q | Q[], ...middleware: Array<Middleware<Filter<C, Q>>>): Composer<Filter<C, Q>>;
|
||||
/**
|
||||
* Checks if the bot has been initialized. A bot is initialized if the bot
|
||||
* information is set. The bot information can either be set automatically
|
||||
* by calling `bot.init`, or manually through the bot constructor. Note that
|
||||
* usually, initialization is done automatically and you do not have to care
|
||||
* about this method.
|
||||
*
|
||||
* @returns true if the bot is initialized, and false otherwise
|
||||
*/
|
||||
isInited(): boolean;
|
||||
/**
|
||||
* Initializes the bot, i.e. fetches information about the bot itself. This
|
||||
* method is called automatically, you usually don't have to call it
|
||||
* manually.
|
||||
*
|
||||
* @param signal Optional `AbortSignal` to cancel the initialization
|
||||
*/
|
||||
init(signal?: AbortSignal): Promise<void>;
|
||||
/**
|
||||
* Internal. Do not call. Handles an update batch sequentially by supplying
|
||||
* it one-by-one to the middleware. Handles middleware errors and stores the
|
||||
* last update identifier that was being tried to handle.
|
||||
*
|
||||
* @param updates An array of updates to handle
|
||||
*/
|
||||
private handleUpdates;
|
||||
/**
|
||||
* This is an internal method that you probably will not ever need to call.
|
||||
* It is used whenever a new update arrives from the Telegram servers that
|
||||
* your bot will handle.
|
||||
*
|
||||
* If you're writing a library on top of grammY, check out the
|
||||
* [documentation](https://grammy.dev/plugins/runner.html) of the runner
|
||||
* plugin for an example that uses this method.
|
||||
*
|
||||
* @param update An update from the Telegram Bot API
|
||||
* @param webhookReplyEnvelope An optional webhook reply envelope
|
||||
*/
|
||||
handleUpdate(update: Update, webhookReplyEnvelope?: WebhookReplyEnvelope): Promise<void>;
|
||||
/**
|
||||
* Starts your bot using long polling.
|
||||
*
|
||||
* > This method returns a `Promise` that will never resolve except if your
|
||||
* > bot is stopped. **You don't need to `await` the call to `bot.start`**,
|
||||
* > but remember to catch potential errors by calling `bot.catch`.
|
||||
* > Otherwise your bot will crash (and stop) if something goes wrong in
|
||||
* > your code.
|
||||
*
|
||||
* This method effectively enters a loop that will repeatedly call
|
||||
* `getUpdates` and run your middleware for every received update, allowing
|
||||
* your bot to respond to messages.
|
||||
*
|
||||
* If your bot is already running, this method does nothing.
|
||||
*
|
||||
* **Note that this starts your bot using a very simple long polling
|
||||
* implementation.** `bot.start` should only be used for small bots. While
|
||||
* the rest of grammY was built to perform well even under extreme loads,
|
||||
* simple long polling is not capable of scaling up in a similar fashion.
|
||||
* You should switch over to using `@grammyjs/runner` if you are running a
|
||||
* bot with high load.
|
||||
*
|
||||
* What exactly _high load_ means differs from bot to bot, but as a rule of
|
||||
* thumb, simple long polling should not be processing more than ~5K
|
||||
* messages every hour. Also, if your bot has long-running operations such
|
||||
* as large file transfers that block the middleware from completing, this
|
||||
* will impact the responsiveness negatively, so it makes sense to use the
|
||||
* `@grammyjs/runner` package even if you receive much fewer messages. If
|
||||
* you worry about how much load your bot can handle, check out the grammY
|
||||
* [documentation](https://grammy.dev/advanced/scaling.html) about scaling
|
||||
* up.
|
||||
*
|
||||
* @param options Options to use for simple long polling
|
||||
*/
|
||||
start(options?: PollingOptions): Promise<void>;
|
||||
/**
|
||||
* Stops the bot from long polling.
|
||||
*
|
||||
* All middleware that is currently being executed may complete, but no
|
||||
* further `getUpdates` calls will be performed. The current `getUpdates`
|
||||
* request will be cancelled.
|
||||
*
|
||||
* In addition, this method will _confirm_ the last received update to the
|
||||
* Telegram servers by calling `getUpdates` one last time with the latest
|
||||
* offset value. If any updates are received in this call, they are
|
||||
* discarded and will be fetched again when the bot starts up the next time.
|
||||
* Confer the official documentation on confirming updates if you want to
|
||||
* know more: https://core.telegram.org/bots/api#getupdates
|
||||
*
|
||||
* > Note that this method will not wait for the middleware stack to finish.
|
||||
* > If you need to run code after all middleware is done, consider waiting
|
||||
* > for the promise returned by `bot.start()` to resolve.
|
||||
*/
|
||||
stop(): Promise<void>;
|
||||
/**
|
||||
* Sets the bots error handler that is used during long polling.
|
||||
*
|
||||
* You should call this method to set an error handler if you are using long
|
||||
* polling, no matter whether you use `bot.start` or the `@grammyjs/runner`
|
||||
* package to run your bot.
|
||||
*
|
||||
* Calling `bot.catch` when using other means of running your bot (or
|
||||
* webhooks) has no effect.
|
||||
*
|
||||
* @param errorHandler A function that handles potential middleware errors
|
||||
*/
|
||||
catch(errorHandler: ErrorHandler<C>): void;
|
||||
/**
|
||||
* Internal. Do not call. Enters a loop that will perform long polling until
|
||||
* the bot is stopped.
|
||||
*/
|
||||
private loop;
|
||||
/**
|
||||
* Internal. Do not call. Reliably fetches an update batch via `getUpdates`.
|
||||
* Handles all known errors. Returns `undefined` if the bot is stopped and
|
||||
* the call gets cancelled.
|
||||
*
|
||||
* @param options Polling options
|
||||
* @returns An array of updates, or `undefined` if the bot is stopped.
|
||||
*/
|
||||
private fetchUpdates;
|
||||
/**
|
||||
* Internal. Do not call. Handles an error that occurred during long
|
||||
* polling.
|
||||
*/
|
||||
private handlePollingError;
|
||||
}
|
||||
import { AbortSignal } from "./shim.node.js";
|
550
node_modules/grammy/out/bot.js
generated
vendored
Normal file
550
node_modules/grammy/out/bot.js
generated
vendored
Normal file
@ -0,0 +1,550 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Bot = exports.BotError = exports.DEFAULT_UPDATE_TYPES = void 0;
|
||||
// deno-lint-ignore-file camelcase
|
||||
const composer_js_1 = require("./composer.js");
|
||||
Object.defineProperty(exports, "BotError", { enumerable: true, get: function () { return composer_js_1.BotError; } });
|
||||
const context_js_1 = require("./context.js");
|
||||
const api_js_1 = require("./core/api.js");
|
||||
const error_js_1 = require("./core/error.js");
|
||||
const filter_js_1 = require("./filter.js");
|
||||
const platform_node_js_1 = require("./platform.node.js");
|
||||
const debug = (0, platform_node_js_1.debug)("grammy:bot");
|
||||
const debugWarn = (0, platform_node_js_1.debug)("grammy:warn");
|
||||
const debugErr = (0, platform_node_js_1.debug)("grammy:error");
|
||||
exports.DEFAULT_UPDATE_TYPES = [
|
||||
"message",
|
||||
"edited_message",
|
||||
"channel_post",
|
||||
"edited_channel_post",
|
||||
"inline_query",
|
||||
"chosen_inline_result",
|
||||
"callback_query",
|
||||
"shipping_query",
|
||||
"pre_checkout_query",
|
||||
"poll",
|
||||
"poll_answer",
|
||||
"my_chat_member",
|
||||
"chat_join_request",
|
||||
];
|
||||
/**
|
||||
* This is the single most important class of grammY. It represents your bot.
|
||||
*
|
||||
* First, you must create a bot by talking to @BotFather, check out
|
||||
* https://t.me/BotFather. Once it is ready, you obtain a secret token for your
|
||||
* bot. grammY will use that token to identify as your bot when talking to the
|
||||
* Telegram servers. Got the token? You are now ready to write some code and run
|
||||
* your bot!
|
||||
*
|
||||
* You should do three things to run your bot:
|
||||
* ```ts
|
||||
* // 1. Create a bot instance
|
||||
* const bot = new Bot('<secret-token>')
|
||||
* // 2. Listen for updates
|
||||
* bot.on('message:text', ctx => ctx.reply('You wrote: ' + ctx.message.text))
|
||||
* // 3. Launch it!
|
||||
* bot.start()
|
||||
* ```
|
||||
*/
|
||||
class Bot extends composer_js_1.Composer {
|
||||
/**
|
||||
* Creates a new Bot with the given token.
|
||||
*
|
||||
* Remember that you can listen for messages by calling
|
||||
* ```ts
|
||||
* bot.on('message', ctx => { ... })
|
||||
* ```
|
||||
* or similar methods.
|
||||
*
|
||||
* The simplest way to start your bot is via simple long polling:
|
||||
* ```ts
|
||||
* bot.start()
|
||||
* ```
|
||||
*
|
||||
* @param token The bot's token as acquired from https://t.me/BotFather
|
||||
* @param config Optional configuration properties for the bot
|
||||
*/
|
||||
constructor(token, config) {
|
||||
var _a;
|
||||
super();
|
||||
this.token = token;
|
||||
this.pollingRunning = false;
|
||||
this.lastTriedUpdateId = 0;
|
||||
/** Used to log a warning if some update types are not in allowed_updates */
|
||||
this.observedUpdateTypes = new Set();
|
||||
/**
|
||||
* Holds the bot's error handler that is invoked whenever middleware throws
|
||||
* (rejects). If you set your own error handler via `bot.catch`, all that
|
||||
* happens is that this variable is assigned.
|
||||
*/
|
||||
this.errorHandler = async (err) => {
|
||||
var _a, _b;
|
||||
console.error("Error in middleware while handling update", (_b = (_a = err.ctx) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.update_id, err.error);
|
||||
console.error("No error handler was set!");
|
||||
console.error("Set your own error handler with `bot.catch = ...`");
|
||||
if (this.pollingRunning) {
|
||||
console.error("Stopping bot");
|
||||
await this.stop();
|
||||
}
|
||||
throw err;
|
||||
};
|
||||
if (!token)
|
||||
throw new Error("Empty token!");
|
||||
this.me = config === null || config === void 0 ? void 0 : config.botInfo;
|
||||
this.clientConfig = config === null || config === void 0 ? void 0 : config.client;
|
||||
this.ContextConstructor = (_a = config === null || config === void 0 ? void 0 : config.ContextConstructor) !== null && _a !== void 0 ? _a : context_js_1.Context;
|
||||
this.api = new api_js_1.Api(token, this.clientConfig);
|
||||
}
|
||||
/**
|
||||
* Information about the bot itself as retrieved from `api.getMe()`. Only
|
||||
* available after the bot has been initialized via `await bot.init()`, or
|
||||
* after the value has been set manually.
|
||||
*
|
||||
* Starting the bot will always perform the initialization automatically,
|
||||
* unless a manual value is already set.
|
||||
*
|
||||
* Note that the recommended way to set a custom bot information object is
|
||||
* to pass it to the configuration object of the `new Bot()` instantiation,
|
||||
* rather than assigning this property.
|
||||
*/
|
||||
set botInfo(botInfo) {
|
||||
this.me = botInfo;
|
||||
}
|
||||
get botInfo() {
|
||||
if (this.me === undefined) {
|
||||
throw new Error("Bot information unavailable! Make sure to call `await bot.init()` before accessing `bot.botInfo`!");
|
||||
}
|
||||
return this.me;
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
on(filter, ...middleware) {
|
||||
for (const [u] of (0, filter_js_1.parse)(filter).flatMap(filter_js_1.preprocess)) {
|
||||
this.observedUpdateTypes.add(u);
|
||||
}
|
||||
return super.on(filter, ...middleware);
|
||||
}
|
||||
/**
|
||||
* Checks if the bot has been initialized. A bot is initialized if the bot
|
||||
* information is set. The bot information can either be set automatically
|
||||
* by calling `bot.init`, or manually through the bot constructor. Note that
|
||||
* usually, initialization is done automatically and you do not have to care
|
||||
* about this method.
|
||||
*
|
||||
* @returns true if the bot is initialized, and false otherwise
|
||||
*/
|
||||
isInited() {
|
||||
return this.me !== undefined;
|
||||
}
|
||||
/**
|
||||
* Initializes the bot, i.e. fetches information about the bot itself. This
|
||||
* method is called automatically, you usually don't have to call it
|
||||
* manually.
|
||||
*
|
||||
* @param signal Optional `AbortSignal` to cancel the initialization
|
||||
*/
|
||||
async init(signal) {
|
||||
var _a;
|
||||
if (!this.isInited()) {
|
||||
debug("Initializing bot");
|
||||
(_a = this.mePromise) !== null && _a !== void 0 ? _a : (this.mePromise = withRetries(() => this.api.getMe(signal), signal));
|
||||
let me;
|
||||
try {
|
||||
me = await this.mePromise;
|
||||
}
|
||||
finally {
|
||||
this.mePromise = undefined;
|
||||
}
|
||||
if (this.me === undefined)
|
||||
this.me = me;
|
||||
else
|
||||
debug("Bot info was set by now, will not overwrite");
|
||||
}
|
||||
debug(`I am ${this.me.username}!`);
|
||||
}
|
||||
/**
|
||||
* Internal. Do not call. Handles an update batch sequentially by supplying
|
||||
* it one-by-one to the middleware. Handles middleware errors and stores the
|
||||
* last update identifier that was being tried to handle.
|
||||
*
|
||||
* @param updates An array of updates to handle
|
||||
*/
|
||||
async handleUpdates(updates) {
|
||||
// handle updates sequentially (!)
|
||||
for (const update of updates) {
|
||||
this.lastTriedUpdateId = update.update_id;
|
||||
try {
|
||||
await this.handleUpdate(update);
|
||||
}
|
||||
catch (err) {
|
||||
// should always be true
|
||||
if (err instanceof composer_js_1.BotError) {
|
||||
await this.errorHandler(err);
|
||||
}
|
||||
else {
|
||||
console.error("FATAL: grammY unable to handle:", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This is an internal method that you probably will not ever need to call.
|
||||
* It is used whenever a new update arrives from the Telegram servers that
|
||||
* your bot will handle.
|
||||
*
|
||||
* If you're writing a library on top of grammY, check out the
|
||||
* [documentation](https://grammy.dev/plugins/runner.html) of the runner
|
||||
* plugin for an example that uses this method.
|
||||
*
|
||||
* @param update An update from the Telegram Bot API
|
||||
* @param webhookReplyEnvelope An optional webhook reply envelope
|
||||
*/
|
||||
async handleUpdate(update, webhookReplyEnvelope) {
|
||||
if (this.me === undefined) {
|
||||
throw new Error("Bot not initialized! Either call `await bot.init()`, \
|
||||
or directly set the `botInfo` option in the `Bot` constructor to specify \
|
||||
a known bot info object.");
|
||||
}
|
||||
debug(`Processing update ${update.update_id}`);
|
||||
// create API object
|
||||
const api = new api_js_1.Api(this.token, this.clientConfig, webhookReplyEnvelope);
|
||||
// configure it with the same transformers as bot.api
|
||||
const t = this.api.config.installedTransformers();
|
||||
if (t.length > 0)
|
||||
api.config.use(...t);
|
||||
// create context object
|
||||
const ctx = new this.ContextConstructor(update, api, this.me);
|
||||
try {
|
||||
// run middleware stack
|
||||
await (0, composer_js_1.run)(this.middleware(), ctx);
|
||||
}
|
||||
catch (err) {
|
||||
debugErr(`Error in middleware for update ${update.update_id}`);
|
||||
throw new composer_js_1.BotError(err, ctx);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Starts your bot using long polling.
|
||||
*
|
||||
* > This method returns a `Promise` that will never resolve except if your
|
||||
* > bot is stopped. **You don't need to `await` the call to `bot.start`**,
|
||||
* > but remember to catch potential errors by calling `bot.catch`.
|
||||
* > Otherwise your bot will crash (and stop) if something goes wrong in
|
||||
* > your code.
|
||||
*
|
||||
* This method effectively enters a loop that will repeatedly call
|
||||
* `getUpdates` and run your middleware for every received update, allowing
|
||||
* your bot to respond to messages.
|
||||
*
|
||||
* If your bot is already running, this method does nothing.
|
||||
*
|
||||
* **Note that this starts your bot using a very simple long polling
|
||||
* implementation.** `bot.start` should only be used for small bots. While
|
||||
* the rest of grammY was built to perform well even under extreme loads,
|
||||
* simple long polling is not capable of scaling up in a similar fashion.
|
||||
* You should switch over to using `@grammyjs/runner` if you are running a
|
||||
* bot with high load.
|
||||
*
|
||||
* What exactly _high load_ means differs from bot to bot, but as a rule of
|
||||
* thumb, simple long polling should not be processing more than ~5K
|
||||
* messages every hour. Also, if your bot has long-running operations such
|
||||
* as large file transfers that block the middleware from completing, this
|
||||
* will impact the responsiveness negatively, so it makes sense to use the
|
||||
* `@grammyjs/runner` package even if you receive much fewer messages. If
|
||||
* you worry about how much load your bot can handle, check out the grammY
|
||||
* [documentation](https://grammy.dev/advanced/scaling.html) about scaling
|
||||
* up.
|
||||
*
|
||||
* @param options Options to use for simple long polling
|
||||
*/
|
||||
async start(options) {
|
||||
var _a, _b, _c;
|
||||
// Perform setup
|
||||
if (!this.isInited()) {
|
||||
await this.init((_a = this.pollingAbortController) === null || _a === void 0 ? void 0 : _a.signal);
|
||||
}
|
||||
if (this.pollingRunning) {
|
||||
debug("Simple long polling already running!");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this.pollingRunning = true;
|
||||
this.pollingAbortController = new shim_node_js_1.AbortController();
|
||||
}
|
||||
await withRetries(() => {
|
||||
var _a;
|
||||
return this.api.deleteWebhook({
|
||||
drop_pending_updates: options === null || options === void 0 ? void 0 : options.drop_pending_updates,
|
||||
}, (_a = this.pollingAbortController) === null || _a === void 0 ? void 0 : _a.signal);
|
||||
}, (_b = this.pollingAbortController) === null || _b === void 0 ? void 0 : _b.signal);
|
||||
// All async ops of setup complete, run callback
|
||||
await ((_c = options === null || options === void 0 ? void 0 : options.onStart) === null || _c === void 0 ? void 0 : _c.call(options, this.botInfo));
|
||||
// Bot was stopped during `onStart`
|
||||
if (!this.pollingRunning)
|
||||
return;
|
||||
// Prevent common misuse that leads to missing updates
|
||||
validateAllowedUpdates(this.observedUpdateTypes, options === null || options === void 0 ? void 0 : options.allowed_updates);
|
||||
// Prevent common misuse that causes memory leak
|
||||
this.use = noUseFunction;
|
||||
// Start polling
|
||||
debug("Starting simple long polling");
|
||||
await this.loop(options);
|
||||
debug("Middleware is done running");
|
||||
}
|
||||
/**
|
||||
* Stops the bot from long polling.
|
||||
*
|
||||
* All middleware that is currently being executed may complete, but no
|
||||
* further `getUpdates` calls will be performed. The current `getUpdates`
|
||||
* request will be cancelled.
|
||||
*
|
||||
* In addition, this method will _confirm_ the last received update to the
|
||||
* Telegram servers by calling `getUpdates` one last time with the latest
|
||||
* offset value. If any updates are received in this call, they are
|
||||
* discarded and will be fetched again when the bot starts up the next time.
|
||||
* Confer the official documentation on confirming updates if you want to
|
||||
* know more: https://core.telegram.org/bots/api#getupdates
|
||||
*
|
||||
* > Note that this method will not wait for the middleware stack to finish.
|
||||
* > If you need to run code after all middleware is done, consider waiting
|
||||
* > for the promise returned by `bot.start()` to resolve.
|
||||
*/
|
||||
async stop() {
|
||||
var _a;
|
||||
if (this.pollingRunning) {
|
||||
debug("Stopping bot, saving update offset");
|
||||
this.pollingRunning = false;
|
||||
(_a = this.pollingAbortController) === null || _a === void 0 ? void 0 : _a.abort();
|
||||
const offset = this.lastTriedUpdateId + 1;
|
||||
await this.api.getUpdates({ offset, limit: 1 })
|
||||
.finally(() => this.pollingAbortController = undefined);
|
||||
}
|
||||
else {
|
||||
debug("Bot is not running!");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the bots error handler that is used during long polling.
|
||||
*
|
||||
* You should call this method to set an error handler if you are using long
|
||||
* polling, no matter whether you use `bot.start` or the `@grammyjs/runner`
|
||||
* package to run your bot.
|
||||
*
|
||||
* Calling `bot.catch` when using other means of running your bot (or
|
||||
* webhooks) has no effect.
|
||||
*
|
||||
* @param errorHandler A function that handles potential middleware errors
|
||||
*/
|
||||
catch(errorHandler) {
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
/**
|
||||
* Internal. Do not call. Enters a loop that will perform long polling until
|
||||
* the bot is stopped.
|
||||
*/
|
||||
async loop(options) {
|
||||
var _a, _b;
|
||||
const limit = options === null || options === void 0 ? void 0 : options.limit;
|
||||
const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 30; // seconds
|
||||
let allowed_updates = (_b = options === null || options === void 0 ? void 0 : options.allowed_updates) !== null && _b !== void 0 ? _b : []; // reset to default if unspecified
|
||||
while (this.pollingRunning) {
|
||||
// fetch updates
|
||||
const updates = await this.fetchUpdates({ limit, timeout, allowed_updates });
|
||||
// check if polling stopped
|
||||
if (updates === undefined)
|
||||
break;
|
||||
// handle updates
|
||||
await this.handleUpdates(updates);
|
||||
// Telegram uses the last setting if `allowed_updates` is omitted so
|
||||
// we can save some traffic by only sending it in the first request
|
||||
allowed_updates = undefined;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Internal. Do not call. Reliably fetches an update batch via `getUpdates`.
|
||||
* Handles all known errors. Returns `undefined` if the bot is stopped and
|
||||
* the call gets cancelled.
|
||||
*
|
||||
* @param options Polling options
|
||||
* @returns An array of updates, or `undefined` if the bot is stopped.
|
||||
*/
|
||||
async fetchUpdates({ limit, timeout, allowed_updates }) {
|
||||
var _a;
|
||||
const offset = this.lastTriedUpdateId + 1;
|
||||
let updates = undefined;
|
||||
do {
|
||||
try {
|
||||
updates = await this.api.getUpdates({ offset, limit, timeout, allowed_updates }, (_a = this.pollingAbortController) === null || _a === void 0 ? void 0 : _a.signal);
|
||||
}
|
||||
catch (error) {
|
||||
await this.handlePollingError(error);
|
||||
}
|
||||
} while (updates === undefined && this.pollingRunning);
|
||||
return updates;
|
||||
}
|
||||
/**
|
||||
* Internal. Do not call. Handles an error that occurred during long
|
||||
* polling.
|
||||
*/
|
||||
async handlePollingError(error) {
|
||||
var _a;
|
||||
if (!this.pollingRunning) {
|
||||
debug("Pending getUpdates request cancelled");
|
||||
return;
|
||||
}
|
||||
let sleepSeconds = 3;
|
||||
if (error instanceof error_js_1.GrammyError) {
|
||||
debugErr(error.message);
|
||||
if (error.error_code === 401) {
|
||||
debugErr("Make sure you are using the bot token you obtained from @BotFather (https://t.me/BotFather).");
|
||||
throw error;
|
||||
}
|
||||
else if (error.error_code === 409) {
|
||||
debugErr("Consider revoking the bot token if you believe that no other instance is running.");
|
||||
throw error;
|
||||
}
|
||||
else if (error.error_code === 429) {
|
||||
debugErr("Bot API server is closing.");
|
||||
sleepSeconds = (_a = error.parameters.retry_after) !== null && _a !== void 0 ? _a : sleepSeconds;
|
||||
}
|
||||
}
|
||||
else
|
||||
debugErr(error);
|
||||
debugErr(`Call to getUpdates failed, retrying in ${sleepSeconds} seconds ...`);
|
||||
await sleep(sleepSeconds);
|
||||
}
|
||||
}
|
||||
exports.Bot = Bot;
|
||||
/**
|
||||
* Performs a network call task, retrying upon known errors until success.
|
||||
*
|
||||
* If the task errors and a retry_after value can be used, a subsequent retry
|
||||
* will be delayed by the specified period of time.
|
||||
*
|
||||
* Otherwise, if the first attempt at running the task fails, the task is
|
||||
* retried immediately. If second attempt fails, too, waits for 100 ms, and then
|
||||
* doubles this delay for every subsequent attemt. Never waits longer than 1
|
||||
* hour before retrying.
|
||||
*
|
||||
* @param task Async task to perform
|
||||
* @param signal Optional `AbortSignal` to prevent further retries
|
||||
*/
|
||||
async function withRetries(task, signal) {
|
||||
// Set up delays between retries
|
||||
const INITIAL_DELAY = 50; // ms
|
||||
let lastDelay = INITIAL_DELAY;
|
||||
// Define error handler
|
||||
/**
|
||||
* Determines the error handling strategy based on various error types.
|
||||
* Sleeps if necessary, and returns whether to retry or rethrow an error.
|
||||
*/
|
||||
async function handleError(error) {
|
||||
let delay = false;
|
||||
let strategy = "rethrow";
|
||||
if (error instanceof error_js_1.HttpError) {
|
||||
delay = true;
|
||||
strategy = "retry";
|
||||
}
|
||||
else if (error instanceof error_js_1.GrammyError) {
|
||||
if (error.error_code >= 500) {
|
||||
delay = true;
|
||||
strategy = "retry";
|
||||
}
|
||||
else if (error.error_code === 429) {
|
||||
const retryAfter = error.parameters.retry_after;
|
||||
if (typeof retryAfter === "number") {
|
||||
// ignore the backoff for sleep, then reset it
|
||||
await sleep(retryAfter, signal);
|
||||
lastDelay = INITIAL_DELAY;
|
||||
}
|
||||
else {
|
||||
delay = true;
|
||||
}
|
||||
strategy = "retry";
|
||||
}
|
||||
}
|
||||
if (delay) {
|
||||
// Do not sleep for the first retry
|
||||
if (lastDelay !== INITIAL_DELAY) {
|
||||
await sleep(lastDelay, signal);
|
||||
}
|
||||
const TWENTY_MINUTES = 20 * 60 * 1000; // ms
|
||||
lastDelay = Math.min(TWENTY_MINUTES, 2 * lastDelay);
|
||||
}
|
||||
return strategy;
|
||||
}
|
||||
// Perform the actual task with retries
|
||||
let result = { ok: false };
|
||||
while (!result.ok) {
|
||||
try {
|
||||
result = { ok: true, value: await task() };
|
||||
}
|
||||
catch (error) {
|
||||
debugErr(error);
|
||||
const strategy = await handleError(error);
|
||||
switch (strategy) {
|
||||
case "retry":
|
||||
continue;
|
||||
case "rethrow":
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.value;
|
||||
}
|
||||
/**
|
||||
* Returns a new promise that resolves after the specified number of seconds, or
|
||||
* rejects as soon as the given signal is aborted.
|
||||
*/
|
||||
async function sleep(seconds, signal) {
|
||||
let handle;
|
||||
let reject;
|
||||
function abort() {
|
||||
reject === null || reject === void 0 ? void 0 : reject(new Error("Aborted delay"));
|
||||
if (handle !== undefined)
|
||||
clearTimeout(handle);
|
||||
}
|
||||
try {
|
||||
await new Promise((res, rej) => {
|
||||
reject = rej;
|
||||
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
signal === null || signal === void 0 ? void 0 : signal.addEventListener("abort", abort);
|
||||
handle = setTimeout(res, 1000 * seconds);
|
||||
});
|
||||
}
|
||||
finally {
|
||||
signal === null || signal === void 0 ? void 0 : signal.removeEventListener("abort", abort);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Takes a set of observed update types and a list of allowed updates and logs a
|
||||
* warning in debug mode if some update types were observed that have not been
|
||||
* allowed.
|
||||
*/
|
||||
function validateAllowedUpdates(updates, allowed = exports.DEFAULT_UPDATE_TYPES) {
|
||||
const impossible = Array.from(updates).filter((u) => !allowed.includes(u));
|
||||
if (impossible.length > 0) {
|
||||
debugWarn(`You registered listeners for the following update types, \
|
||||
but you did not specify them in \`allowed_updates\` \
|
||||
so they may not be received: ${impossible.map((u) => `'${u}'`).join(", ")}`);
|
||||
}
|
||||
}
|
||||
function noUseFunction() {
|
||||
throw new Error(`It looks like you are registering more listeners \
|
||||
on your bot from within other listeners! This means that every time your bot \
|
||||
handles a message like this one, new listeners will be added. This list grows until \
|
||||
your machine crashes, so grammY throws this error to tell you that you should \
|
||||
probably do things a bit differently. If you're unsure how to resolve this problem, \
|
||||
you can ask in the group chat: https://telegram.me/grammyjs
|
||||
|
||||
On the other hand, if you actually know what you're doing and you do need to install \
|
||||
further middleware while your bot is running, consider installing a composer \
|
||||
instance on your bot, and in turn augment the composer after the fact. This way, \
|
||||
you can circumvent this protection against memory leaks.`);
|
||||
}
|
||||
const shim_node_js_1 = require("./shim.node.js");
|
668
node_modules/grammy/out/composer.d.ts
generated
vendored
Normal file
668
node_modules/grammy/out/composer.d.ts
generated
vendored
Normal file
@ -0,0 +1,668 @@
|
||||
import { type CallbackQueryContext, type ChatTypeContext, type ChosenInlineResultContext, type CommandContext, Context, type GameQueryContext, type HearsContext, type InlineQueryContext, type MaybeArray, type StringWithSuggestions } from "./context.js";
|
||||
import { type Filter, type FilterQuery } from "./filter.js";
|
||||
import { type Chat } from "./types.js";
|
||||
type MaybePromise<T> = T | Promise<T>;
|
||||
/**
|
||||
* A function of this type is passed as the second parameter to all middleware.
|
||||
* Invoke it to call the downstream middleware and pass on the control flow.
|
||||
*
|
||||
* In other words, if your middleware is done handling the context object, and
|
||||
* other middleware should take over, this function should be called and
|
||||
* `await`ed.
|
||||
*
|
||||
* Once the `Promise` returned by this function resolves, the downstream
|
||||
* middleware is done executing, hence returning the control.
|
||||
*/
|
||||
export type NextFunction = () => Promise<void>;
|
||||
/**
|
||||
* Middleware in the form of a function.
|
||||
*/
|
||||
export type MiddlewareFn<C extends Context = Context> = (ctx: C, next: NextFunction) => MaybePromise<unknown>;
|
||||
/**
|
||||
* Middleware in the form of a container for a function.
|
||||
*/
|
||||
export interface MiddlewareObj<C extends Context = Context> {
|
||||
/**
|
||||
* Returns the contained middleware.
|
||||
*/
|
||||
middleware: () => MiddlewareFn<C>;
|
||||
}
|
||||
/**
|
||||
* Middleware for grammY, either as a function or as a container for a function.
|
||||
*
|
||||
* Simply put, middleware is just a fancy term for a _listener_. You can
|
||||
* register middleware on a bot to listen for updates. Example:
|
||||
*
|
||||
* ```ts
|
||||
* bot.on('message', ctx => ctx.reply('I got your message!'))
|
||||
* // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* // ^
|
||||
* // |
|
||||
* // This is middleware!
|
||||
* ```
|
||||
*
|
||||
* Middleware receives one object that we call the _context object_. This is
|
||||
* another fancy term for a simple object that holds information about the
|
||||
* update you're processing. For instance, the context object gives you access
|
||||
* to the message that was sent to your bot (`ctx.message`), including the text
|
||||
* (or photo or whatever message the user has sent). The context object is
|
||||
* commonly named `ctx`.
|
||||
*
|
||||
* It also provides you with the `ctx.api` object that you also find on
|
||||
* `bot.api`. As a result, you can call `ctx.api.sendMessage` instead of
|
||||
* `bot.api.sendMessage`. This prevents you from having to pass around your
|
||||
* `bot` instance all over your code.
|
||||
*
|
||||
* Most importantly, the context object gives you a handful of really useful
|
||||
* shortcuts, such as a `reply` method (see above). This method is nothing else
|
||||
* than a wrapper around `ctx.api.sendMessage`—but with some arguments
|
||||
* pre-filled for you. As you can see above, you no longer have to specify a
|
||||
* `chat_id` or anything; the context object knows which chat it belongs to, so
|
||||
* when you call `reply`, the context will call `sendMessage` with the correct
|
||||
* `chat_id`, namely the one for the same chat that the incoming message
|
||||
* originates from. This makes it very convenient to reply to a message.
|
||||
*
|
||||
* Middleware is an extremely powerful concept and this short explanation only
|
||||
* scratched the surface of what is possible with grammY. If you want to know
|
||||
* more advanced things about middleware, check out the
|
||||
* [documentation](https://grammy.dev/guide/middleware.html) on the website.
|
||||
*/
|
||||
export type Middleware<C extends Context = Context> = MiddlewareFn<C> | MiddlewareObj<C>;
|
||||
/**
|
||||
* This error is thrown when middleware throws. It simply wraps the original
|
||||
* error (accessible via the `error` property), but also provides access to the
|
||||
* respective context object that was processed while the error occurred.
|
||||
*/
|
||||
export declare class BotError<C extends Context = Context> extends Error {
|
||||
readonly error: unknown;
|
||||
readonly ctx: C;
|
||||
constructor(error: unknown, ctx: C);
|
||||
}
|
||||
/**
|
||||
* Runs some given middleware function with a given context object.
|
||||
*
|
||||
* @param middleware The middleware to run
|
||||
* @param ctx The context to use
|
||||
*/
|
||||
export declare function run<C extends Context>(middleware: MiddlewareFn<C>, ctx: C): Promise<void>;
|
||||
/**
|
||||
* The composer is the heart of the middleware system in grammY. It is also the
|
||||
* superclass of `Bot`. Whenever you call `use` or `on` or some of the other
|
||||
* methods on your bot, you are in fact using the underlying composer instance
|
||||
* to register your middleware.
|
||||
*
|
||||
* If you're just getting started, you do not need to worry about what
|
||||
* middleware is, or about how to use a composer.
|
||||
*
|
||||
* On the other hand, if you want to dig deeper into how grammY implements
|
||||
* middleware, check out the
|
||||
* [documentation](https://grammy.dev/advanced/middleware.html) on the website.
|
||||
*/
|
||||
export declare class Composer<C extends Context> implements MiddlewareObj<C> {
|
||||
private handler;
|
||||
/**
|
||||
* Constructs a new composer based on the provided middleware. If no
|
||||
* middleware is given, the composer instance will simply make all context
|
||||
* objects pass through without touching them.
|
||||
*
|
||||
* @param middleware The middleware to compose
|
||||
*/
|
||||
constructor(...middleware: Array<Middleware<C>>);
|
||||
middleware(): MiddlewareFn<C>;
|
||||
/**
|
||||
* Registers some middleware that receives all updates. It is installed by
|
||||
* concatenating it to the end of all previously installed middleware.
|
||||
*
|
||||
* Often, this method is used to install middleware that behaves like a
|
||||
* plugin, for example session middleware.
|
||||
* ```ts
|
||||
* bot.use(session())
|
||||
* ```
|
||||
*
|
||||
* This method returns a new instance of composer. The returned instance can
|
||||
* be further extended, and all changes will be regarded here. Confer the
|
||||
* [documentation](https://grammy.dev/advanced/middleware.html) on the
|
||||
* website if you want to know more about how the middleware system in
|
||||
* grammY works, especially when it comes to chaining the method calls
|
||||
* (`use( ... ).use( ... ).use( ... )`).
|
||||
*
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
use(...middleware: Array<Middleware<C>>): Composer<C>;
|
||||
/**
|
||||
* Registers some middleware that will only be executed for some specific
|
||||
* updates, namely those matching the provided filter query. Filter queries
|
||||
* are a concise way to specify which updates you are interested in.
|
||||
*
|
||||
* Here are some examples of valid filter queries:
|
||||
* ```ts
|
||||
* // All kinds of message updates
|
||||
* bot.on('message', ctx => { ... })
|
||||
*
|
||||
* // Only text messages
|
||||
* bot.on('message:text', ctx => { ... })
|
||||
*
|
||||
* // Only text messages with URL
|
||||
* bot.on('message:entities:url', ctx => { ... })
|
||||
*
|
||||
* // Text messages and text channel posts
|
||||
* bot.on(':text', ctx => { ... })
|
||||
*
|
||||
* // Messages with URL in text or caption (i.e. entities or caption entities)
|
||||
* bot.on('message::url', ctx => { ... })
|
||||
*
|
||||
* // Messages or channel posts with URL in text or caption
|
||||
* bot.on('::url', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* You can use autocomplete in VS Code to see all available filter queries.
|
||||
* Check out the
|
||||
* [documentation](https://grammy.dev/guide/filter-queries.html) on the
|
||||
* website to learn more about filter queries in grammY.
|
||||
*
|
||||
* It is possible to pass multiple filter queries in an array, i.e.
|
||||
* ```ts
|
||||
* // Matches all text messages and edited text messages that contain a URL
|
||||
* bot.on(['message:entities:url', 'edited_message:entities:url'], ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* Your middleware will be executed if _any of the provided filter queries_
|
||||
* matches (logical OR).
|
||||
*
|
||||
* If you instead want to match _all of the provided filter queries_
|
||||
* (logical AND), you can chain the `.on` calls:
|
||||
* ```ts
|
||||
* // Matches all messages and channel posts that both a) contain a URL and b) are forwards
|
||||
* bot.on('::url').on(':forward_date', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param filter The filter query to use, may also be an array of queries
|
||||
* @param middleware The middleware to register behind the given filter
|
||||
*/
|
||||
on<Q extends FilterQuery>(filter: Q | Q[], ...middleware: Array<Middleware<Filter<C, Q>>>): Composer<Filter<C, Q>>;
|
||||
/**
|
||||
* Registers some middleware that will only be executed when the message
|
||||
* contains some text. Is it possible to pass a regular expression to match:
|
||||
* ```ts
|
||||
* // Match some text (exact match)
|
||||
* bot.hears('I love grammY', ctx => ctx.reply('And grammY loves you! <3'))
|
||||
* // Match a regular expression
|
||||
* bot.hears(/\/echo (.+)/, ctx => ctx.reply(ctx.match[1]))
|
||||
* ```
|
||||
* Note how `ctx.match` will contain the result of the regular expression.
|
||||
* Here it is a `RegExpMatchArray` object, so `ctx.match[1]` refers to the
|
||||
* part of the regex that was matched by `(.+)`, i.e. the text that comes
|
||||
* after “/echo”.
|
||||
*
|
||||
* You can pass an array of triggers. Your middleware will be executed if at
|
||||
* least one of them matches.
|
||||
*
|
||||
* Both text and captions of the received messages will be scanned. For
|
||||
* example, when a photo is sent to the chat and its caption matches the
|
||||
* trigger, your middleware will be executed.
|
||||
*
|
||||
* If you only want to match text messages and not captions, you can do
|
||||
* this:
|
||||
* ```ts
|
||||
* // Only matches text messages (and channel posts) for the regex
|
||||
* bot.on(':text').hears(/\/echo (.+)/, ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param trigger The text to look for
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
hears(trigger: MaybeArray<string | RegExp>, ...middleware: Array<HearsMiddleware<C>>): Composer<HearsContext<C>>;
|
||||
/**
|
||||
* Registers some middleware that will only be executed when a certain
|
||||
* command is found.
|
||||
* ```ts
|
||||
* // Reacts to /start commands
|
||||
* bot.command('start', ctx => { ... })
|
||||
* // Reacts to /help commands
|
||||
* bot.command('help', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* The rest of the message (excluding the command, and trimmed) is provided
|
||||
* via `ctx.match`.
|
||||
*
|
||||
* > **Did you know?** You can use deep linking
|
||||
* > (https://core.telegram.org/bots/features#deep-linking) to let users
|
||||
* > start your bot with a custom payload. As an example, send someone the
|
||||
* > link https://t.me/name-of-your-bot?start=custom-payload and register a
|
||||
* > start command handler on your bot with grammY. As soon as the user
|
||||
* > starts your bot, you will receive `custom-payload` in the `ctx.match`
|
||||
* > property!
|
||||
* > ```ts
|
||||
* > bot.command('start', ctx => {
|
||||
* > const payload = ctx.match // will be 'custom-payload'
|
||||
* > })
|
||||
* > ```
|
||||
*
|
||||
* Note that commands are not matched in captions or in the middle of the
|
||||
* text.
|
||||
* ```ts
|
||||
* bot.command('start', ctx => { ... })
|
||||
* // ... does not match:
|
||||
* // A message saying: “some text /start some more text”
|
||||
* // A photo message with the caption “/start”
|
||||
* ```
|
||||
*
|
||||
* By default, commands are detected in channel posts, too. This means that
|
||||
* `ctx.message` is potentially `undefined`, so you should use `ctx.msg`
|
||||
* instead to grab both messages and channel posts. Alternatively, if you
|
||||
* want to limit your bot to finding commands only in private and group
|
||||
* chats, you can use `bot.on('message').command('start', ctx => { ... })`,
|
||||
* or even store a message-only version of your bot in a variable like so:
|
||||
* ```ts
|
||||
* const m = bot.on('message')
|
||||
*
|
||||
* m.command('start', ctx => { ... })
|
||||
* m.command('help', ctx => { ... })
|
||||
* // etc
|
||||
* ```
|
||||
*
|
||||
* If you need more freedom matching your commands, check out the `commands`
|
||||
* plugin.
|
||||
*
|
||||
* @param command The command to look for
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
command<S extends string>(command: MaybeArray<StringWithSuggestions<S | "start" | "help" | "settings">>, ...middleware: Array<CommandMiddleware<C>>): Composer<CommandContext<C>>;
|
||||
/**
|
||||
* Registers some middleware for certain chat types only. For example, you
|
||||
* can use this method to only receive updates from private chats. The four
|
||||
* chat types are `"channel"`, `"supergroup"`, `"group"`, and `"private"`.
|
||||
* This is especially useful when combined with other filtering logic. For
|
||||
* example, this is how can you respond to `/start` commands only from
|
||||
* private chats:
|
||||
* ```ts
|
||||
* bot.chatType("private").command("start", ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* Naturally, you can also use this method on its own.
|
||||
* ```ts
|
||||
* // Private chats only
|
||||
* bot.chatType("private", ctx => { ... });
|
||||
* // Channels only
|
||||
* bot.chatType("channel", ctx => { ... });
|
||||
* ```
|
||||
*
|
||||
* You can pass an array of chat types if you want your middleware to run
|
||||
* for any of several provided chat types.
|
||||
* ```ts
|
||||
* // Groups and supergroups only
|
||||
* bot.chatType(["group", "supergroup"], ctx => { ... });
|
||||
* ```
|
||||
* [Remember](https://grammy.dev/guide/context.html#shortcuts) also that you
|
||||
* can access the chat type via `ctx.chat.type`.
|
||||
*
|
||||
* @param chatType The chat type
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
chatType<T extends Chat["type"]>(chatType: MaybeArray<T>, ...middleware: Array<Middleware<ChatTypeContext<C, T>>>): Composer<ChatTypeContext<C, T>>;
|
||||
/**
|
||||
* Registers some middleware for callback queries, i.e. the updates that
|
||||
* Telegram delivers to your bot when a user clicks an inline button (that
|
||||
* is a button under a message).
|
||||
*
|
||||
* This method is essentially the same as calling
|
||||
* ```ts
|
||||
* bot.on('callback_query:data', ctx => { ... })
|
||||
* ```
|
||||
* but it also allows you to match the query data against a given text or
|
||||
* regular expression.
|
||||
*
|
||||
* ```ts
|
||||
* // Create an inline keyboard
|
||||
* const keyboard = new InlineKeyboard().text('Go!', 'button-payload')
|
||||
* // Send a message with the keyboard
|
||||
* await bot.api.sendMessage(chat_id, 'Press a button!', {
|
||||
* reply_markup: keyboard
|
||||
* })
|
||||
* // Listen to users pressing buttons with that specific payload
|
||||
* bot.callbackQuery('button-payload', ctx => { ... })
|
||||
*
|
||||
* // Listen to users pressing any button your bot ever sent
|
||||
* bot.on('callback_query:data', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* Always remember to call `answerCallbackQuery`—even if you don't perform
|
||||
* any action: https://core.telegram.org/bots/api#answercallbackquery
|
||||
* ```ts
|
||||
* bot.on('callback_query:data', async ctx => {
|
||||
* await ctx.answerCallbackQuery()
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* You can pass an array of triggers. Your middleware will be executed if at
|
||||
* least one of them matches.
|
||||
*
|
||||
* @param trigger The string to look for in the payload
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
callbackQuery(trigger: MaybeArray<string | RegExp>, ...middleware: Array<CallbackQueryMiddleware<C>>): Composer<CallbackQueryContext<C>>;
|
||||
/**
|
||||
* Registers some middleware for game queries, i.e. the updates that
|
||||
* Telegram delivers to your bot when a user clicks an inline button for the
|
||||
* HTML5 games platform on Telegram.
|
||||
*
|
||||
* This method is essentially the same as calling
|
||||
* ```ts
|
||||
* bot.on('callback_query:game_short_name', ctx => { ... })
|
||||
* ```
|
||||
* but it also allows you to match the query data against a given text or
|
||||
* regular expression.
|
||||
*
|
||||
* You can pass an array of triggers. Your middleware will be executed if at
|
||||
* least one of them matches.
|
||||
*
|
||||
* @param trigger The string to look for in the payload
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
gameQuery(trigger: MaybeArray<string | RegExp>, ...middleware: Array<GameQueryMiddleware<C>>): Composer<GameQueryContext<C>>;
|
||||
/**
|
||||
* Registers middleware for inline queries. Telegram sends an inline query
|
||||
* to your bot whenever a user types “@your_bot_name ...” into a text field
|
||||
* in Telegram. You bot will then receive the entered search query and can
|
||||
* respond with a number of results (text, images, etc) that the user can
|
||||
* pick from to send a message _via_ your bot to the respective chat. Check
|
||||
* out https://core.telegram.org/bots/inline to read more about inline bots.
|
||||
*
|
||||
* > Note that you have to enable inline mode for you bot by contacting
|
||||
* > @BotFather first.
|
||||
*
|
||||
* ```ts
|
||||
* // Listen for users typing “@your_bot_name query”
|
||||
* bot.inlineQuery('query', async ctx => {
|
||||
* // Answer the inline query, confer https://core.telegram.org/bots/api#answerinlinequery
|
||||
* await ctx.answerInlineQuery( ... )
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param trigger The inline query text to match
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
inlineQuery(trigger: MaybeArray<string | RegExp>, ...middleware: Array<InlineQueryMiddleware<C>>): Composer<InlineQueryContext<C>>;
|
||||
/**
|
||||
* Registers middleware for the ChosenInlineResult by the given id or ids.
|
||||
* ChosenInlineResult represents a result of an inline query that was
|
||||
* chosen by the user and sent to their chat partner. Check out
|
||||
* https://core.telegram.org/bots/api#choseninlineresult to read more
|
||||
* about chosen inline results.
|
||||
*
|
||||
* ```ts
|
||||
* bot.chosenInlineResult('id', async ctx => {
|
||||
* const id = ctx.result_id;
|
||||
* // Your code
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param resultId An id or array of ids
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
chosenInlineResult(resultId: MaybeArray<string | RegExp>, ...middleware: Array<ChosenInlineResultMiddleware<C>>): Composer<ChosenInlineResultContext<C>>;
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Registers middleware behind a custom filter function that operates on the
|
||||
* context object and decides whether or not to execute the middleware. In
|
||||
* other words, the middleware will only be executed if the given predicate
|
||||
* returns `true` for the given context object. Otherwise, it will be
|
||||
* skipped and the next middleware will be executed.
|
||||
*
|
||||
* This method has two signatures. The first one is straightforward, it is
|
||||
* the one described above. Note that the predicate may be asynchronous,
|
||||
* i.e. it can return a Promise of a boolean.
|
||||
*
|
||||
* Alternatively, you can pass a function that has a type predicate as
|
||||
* return type. This will allow you to narrow down the context object. The
|
||||
* installed middleware is then able to operate on this constrained context
|
||||
* object.
|
||||
* ```ts
|
||||
* // NORMAL USAGE
|
||||
* // Only process every second update
|
||||
* bot.filter(ctx => ctx.update.update_id % 2 === 0, ctx => { ... })
|
||||
*
|
||||
* // TYPE PREDICATE USAGE
|
||||
* function predicate(ctx): ctx is Context & { message: undefined } {
|
||||
* return ctx.message === undefined
|
||||
* }
|
||||
* // Only process updates where `message` is `undefined`
|
||||
* bot.filter(predicate, ctx => {
|
||||
* const m = ctx.message // inferred as always undefined!
|
||||
* const m2 = ctx.update.message // also inferred as always undefined!
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param predicate The predicate to check
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
filter<D extends C>(predicate: (ctx: C) => ctx is D, ...middleware: Array<Middleware<D>>): Composer<D>;
|
||||
filter(predicate: (ctx: C) => MaybePromise<boolean>, ...middleware: Array<Middleware<C>>): Composer<C>;
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Registers middleware behind a custom filter function that operates on the
|
||||
* context object and decides whether or not to execute the middleware. In
|
||||
* other words, the middleware will only be executed if the given predicate
|
||||
* returns `false` for the given context object. Otherwise, it will be
|
||||
* skipped and the next middleware will be executed. Note that the predicate
|
||||
* may be asynchronous, i.e. it can return a Promise of a boolean.
|
||||
*
|
||||
* This method is the same using `filter` (normal usage) with a negated
|
||||
* predicate.
|
||||
*
|
||||
* @param predicate The predicate to check
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
drop(predicate: (ctx: C) => MaybePromise<boolean>, ...middleware: Array<Middleware<C>>): Composer<C>;
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Registers some middleware that runs concurrently to the executing
|
||||
* middleware stack.
|
||||
* ```ts
|
||||
* bot.use( ... ) // will run first
|
||||
* bot.fork( ... ) // will be started second, but run concurrently
|
||||
* bot.use( ... ) // will also be run second
|
||||
* ```
|
||||
* In the first middleware, as soon as `next`'s Promise resolves, both forks
|
||||
* have completed.
|
||||
*
|
||||
* Both the fork and the downstream middleware are awaited with
|
||||
* `Promise.all`, so you will only be to catch up to one error (the one that
|
||||
* is thrown first).
|
||||
*
|
||||
* In opposite to the other middleware methods on composer, `fork` does not
|
||||
* return simply return the composer connected to the main middleware stack.
|
||||
* Instead, it returns the created composer _of the fork_ connected to the
|
||||
* middleware stack. This allows for the following pattern.
|
||||
* ```ts
|
||||
* // Middleware will be run concurrently!
|
||||
* bot.fork().on('message', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param middleware The middleware to run concurrently
|
||||
*/
|
||||
fork(...middleware: Array<Middleware<C>>): Composer<C>;
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Executes some middleware that can be generated on the fly for each
|
||||
* context. Pass a factory function that creates some middleware (or a
|
||||
* middleware array even). The factory function will be called once per
|
||||
* context, and its result will be executed with the context object.
|
||||
* ```ts
|
||||
* // The middleware returned by `createMyMiddleware` will be used only once
|
||||
* bot.lazy(ctx => createMyMiddleware(ctx))
|
||||
* ```
|
||||
*
|
||||
* You may generate this middleware in an `async` fashion.
|
||||
*
|
||||
* You can decide to return an empty array (`[]`) if you don't want to run
|
||||
* any middleware for a given context object. This is equivalent to
|
||||
* returning an empty instance of `Composer`.
|
||||
*
|
||||
* @param middlewareFactory The factory function creating the middleware
|
||||
*/
|
||||
lazy(middlewareFactory: (ctx: C) => MaybePromise<MaybeArray<Middleware<C>>>): Composer<C>;
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* _Not to be confused with the `router` plugin._
|
||||
*
|
||||
* This method is an alternative to the `router` plugin. It allows you to
|
||||
* branch between different middleware per context object. You can pass two
|
||||
* things to it:
|
||||
* 1. A routing function
|
||||
* 2. Different middleware identified by key
|
||||
*
|
||||
* The routing function decides based on the context object which middleware
|
||||
* to run. Each middleware is identified by a key, so the routing function
|
||||
* simply returns the key of that middleware.
|
||||
* ```ts
|
||||
* // Define different route handlers
|
||||
* const routeHandlers = {
|
||||
* evenUpdates: (ctx: Context) => { ... }
|
||||
* oddUpdates: (ctx: Context) => { ... }
|
||||
* }
|
||||
* // Decide for a context object which one to pick
|
||||
* const router = (ctx: Context) => ctx.update.update_id % 2 === 0
|
||||
* ? 'evenUpdates'
|
||||
* : 'oddUpdates'
|
||||
* // Route it!
|
||||
* bot.route(router, routeHandlers)
|
||||
* ```
|
||||
*
|
||||
* Optionally, you can pass a third option that is used as fallback
|
||||
* middleware if your route function returns `undefined`, or if the key
|
||||
* returned by your router has no middleware associated with it.
|
||||
*
|
||||
* This method may need less setup than first instantiating a `Router`, but
|
||||
* for more complex setups, having a `Router` may be more readable.
|
||||
*
|
||||
* @param router The routing function to use
|
||||
* @param routeHandlers Handlers for every route
|
||||
* @param fallback Optional fallback middleware if no route matches
|
||||
*/
|
||||
route<R extends Record<PropertyKey, Middleware<C>>>(router: (ctx: C) => MaybePromise<undefined | keyof R>, routeHandlers: R, fallback?: Middleware<C>): Composer<C>;
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Allows you to branch between two cases for a given context object.
|
||||
*
|
||||
* This method takes a predicate function that is tested once per context
|
||||
* object. If it returns `true`, the first supplied middleware is executed.
|
||||
* If it returns `false`, the second supplied middleware is executed. Note
|
||||
* that the predicate may be asynchronous, i.e. it can return a Promise of a
|
||||
* boolean.
|
||||
*
|
||||
* @param predicate The predicate to check
|
||||
* @param trueMiddleware The middleware for the `true` case
|
||||
* @param falseMiddleware The middleware for the `false` case
|
||||
*/
|
||||
branch(predicate: (ctx: C) => MaybePromise<boolean>, trueMiddleware: MaybeArray<Middleware<C>>, falseMiddleware: MaybeArray<Middleware<C>>): Composer<C>;
|
||||
/**
|
||||
* > This is an advanced function of grammY.
|
||||
*
|
||||
* Installs an error boundary that catches errors that happen only inside
|
||||
* the given middleware. This allows you to install custom error handlers
|
||||
* that protect some parts of your bot. Errors will not be able to bubble
|
||||
* out of this part of your middleware system, unless the supplied error
|
||||
* handler rethrows them, in which case the next surrounding error boundary
|
||||
* will catch the error.
|
||||
*
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* function errHandler(err: BotError) {
|
||||
* console.error('Error boundary caught error!', err)
|
||||
* }
|
||||
*
|
||||
* const safe =
|
||||
* // All passed middleware will be protected by the error boundary.
|
||||
* bot.errorBoundary(errHandler, middleware0, middleware1, middleware2)
|
||||
*
|
||||
* // Those will also be protected!
|
||||
* safe.on('message', middleware3)
|
||||
*
|
||||
* // No error from `middleware4` will reach the `errHandler` from above,
|
||||
* // as errors are suppressed.
|
||||
*
|
||||
* // do nothing on error (suppress error), and run outside middleware
|
||||
* const suppress = (_err: BotError, next: NextFunction) => { return next() }
|
||||
* safe.errorBoundary(suppress).on('edited_message', middleware4)
|
||||
* ```
|
||||
*
|
||||
* Check out the
|
||||
* [documentation](https://grammy.dev/guide/errors.html#error-boundaries) on
|
||||
* the website to learn more about error boundaries.
|
||||
*
|
||||
* @param errorHandler The error handler to use
|
||||
* @param middleware The middleware to protect
|
||||
*/
|
||||
errorBoundary(errorHandler: (error: BotError<C>, next: NextFunction) => MaybePromise<unknown>, ...middleware: Array<Middleware<C>>): Composer<C>;
|
||||
}
|
||||
/**
|
||||
* Type of the middleware that can be passed to `bot.hears`.
|
||||
*
|
||||
* This helper type can be used to annotate middleware functions that are
|
||||
* defined in one place, so that they have the correct type when passed to
|
||||
* `bot.hears` in a different place. For instance, this allows for more modular
|
||||
* code where handlers are defined in separate files.
|
||||
*/
|
||||
export type HearsMiddleware<C extends Context> = Middleware<HearsContext<C>>;
|
||||
/**
|
||||
* Type of the middleware that can be passed to `bot.command`.
|
||||
*
|
||||
* This helper type can be used to annotate middleware functions that are
|
||||
* defined in one place, so that they have the correct type when passed to
|
||||
* `bot.command` in a different place. For instance, this allows for more
|
||||
* modular code where handlers are defined in separate files.
|
||||
*/
|
||||
export type CommandMiddleware<C extends Context> = Middleware<CommandContext<C>>;
|
||||
/**
|
||||
* Type of the middleware that can be passed to `bot.callbackQuery`.
|
||||
*
|
||||
* This helper type can be used to annotate middleware functions that are
|
||||
* defined in one place, so that they have the correct type when passed to
|
||||
* `bot.callbackQuery` in a different place. For instance, this allows for more
|
||||
* modular code where handlers are defined in separate files.
|
||||
*/
|
||||
export type CallbackQueryMiddleware<C extends Context> = Middleware<CallbackQueryContext<C>>;
|
||||
/**
|
||||
* Type of the middleware that can be passed to `bot.gameQuery`.
|
||||
*
|
||||
* This helper type can be used to annotate middleware functions that are
|
||||
* defined in one place, so that they have the correct type when passed to
|
||||
* `bot.gameQuery` in a different place. For instance, this allows for more
|
||||
* modular code where handlers are defined in separate files.
|
||||
*/
|
||||
export type GameQueryMiddleware<C extends Context> = Middleware<GameQueryContext<C>>;
|
||||
/**
|
||||
* Type of the middleware that can be passed to `bot.inlineQuery`.
|
||||
*
|
||||
* This helper type can be used to annotate middleware functions that are
|
||||
* defined in one place, so that they have the correct type when passed to
|
||||
* `bot.inlineQuery` in a different place. For instance, this allows for more
|
||||
* modular code where handlers are defined in separate files.
|
||||
*/
|
||||
export type InlineQueryMiddleware<C extends Context> = Middleware<InlineQueryContext<C>>;
|
||||
/**
|
||||
* Type of the middleware that can be passed to `bot.chosenInlineResult`.
|
||||
*
|
||||
* This helper type can be used to annotate middleware functions that are
|
||||
* defined in one place, so that they have the correct type when passed to
|
||||
* `bot.chosenInlineResult` in a different place. For instance, this allows for more
|
||||
* modular code where handlers are defined in separate files.
|
||||
*/
|
||||
export type ChosenInlineResultMiddleware<C extends Context> = Middleware<ChosenInlineResultContext<C>>;
|
||||
/**
|
||||
* Type of the middleware that can be passed to `bot.chatType`.
|
||||
*
|
||||
* This helper type can be used to annotate middleware functions that are
|
||||
* defined in one place, so that they have the correct type when passed to
|
||||
* `bot.chatType` in a different place. For instance, this allows for more
|
||||
* modular code where handlers are defined in separate files.
|
||||
*/
|
||||
export type ChatTypeMiddleware<C extends Context, T extends Chat["type"]> = Middleware<ChatTypeContext<C, T>>;
|
||||
export {};
|
629
node_modules/grammy/out/composer.js
generated
vendored
Normal file
629
node_modules/grammy/out/composer.js
generated
vendored
Normal file
@ -0,0 +1,629 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Composer = exports.run = exports.BotError = void 0;
|
||||
const context_js_1 = require("./context.js");
|
||||
// === Middleware errors
|
||||
/**
|
||||
* This error is thrown when middleware throws. It simply wraps the original
|
||||
* error (accessible via the `error` property), but also provides access to the
|
||||
* respective context object that was processed while the error occurred.
|
||||
*/
|
||||
class BotError extends Error {
|
||||
constructor(error, ctx) {
|
||||
super(generateBotErrorMessage(error));
|
||||
this.error = error;
|
||||
this.ctx = ctx;
|
||||
this.name = "BotError";
|
||||
if (error instanceof Error)
|
||||
this.stack = error.stack;
|
||||
}
|
||||
}
|
||||
exports.BotError = BotError;
|
||||
function generateBotErrorMessage(error) {
|
||||
let msg;
|
||||
if (error instanceof Error) {
|
||||
msg = `${error.name} in middleware: ${error.message}`;
|
||||
}
|
||||
else {
|
||||
const type = typeof error;
|
||||
msg = `Non-error value of type ${type} thrown in middleware`;
|
||||
switch (type) {
|
||||
case "bigint":
|
||||
case "boolean":
|
||||
case "number":
|
||||
case "symbol":
|
||||
msg += `: ${error}`;
|
||||
break;
|
||||
case "string":
|
||||
msg += `: ${String(error).substring(0, 50)}`;
|
||||
break;
|
||||
default:
|
||||
msg += "!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
// === Middleware base functions
|
||||
function flatten(mw) {
|
||||
return typeof mw === "function"
|
||||
? mw
|
||||
: (ctx, next) => mw.middleware()(ctx, next);
|
||||
}
|
||||
function concat(first, andThen) {
|
||||
return async (ctx, next) => {
|
||||
let nextCalled = false;
|
||||
await first(ctx, async () => {
|
||||
if (nextCalled)
|
||||
throw new Error("`next` already called before!");
|
||||
else
|
||||
nextCalled = true;
|
||||
await andThen(ctx, next);
|
||||
});
|
||||
};
|
||||
}
|
||||
function pass(_ctx, next) {
|
||||
return next();
|
||||
}
|
||||
const leaf = () => Promise.resolve();
|
||||
/**
|
||||
* Runs some given middleware function with a given context object.
|
||||
*
|
||||
* @param middleware The middleware to run
|
||||
* @param ctx The context to use
|
||||
*/
|
||||
async function run(middleware, ctx) {
|
||||
await middleware(ctx, leaf);
|
||||
}
|
||||
exports.run = run;
|
||||
// === Composer
|
||||
/**
|
||||
* The composer is the heart of the middleware system in grammY. It is also the
|
||||
* superclass of `Bot`. Whenever you call `use` or `on` or some of the other
|
||||
* methods on your bot, you are in fact using the underlying composer instance
|
||||
* to register your middleware.
|
||||
*
|
||||
* If you're just getting started, you do not need to worry about what
|
||||
* middleware is, or about how to use a composer.
|
||||
*
|
||||
* On the other hand, if you want to dig deeper into how grammY implements
|
||||
* middleware, check out the
|
||||
* [documentation](https://grammy.dev/advanced/middleware.html) on the website.
|
||||
*/
|
||||
class Composer {
|
||||
/**
|
||||
* Constructs a new composer based on the provided middleware. If no
|
||||
* middleware is given, the composer instance will simply make all context
|
||||
* objects pass through without touching them.
|
||||
*
|
||||
* @param middleware The middleware to compose
|
||||
*/
|
||||
constructor(...middleware) {
|
||||
this.handler = middleware.length === 0
|
||||
? pass
|
||||
: middleware.map(flatten).reduce(concat);
|
||||
}
|
||||
middleware() {
|
||||
return this.handler;
|
||||
}
|
||||
/**
|
||||
* Registers some middleware that receives all updates. It is installed by
|
||||
* concatenating it to the end of all previously installed middleware.
|
||||
*
|
||||
* Often, this method is used to install middleware that behaves like a
|
||||
* plugin, for example session middleware.
|
||||
* ```ts
|
||||
* bot.use(session())
|
||||
* ```
|
||||
*
|
||||
* This method returns a new instance of composer. The returned instance can
|
||||
* be further extended, and all changes will be regarded here. Confer the
|
||||
* [documentation](https://grammy.dev/advanced/middleware.html) on the
|
||||
* website if you want to know more about how the middleware system in
|
||||
* grammY works, especially when it comes to chaining the method calls
|
||||
* (`use( ... ).use( ... ).use( ... )`).
|
||||
*
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
use(...middleware) {
|
||||
const composer = new Composer(...middleware);
|
||||
this.handler = concat(this.handler, flatten(composer));
|
||||
return composer;
|
||||
}
|
||||
/**
|
||||
* Registers some middleware that will only be executed for some specific
|
||||
* updates, namely those matching the provided filter query. Filter queries
|
||||
* are a concise way to specify which updates you are interested in.
|
||||
*
|
||||
* Here are some examples of valid filter queries:
|
||||
* ```ts
|
||||
* // All kinds of message updates
|
||||
* bot.on('message', ctx => { ... })
|
||||
*
|
||||
* // Only text messages
|
||||
* bot.on('message:text', ctx => { ... })
|
||||
*
|
||||
* // Only text messages with URL
|
||||
* bot.on('message:entities:url', ctx => { ... })
|
||||
*
|
||||
* // Text messages and text channel posts
|
||||
* bot.on(':text', ctx => { ... })
|
||||
*
|
||||
* // Messages with URL in text or caption (i.e. entities or caption entities)
|
||||
* bot.on('message::url', ctx => { ... })
|
||||
*
|
||||
* // Messages or channel posts with URL in text or caption
|
||||
* bot.on('::url', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* You can use autocomplete in VS Code to see all available filter queries.
|
||||
* Check out the
|
||||
* [documentation](https://grammy.dev/guide/filter-queries.html) on the
|
||||
* website to learn more about filter queries in grammY.
|
||||
*
|
||||
* It is possible to pass multiple filter queries in an array, i.e.
|
||||
* ```ts
|
||||
* // Matches all text messages and edited text messages that contain a URL
|
||||
* bot.on(['message:entities:url', 'edited_message:entities:url'], ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* Your middleware will be executed if _any of the provided filter queries_
|
||||
* matches (logical OR).
|
||||
*
|
||||
* If you instead want to match _all of the provided filter queries_
|
||||
* (logical AND), you can chain the `.on` calls:
|
||||
* ```ts
|
||||
* // Matches all messages and channel posts that both a) contain a URL and b) are forwards
|
||||
* bot.on('::url').on(':forward_date', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param filter The filter query to use, may also be an array of queries
|
||||
* @param middleware The middleware to register behind the given filter
|
||||
*/
|
||||
on(filter, ...middleware) {
|
||||
return this.filter(context_js_1.Context.has.filterQuery(filter), ...middleware);
|
||||
}
|
||||
/**
|
||||
* Registers some middleware that will only be executed when the message
|
||||
* contains some text. Is it possible to pass a regular expression to match:
|
||||
* ```ts
|
||||
* // Match some text (exact match)
|
||||
* bot.hears('I love grammY', ctx => ctx.reply('And grammY loves you! <3'))
|
||||
* // Match a regular expression
|
||||
* bot.hears(/\/echo (.+)/, ctx => ctx.reply(ctx.match[1]))
|
||||
* ```
|
||||
* Note how `ctx.match` will contain the result of the regular expression.
|
||||
* Here it is a `RegExpMatchArray` object, so `ctx.match[1]` refers to the
|
||||
* part of the regex that was matched by `(.+)`, i.e. the text that comes
|
||||
* after “/echo”.
|
||||
*
|
||||
* You can pass an array of triggers. Your middleware will be executed if at
|
||||
* least one of them matches.
|
||||
*
|
||||
* Both text and captions of the received messages will be scanned. For
|
||||
* example, when a photo is sent to the chat and its caption matches the
|
||||
* trigger, your middleware will be executed.
|
||||
*
|
||||
* If you only want to match text messages and not captions, you can do
|
||||
* this:
|
||||
* ```ts
|
||||
* // Only matches text messages (and channel posts) for the regex
|
||||
* bot.on(':text').hears(/\/echo (.+)/, ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param trigger The text to look for
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
hears(trigger, ...middleware) {
|
||||
return this.filter(context_js_1.Context.has.text(trigger), ...middleware);
|
||||
}
|
||||
/**
|
||||
* Registers some middleware that will only be executed when a certain
|
||||
* command is found.
|
||||
* ```ts
|
||||
* // Reacts to /start commands
|
||||
* bot.command('start', ctx => { ... })
|
||||
* // Reacts to /help commands
|
||||
* bot.command('help', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* The rest of the message (excluding the command, and trimmed) is provided
|
||||
* via `ctx.match`.
|
||||
*
|
||||
* > **Did you know?** You can use deep linking
|
||||
* > (https://core.telegram.org/bots/features#deep-linking) to let users
|
||||
* > start your bot with a custom payload. As an example, send someone the
|
||||
* > link https://t.me/name-of-your-bot?start=custom-payload and register a
|
||||
* > start command handler on your bot with grammY. As soon as the user
|
||||
* > starts your bot, you will receive `custom-payload` in the `ctx.match`
|
||||
* > property!
|
||||
* > ```ts
|
||||
* > bot.command('start', ctx => {
|
||||
* > const payload = ctx.match // will be 'custom-payload'
|
||||
* > })
|
||||
* > ```
|
||||
*
|
||||
* Note that commands are not matched in captions or in the middle of the
|
||||
* text.
|
||||
* ```ts
|
||||
* bot.command('start', ctx => { ... })
|
||||
* // ... does not match:
|
||||
* // A message saying: “some text /start some more text”
|
||||
* // A photo message with the caption “/start”
|
||||
* ```
|
||||
*
|
||||
* By default, commands are detected in channel posts, too. This means that
|
||||
* `ctx.message` is potentially `undefined`, so you should use `ctx.msg`
|
||||
* instead to grab both messages and channel posts. Alternatively, if you
|
||||
* want to limit your bot to finding commands only in private and group
|
||||
* chats, you can use `bot.on('message').command('start', ctx => { ... })`,
|
||||
* or even store a message-only version of your bot in a variable like so:
|
||||
* ```ts
|
||||
* const m = bot.on('message')
|
||||
*
|
||||
* m.command('start', ctx => { ... })
|
||||
* m.command('help', ctx => { ... })
|
||||
* // etc
|
||||
* ```
|
||||
*
|
||||
* If you need more freedom matching your commands, check out the `commands`
|
||||
* plugin.
|
||||
*
|
||||
* @param command The command to look for
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
command(command, ...middleware) {
|
||||
return this.filter(context_js_1.Context.has.command(command), ...middleware);
|
||||
}
|
||||
/**
|
||||
* Registers some middleware for certain chat types only. For example, you
|
||||
* can use this method to only receive updates from private chats. The four
|
||||
* chat types are `"channel"`, `"supergroup"`, `"group"`, and `"private"`.
|
||||
* This is especially useful when combined with other filtering logic. For
|
||||
* example, this is how can you respond to `/start` commands only from
|
||||
* private chats:
|
||||
* ```ts
|
||||
* bot.chatType("private").command("start", ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* Naturally, you can also use this method on its own.
|
||||
* ```ts
|
||||
* // Private chats only
|
||||
* bot.chatType("private", ctx => { ... });
|
||||
* // Channels only
|
||||
* bot.chatType("channel", ctx => { ... });
|
||||
* ```
|
||||
*
|
||||
* You can pass an array of chat types if you want your middleware to run
|
||||
* for any of several provided chat types.
|
||||
* ```ts
|
||||
* // Groups and supergroups only
|
||||
* bot.chatType(["group", "supergroup"], ctx => { ... });
|
||||
* ```
|
||||
* [Remember](https://grammy.dev/guide/context.html#shortcuts) also that you
|
||||
* can access the chat type via `ctx.chat.type`.
|
||||
*
|
||||
* @param chatType The chat type
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
chatType(chatType, ...middleware) {
|
||||
return this.filter(context_js_1.Context.has.chatType(chatType), ...middleware);
|
||||
}
|
||||
/**
|
||||
* Registers some middleware for callback queries, i.e. the updates that
|
||||
* Telegram delivers to your bot when a user clicks an inline button (that
|
||||
* is a button under a message).
|
||||
*
|
||||
* This method is essentially the same as calling
|
||||
* ```ts
|
||||
* bot.on('callback_query:data', ctx => { ... })
|
||||
* ```
|
||||
* but it also allows you to match the query data against a given text or
|
||||
* regular expression.
|
||||
*
|
||||
* ```ts
|
||||
* // Create an inline keyboard
|
||||
* const keyboard = new InlineKeyboard().text('Go!', 'button-payload')
|
||||
* // Send a message with the keyboard
|
||||
* await bot.api.sendMessage(chat_id, 'Press a button!', {
|
||||
* reply_markup: keyboard
|
||||
* })
|
||||
* // Listen to users pressing buttons with that specific payload
|
||||
* bot.callbackQuery('button-payload', ctx => { ... })
|
||||
*
|
||||
* // Listen to users pressing any button your bot ever sent
|
||||
* bot.on('callback_query:data', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* Always remember to call `answerCallbackQuery`—even if you don't perform
|
||||
* any action: https://core.telegram.org/bots/api#answercallbackquery
|
||||
* ```ts
|
||||
* bot.on('callback_query:data', async ctx => {
|
||||
* await ctx.answerCallbackQuery()
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* You can pass an array of triggers. Your middleware will be executed if at
|
||||
* least one of them matches.
|
||||
*
|
||||
* @param trigger The string to look for in the payload
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
callbackQuery(trigger, ...middleware) {
|
||||
return this.filter(context_js_1.Context.has.callbackQuery(trigger), ...middleware);
|
||||
}
|
||||
/**
|
||||
* Registers some middleware for game queries, i.e. the updates that
|
||||
* Telegram delivers to your bot when a user clicks an inline button for the
|
||||
* HTML5 games platform on Telegram.
|
||||
*
|
||||
* This method is essentially the same as calling
|
||||
* ```ts
|
||||
* bot.on('callback_query:game_short_name', ctx => { ... })
|
||||
* ```
|
||||
* but it also allows you to match the query data against a given text or
|
||||
* regular expression.
|
||||
*
|
||||
* You can pass an array of triggers. Your middleware will be executed if at
|
||||
* least one of them matches.
|
||||
*
|
||||
* @param trigger The string to look for in the payload
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
gameQuery(trigger, ...middleware) {
|
||||
return this.filter(context_js_1.Context.has.gameQuery(trigger), ...middleware);
|
||||
}
|
||||
/**
|
||||
* Registers middleware for inline queries. Telegram sends an inline query
|
||||
* to your bot whenever a user types “@your_bot_name ...” into a text field
|
||||
* in Telegram. You bot will then receive the entered search query and can
|
||||
* respond with a number of results (text, images, etc) that the user can
|
||||
* pick from to send a message _via_ your bot to the respective chat. Check
|
||||
* out https://core.telegram.org/bots/inline to read more about inline bots.
|
||||
*
|
||||
* > Note that you have to enable inline mode for you bot by contacting
|
||||
* > @BotFather first.
|
||||
*
|
||||
* ```ts
|
||||
* // Listen for users typing “@your_bot_name query”
|
||||
* bot.inlineQuery('query', async ctx => {
|
||||
* // Answer the inline query, confer https://core.telegram.org/bots/api#answerinlinequery
|
||||
* await ctx.answerInlineQuery( ... )
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param trigger The inline query text to match
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
inlineQuery(trigger, ...middleware) {
|
||||
return this.filter(context_js_1.Context.has.inlineQuery(trigger), ...middleware);
|
||||
}
|
||||
/**
|
||||
* Registers middleware for the ChosenInlineResult by the given id or ids.
|
||||
* ChosenInlineResult represents a result of an inline query that was
|
||||
* chosen by the user and sent to their chat partner. Check out
|
||||
* https://core.telegram.org/bots/api#choseninlineresult to read more
|
||||
* about chosen inline results.
|
||||
*
|
||||
* ```ts
|
||||
* bot.chosenInlineResult('id', async ctx => {
|
||||
* const id = ctx.result_id;
|
||||
* // Your code
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param resultId An id or array of ids
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
chosenInlineResult(resultId, ...middleware) {
|
||||
return this.filter(context_js_1.Context.has.chosenInlineResult(resultId), ...middleware);
|
||||
}
|
||||
filter(predicate, ...middleware) {
|
||||
const composer = new Composer(...middleware);
|
||||
this.branch(predicate, composer, pass);
|
||||
return composer;
|
||||
}
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Registers middleware behind a custom filter function that operates on the
|
||||
* context object and decides whether or not to execute the middleware. In
|
||||
* other words, the middleware will only be executed if the given predicate
|
||||
* returns `false` for the given context object. Otherwise, it will be
|
||||
* skipped and the next middleware will be executed. Note that the predicate
|
||||
* may be asynchronous, i.e. it can return a Promise of a boolean.
|
||||
*
|
||||
* This method is the same using `filter` (normal usage) with a negated
|
||||
* predicate.
|
||||
*
|
||||
* @param predicate The predicate to check
|
||||
* @param middleware The middleware to register
|
||||
*/
|
||||
drop(predicate, ...middleware) {
|
||||
return this.filter(async (ctx) => !(await predicate(ctx)), ...middleware);
|
||||
}
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Registers some middleware that runs concurrently to the executing
|
||||
* middleware stack.
|
||||
* ```ts
|
||||
* bot.use( ... ) // will run first
|
||||
* bot.fork( ... ) // will be started second, but run concurrently
|
||||
* bot.use( ... ) // will also be run second
|
||||
* ```
|
||||
* In the first middleware, as soon as `next`'s Promise resolves, both forks
|
||||
* have completed.
|
||||
*
|
||||
* Both the fork and the downstream middleware are awaited with
|
||||
* `Promise.all`, so you will only be to catch up to one error (the one that
|
||||
* is thrown first).
|
||||
*
|
||||
* In opposite to the other middleware methods on composer, `fork` does not
|
||||
* return simply return the composer connected to the main middleware stack.
|
||||
* Instead, it returns the created composer _of the fork_ connected to the
|
||||
* middleware stack. This allows for the following pattern.
|
||||
* ```ts
|
||||
* // Middleware will be run concurrently!
|
||||
* bot.fork().on('message', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param middleware The middleware to run concurrently
|
||||
*/
|
||||
fork(...middleware) {
|
||||
const composer = new Composer(...middleware);
|
||||
const fork = flatten(composer);
|
||||
this.use((ctx, next) => Promise.all([next(), run(fork, ctx)]));
|
||||
return composer;
|
||||
}
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Executes some middleware that can be generated on the fly for each
|
||||
* context. Pass a factory function that creates some middleware (or a
|
||||
* middleware array even). The factory function will be called once per
|
||||
* context, and its result will be executed with the context object.
|
||||
* ```ts
|
||||
* // The middleware returned by `createMyMiddleware` will be used only once
|
||||
* bot.lazy(ctx => createMyMiddleware(ctx))
|
||||
* ```
|
||||
*
|
||||
* You may generate this middleware in an `async` fashion.
|
||||
*
|
||||
* You can decide to return an empty array (`[]`) if you don't want to run
|
||||
* any middleware for a given context object. This is equivalent to
|
||||
* returning an empty instance of `Composer`.
|
||||
*
|
||||
* @param middlewareFactory The factory function creating the middleware
|
||||
*/
|
||||
lazy(middlewareFactory) {
|
||||
return this.use(async (ctx, next) => {
|
||||
const middleware = await middlewareFactory(ctx);
|
||||
const arr = Array.isArray(middleware) ? middleware : [middleware];
|
||||
await flatten(new Composer(...arr))(ctx, next);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* _Not to be confused with the `router` plugin._
|
||||
*
|
||||
* This method is an alternative to the `router` plugin. It allows you to
|
||||
* branch between different middleware per context object. You can pass two
|
||||
* things to it:
|
||||
* 1. A routing function
|
||||
* 2. Different middleware identified by key
|
||||
*
|
||||
* The routing function decides based on the context object which middleware
|
||||
* to run. Each middleware is identified by a key, so the routing function
|
||||
* simply returns the key of that middleware.
|
||||
* ```ts
|
||||
* // Define different route handlers
|
||||
* const routeHandlers = {
|
||||
* evenUpdates: (ctx: Context) => { ... }
|
||||
* oddUpdates: (ctx: Context) => { ... }
|
||||
* }
|
||||
* // Decide for a context object which one to pick
|
||||
* const router = (ctx: Context) => ctx.update.update_id % 2 === 0
|
||||
* ? 'evenUpdates'
|
||||
* : 'oddUpdates'
|
||||
* // Route it!
|
||||
* bot.route(router, routeHandlers)
|
||||
* ```
|
||||
*
|
||||
* Optionally, you can pass a third option that is used as fallback
|
||||
* middleware if your route function returns `undefined`, or if the key
|
||||
* returned by your router has no middleware associated with it.
|
||||
*
|
||||
* This method may need less setup than first instantiating a `Router`, but
|
||||
* for more complex setups, having a `Router` may be more readable.
|
||||
*
|
||||
* @param router The routing function to use
|
||||
* @param routeHandlers Handlers for every route
|
||||
* @param fallback Optional fallback middleware if no route matches
|
||||
*/
|
||||
route(router, routeHandlers, fallback = pass) {
|
||||
return this.lazy(async (ctx) => {
|
||||
var _a;
|
||||
const route = await router(ctx);
|
||||
return (_a = (route === undefined || !routeHandlers[route]
|
||||
? fallback
|
||||
: routeHandlers[route])) !== null && _a !== void 0 ? _a : [];
|
||||
});
|
||||
}
|
||||
/**
|
||||
* > This is an advanced method of grammY.
|
||||
*
|
||||
* Allows you to branch between two cases for a given context object.
|
||||
*
|
||||
* This method takes a predicate function that is tested once per context
|
||||
* object. If it returns `true`, the first supplied middleware is executed.
|
||||
* If it returns `false`, the second supplied middleware is executed. Note
|
||||
* that the predicate may be asynchronous, i.e. it can return a Promise of a
|
||||
* boolean.
|
||||
*
|
||||
* @param predicate The predicate to check
|
||||
* @param trueMiddleware The middleware for the `true` case
|
||||
* @param falseMiddleware The middleware for the `false` case
|
||||
*/
|
||||
branch(predicate, trueMiddleware, falseMiddleware) {
|
||||
return this.lazy(async (ctx) => (await predicate(ctx)) ? trueMiddleware : falseMiddleware);
|
||||
}
|
||||
/**
|
||||
* > This is an advanced function of grammY.
|
||||
*
|
||||
* Installs an error boundary that catches errors that happen only inside
|
||||
* the given middleware. This allows you to install custom error handlers
|
||||
* that protect some parts of your bot. Errors will not be able to bubble
|
||||
* out of this part of your middleware system, unless the supplied error
|
||||
* handler rethrows them, in which case the next surrounding error boundary
|
||||
* will catch the error.
|
||||
*
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* function errHandler(err: BotError) {
|
||||
* console.error('Error boundary caught error!', err)
|
||||
* }
|
||||
*
|
||||
* const safe =
|
||||
* // All passed middleware will be protected by the error boundary.
|
||||
* bot.errorBoundary(errHandler, middleware0, middleware1, middleware2)
|
||||
*
|
||||
* // Those will also be protected!
|
||||
* safe.on('message', middleware3)
|
||||
*
|
||||
* // No error from `middleware4` will reach the `errHandler` from above,
|
||||
* // as errors are suppressed.
|
||||
*
|
||||
* // do nothing on error (suppress error), and run outside middleware
|
||||
* const suppress = (_err: BotError, next: NextFunction) => { return next() }
|
||||
* safe.errorBoundary(suppress).on('edited_message', middleware4)
|
||||
* ```
|
||||
*
|
||||
* Check out the
|
||||
* [documentation](https://grammy.dev/guide/errors.html#error-boundaries) on
|
||||
* the website to learn more about error boundaries.
|
||||
*
|
||||
* @param errorHandler The error handler to use
|
||||
* @param middleware The middleware to protect
|
||||
*/
|
||||
errorBoundary(errorHandler, ...middleware) {
|
||||
const composer = new Composer(...middleware);
|
||||
const bound = flatten(composer);
|
||||
this.use(async (ctx, next) => {
|
||||
let nextCalled = false;
|
||||
const cont = () => ((nextCalled = true), Promise.resolve());
|
||||
try {
|
||||
await bound(ctx, cont);
|
||||
}
|
||||
catch (err) {
|
||||
nextCalled = false;
|
||||
await errorHandler(new BotError(err, ctx), cont);
|
||||
}
|
||||
if (nextCalled)
|
||||
await next();
|
||||
});
|
||||
return composer;
|
||||
}
|
||||
}
|
||||
exports.Composer = Composer;
|
1238
node_modules/grammy/out/context.d.ts
generated
vendored
Normal file
1238
node_modules/grammy/out/context.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1426
node_modules/grammy/out/context.js
generated
vendored
Normal file
1426
node_modules/grammy/out/context.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
54
node_modules/grammy/out/convenience/constants.d.ts
generated
vendored
Normal file
54
node_modules/grammy/out/convenience/constants.d.ts
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Contains lists of constants which are useful when working with the Bot API.
|
||||
*/
|
||||
export declare const API_CONSTANTS: Readonly<{
|
||||
/**
|
||||
* List of all available update types. Useful if you want to receive all
|
||||
* updates from the Bot API, rather than just those that are delivered by
|
||||
* default.
|
||||
*
|
||||
* The main use case for this is when you want to receive `chat_member`
|
||||
* updates, as they need to be enabled first. Use it like so:
|
||||
*
|
||||
* ```ts
|
||||
* // Built-in polling:
|
||||
* bot.start({ allowed_updates: ALL_UPDATE_TYPES });
|
||||
* // grammY runner:
|
||||
* run(bot, { runner: { fetch: { allowed_updates: ALL_UPDATE_TYPES } } });
|
||||
* // Webhooks:
|
||||
* await bot.api.setWebhook(url, { allowed_updates: ALL_UPDATE_TYPES });
|
||||
* ```
|
||||
*/
|
||||
readonly ALL_UPDATE_TYPES: readonly ["message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_join_request", "chat_member"];
|
||||
/**
|
||||
* An object containing all available chat permissions. Useful if you want
|
||||
* to lift restrictions from a user, as this action requires you to pass
|
||||
* `true` for all permissions. Use it like so:
|
||||
*
|
||||
* ```ts
|
||||
* // On `Bot`:
|
||||
* await bot.api.restrictChatMember(chat_id, user_id, ALL_CHAT_PERMISSIONS);
|
||||
* // On `Api`:
|
||||
* await ctx.api.restrictChatMember(chat_id, user_id, ALL_CHAT_PERMISSIONS);
|
||||
* // On `Context`:
|
||||
* await ctx.restrictChatMember(user_id, ALL_CHAT_PERMISSIONS);
|
||||
* await ctx.restrictAuthor(ALL_CHAT_PERMISSIONS);
|
||||
* ```
|
||||
*/
|
||||
readonly ALL_CHAT_PERMISSIONS: {
|
||||
readonly can_send_messages: true;
|
||||
readonly can_send_audios: true;
|
||||
readonly can_send_documents: true;
|
||||
readonly can_send_photos: true;
|
||||
readonly can_send_videos: true;
|
||||
readonly can_send_video_notes: true;
|
||||
readonly can_send_voice_notes: true;
|
||||
readonly can_send_polls: true;
|
||||
readonly can_send_other_messages: true;
|
||||
readonly can_add_web_page_previews: true;
|
||||
readonly can_change_info: true;
|
||||
readonly can_invite_users: true;
|
||||
readonly can_pin_messages: true;
|
||||
readonly can_manage_topics: true;
|
||||
};
|
||||
}>;
|
60
node_modules/grammy/out/convenience/constants.js
generated
vendored
Normal file
60
node_modules/grammy/out/convenience/constants.js
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.API_CONSTANTS = void 0;
|
||||
const bot_js_1 = require("../bot.js");
|
||||
const ALL_UPDATE_TYPES = [...bot_js_1.DEFAULT_UPDATE_TYPES, "chat_member"];
|
||||
const ALL_CHAT_PERMISSIONS = {
|
||||
can_send_messages: true,
|
||||
can_send_audios: true,
|
||||
can_send_documents: true,
|
||||
can_send_photos: true,
|
||||
can_send_videos: true,
|
||||
can_send_video_notes: true,
|
||||
can_send_voice_notes: true,
|
||||
can_send_polls: true,
|
||||
can_send_other_messages: true,
|
||||
can_add_web_page_previews: true,
|
||||
can_change_info: true,
|
||||
can_invite_users: true,
|
||||
can_pin_messages: true,
|
||||
can_manage_topics: true,
|
||||
};
|
||||
/**
|
||||
* Contains lists of constants which are useful when working with the Bot API.
|
||||
*/
|
||||
exports.API_CONSTANTS = Object.freeze({
|
||||
/**
|
||||
* List of all available update types. Useful if you want to receive all
|
||||
* updates from the Bot API, rather than just those that are delivered by
|
||||
* default.
|
||||
*
|
||||
* The main use case for this is when you want to receive `chat_member`
|
||||
* updates, as they need to be enabled first. Use it like so:
|
||||
*
|
||||
* ```ts
|
||||
* // Built-in polling:
|
||||
* bot.start({ allowed_updates: ALL_UPDATE_TYPES });
|
||||
* // grammY runner:
|
||||
* run(bot, { runner: { fetch: { allowed_updates: ALL_UPDATE_TYPES } } });
|
||||
* // Webhooks:
|
||||
* await bot.api.setWebhook(url, { allowed_updates: ALL_UPDATE_TYPES });
|
||||
* ```
|
||||
*/
|
||||
ALL_UPDATE_TYPES,
|
||||
/**
|
||||
* An object containing all available chat permissions. Useful if you want
|
||||
* to lift restrictions from a user, as this action requires you to pass
|
||||
* `true` for all permissions. Use it like so:
|
||||
*
|
||||
* ```ts
|
||||
* // On `Bot`:
|
||||
* await bot.api.restrictChatMember(chat_id, user_id, ALL_CHAT_PERMISSIONS);
|
||||
* // On `Api`:
|
||||
* await ctx.api.restrictChatMember(chat_id, user_id, ALL_CHAT_PERMISSIONS);
|
||||
* // On `Context`:
|
||||
* await ctx.restrictChatMember(user_id, ALL_CHAT_PERMISSIONS);
|
||||
* await ctx.restrictAuthor(ALL_CHAT_PERMISSIONS);
|
||||
* ```
|
||||
*/
|
||||
ALL_CHAT_PERMISSIONS,
|
||||
});
|
66
node_modules/grammy/out/convenience/frameworks.d.ts
generated
vendored
Normal file
66
node_modules/grammy/out/convenience/frameworks.d.ts
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
import { type Update } from "../types.js";
|
||||
/**
|
||||
* HTTP Web frameworks for which grammY provides compatible callback out of the
|
||||
* box.
|
||||
*/
|
||||
export type SupportedFrameworks = keyof typeof adapters;
|
||||
/**
|
||||
* Abstraction over a request-response cycle, providing access to the update, as
|
||||
* well as a mechanism for responding to the request and to end it.
|
||||
*/
|
||||
export interface ReqResHandler {
|
||||
/**
|
||||
* The update object sent from Telegram, usually resolves the request's JSON
|
||||
* body
|
||||
*/
|
||||
update: Promise<Update>;
|
||||
/**
|
||||
* X-Telegram-Bot-Api-Secret-Token header of the request, or undefined if
|
||||
* not present
|
||||
*/
|
||||
header?: string;
|
||||
/**
|
||||
* Ends the request immediately without body, called after every request
|
||||
* unless a webhook reply was performed
|
||||
*/
|
||||
end?: () => void;
|
||||
/**
|
||||
* Sends the specified JSON as a payload in the body, used for webhook
|
||||
* replies
|
||||
*/
|
||||
respond: (json: string) => unknown | Promise<unknown>;
|
||||
/**
|
||||
* Responds that the request is unauthorized due to mismatching
|
||||
* X-Telegram-Bot-Api-Secret-Token headers
|
||||
*/
|
||||
unauthorized: () => unknown | Promise<unknown>;
|
||||
/**
|
||||
* Some frameworks (e.g. Deno's std/http `listenAndServe`) assume that
|
||||
* handler returns something
|
||||
*/
|
||||
handlerReturn?: any;
|
||||
}
|
||||
/**
|
||||
* Middleware for a web framework. Creates a request-response handler for a
|
||||
* request. The handler will be used to integrate with the compatible framework.
|
||||
*/
|
||||
export type FrameworkAdapter = (...args: any[]) => ReqResHandler;
|
||||
export declare const adapters: {
|
||||
express: FrameworkAdapter;
|
||||
koa: FrameworkAdapter;
|
||||
fastify: FrameworkAdapter;
|
||||
serveHttp: FrameworkAdapter;
|
||||
"std/http": FrameworkAdapter;
|
||||
oak: FrameworkAdapter;
|
||||
http: FrameworkAdapter;
|
||||
https: FrameworkAdapter;
|
||||
"aws-lambda": FrameworkAdapter;
|
||||
"aws-lambda-async": FrameworkAdapter;
|
||||
azure: FrameworkAdapter;
|
||||
"next-js": FrameworkAdapter;
|
||||
sveltekit: FrameworkAdapter;
|
||||
cloudflare: FrameworkAdapter;
|
||||
"cloudflare-mod": FrameworkAdapter;
|
||||
hono: FrameworkAdapter;
|
||||
worktop: FrameworkAdapter;
|
||||
};
|
288
node_modules/grammy/out/convenience/frameworks.js
generated
vendored
Normal file
288
node_modules/grammy/out/convenience/frameworks.js
generated
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.adapters = void 0;
|
||||
const SECRET_HEADER = "X-Telegram-Bot-Api-Secret-Token";
|
||||
const SECRET_HEADER_LOWERCASE = SECRET_HEADER.toLowerCase();
|
||||
const WRONG_TOKEN_ERROR = "secret token is wrong";
|
||||
const ok = () => new Response(null, { status: 200 });
|
||||
const okJson = (json) => new Response(json, {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
const unauthorized = () => new Response('"unauthorized"', {
|
||||
status: 401,
|
||||
statusText: WRONG_TOKEN_ERROR,
|
||||
});
|
||||
/** express web framework */
|
||||
const express = (req, res) => ({
|
||||
update: Promise.resolve(req.body),
|
||||
header: req.header(SECRET_HEADER),
|
||||
end: () => res.end(),
|
||||
respond: (json) => {
|
||||
res.set("Content-Type", "application/json");
|
||||
res.send(json);
|
||||
},
|
||||
unauthorized: () => {
|
||||
res.status(401).send(WRONG_TOKEN_ERROR);
|
||||
},
|
||||
});
|
||||
/** koa web framework */
|
||||
const koa = (ctx) => ({
|
||||
update: Promise.resolve(ctx.request.body),
|
||||
header: ctx.get(SECRET_HEADER),
|
||||
end: () => {
|
||||
ctx.body = "";
|
||||
},
|
||||
respond: (json) => {
|
||||
ctx.set("Content-Type", "application/json");
|
||||
ctx.response.body = json;
|
||||
},
|
||||
unauthorized: () => {
|
||||
ctx.status = 401;
|
||||
},
|
||||
});
|
||||
/** fastify web framework */
|
||||
const fastify = (req, reply) => ({
|
||||
update: Promise.resolve(req.body),
|
||||
header: req.headers[SECRET_HEADER_LOWERCASE],
|
||||
end: () => reply.status(200).send(),
|
||||
respond: (json) => reply.send(json),
|
||||
unauthorized: () => reply.code(401).send(WRONG_TOKEN_ERROR),
|
||||
});
|
||||
const serveHttp = (requestEvent) => ({
|
||||
update: requestEvent.request.json(),
|
||||
header: requestEvent.request.headers.get(SECRET_HEADER) || undefined,
|
||||
end: () => requestEvent.respondWith(ok()),
|
||||
respond: (json) => requestEvent.respondWith(okJson(json)),
|
||||
unauthorized: () => requestEvent.respondWith(unauthorized()),
|
||||
});
|
||||
/** std/http web server */
|
||||
const stdHttp = (req) => {
|
||||
let resolveResponse;
|
||||
return {
|
||||
update: req.json(),
|
||||
header: req.headers.get(SECRET_HEADER) || undefined,
|
||||
end: () => {
|
||||
if (resolveResponse)
|
||||
resolveResponse(ok());
|
||||
},
|
||||
respond: (json) => {
|
||||
if (resolveResponse)
|
||||
resolveResponse(okJson(json));
|
||||
},
|
||||
unauthorized: () => {
|
||||
if (resolveResponse)
|
||||
resolveResponse(unauthorized());
|
||||
},
|
||||
handlerReturn: new Promise((resolve) => {
|
||||
resolveResponse = resolve;
|
||||
}),
|
||||
};
|
||||
};
|
||||
/** oak web framework */
|
||||
const oak = (ctx) => ({
|
||||
update: ctx.request.body({ type: "json" }).value,
|
||||
header: ctx.request.headers.get(SECRET_HEADER) || undefined,
|
||||
end: () => {
|
||||
ctx.response.status = 200;
|
||||
},
|
||||
respond: (json) => {
|
||||
ctx.response.type = "json";
|
||||
ctx.response.body = json;
|
||||
},
|
||||
unauthorized: () => {
|
||||
ctx.response.status = 401;
|
||||
},
|
||||
});
|
||||
/** Node.js native 'http' and 'https' modules */
|
||||
const http = (req, res) => {
|
||||
const secretHeaderFromRequest = req.headers[SECRET_HEADER_LOWERCASE];
|
||||
return {
|
||||
update: new Promise((resolve, reject) => {
|
||||
const chunks = [];
|
||||
req.on("data", (chunk) => chunks.push(chunk))
|
||||
.once("end", () => {
|
||||
// @ts-ignore `Buffer` is Node-only
|
||||
const raw = Buffer.concat(chunks).toString("utf-8");
|
||||
resolve(JSON.parse(raw));
|
||||
})
|
||||
.once("error", reject);
|
||||
}),
|
||||
header: Array.isArray(secretHeaderFromRequest)
|
||||
? secretHeaderFromRequest[0]
|
||||
: secretHeaderFromRequest,
|
||||
end: () => res.end(),
|
||||
respond: (json) => res
|
||||
.writeHead(200, { "Content-Type": "application/json" })
|
||||
.end(json),
|
||||
unauthorized: () => res.writeHead(401).end(WRONG_TOKEN_ERROR),
|
||||
};
|
||||
};
|
||||
/** AWS lambda serverless functions */
|
||||
const awsLambda = (event, _context, callback) => ({
|
||||
update: JSON.parse(event.body),
|
||||
header: event.headers[SECRET_HEADER],
|
||||
end: () => callback(null, { statusCode: 200 }),
|
||||
respond: (json) => callback(null, {
|
||||
statusCode: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: json,
|
||||
}),
|
||||
unauthorized: () => callback(null, { statusCode: 401 }),
|
||||
});
|
||||
/** AWS lambda async/await serverless functions */
|
||||
const awsLambdaAsync = (event, _context) => {
|
||||
let resolveResponse;
|
||||
return {
|
||||
update: JSON.parse(event.body),
|
||||
header: event.headers[SECRET_HEADER],
|
||||
end: () => resolveResponse({ statusCode: 200 }),
|
||||
respond: (json) => resolveResponse({
|
||||
statusCode: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: json,
|
||||
}),
|
||||
unauthorized: () => resolveResponse({ statusCode: 401 }),
|
||||
handlerReturn: new Promise((resolve) => {
|
||||
resolveResponse = resolve;
|
||||
}),
|
||||
};
|
||||
};
|
||||
/** Azure Functions */
|
||||
const azure = (context, req) => ({
|
||||
update: Promise.resolve(req.body),
|
||||
header: context.res.headers[SECRET_HEADER],
|
||||
end: () => (context.res = {
|
||||
status: 200,
|
||||
body: "",
|
||||
}),
|
||||
respond: (json) => {
|
||||
context.res.set("Content-Type", "application/json");
|
||||
context.res.send(json);
|
||||
},
|
||||
unauthorized: () => {
|
||||
context.res.send(401, WRONG_TOKEN_ERROR);
|
||||
},
|
||||
});
|
||||
/** Next.js Serverless Functions */
|
||||
const nextJs = (req, res) => ({
|
||||
update: Promise.resolve(req.body),
|
||||
header: req.headers[SECRET_HEADER_LOWERCASE],
|
||||
end: () => res.end(),
|
||||
respond: (json) => res.status(200).json(json),
|
||||
unauthorized: () => res.status(401).send(WRONG_TOKEN_ERROR),
|
||||
});
|
||||
/** Sveltekit Serverless Functions */
|
||||
const sveltekit = ({ request }) => {
|
||||
let resolveResponse;
|
||||
return {
|
||||
update: Promise.resolve(request.json()),
|
||||
header: request.headers.get(SECRET_HEADER) || undefined,
|
||||
end: () => {
|
||||
if (resolveResponse)
|
||||
resolveResponse(ok());
|
||||
},
|
||||
respond: (json) => {
|
||||
if (resolveResponse)
|
||||
resolveResponse(okJson(json));
|
||||
},
|
||||
unauthorized: () => {
|
||||
if (resolveResponse)
|
||||
resolveResponse(unauthorized());
|
||||
},
|
||||
handlerReturn: new Promise((resolve) => {
|
||||
resolveResponse = resolve;
|
||||
}),
|
||||
};
|
||||
};
|
||||
/** Native CloudFlare workers (service worker) */
|
||||
const cloudflare = (event) => {
|
||||
let resolveResponse;
|
||||
event.respondWith(new Promise((resolve) => {
|
||||
resolveResponse = resolve;
|
||||
}));
|
||||
return {
|
||||
update: event.request.json(),
|
||||
header: event.request.headers.get(SECRET_HEADER) || undefined,
|
||||
end: () => {
|
||||
resolveResponse(ok());
|
||||
},
|
||||
respond: (json) => {
|
||||
resolveResponse(okJson(json));
|
||||
},
|
||||
unauthorized: () => {
|
||||
resolveResponse(unauthorized());
|
||||
},
|
||||
};
|
||||
};
|
||||
/** Native CloudFlare workers (module worker) */
|
||||
const cloudflareModule = (request) => {
|
||||
let resolveResponse;
|
||||
return {
|
||||
update: request.json(),
|
||||
header: request.headers.get(SECRET_HEADER) || undefined,
|
||||
end: () => {
|
||||
resolveResponse(ok());
|
||||
},
|
||||
respond: (json) => {
|
||||
resolveResponse(okJson(json));
|
||||
},
|
||||
unauthorized: () => {
|
||||
resolveResponse(unauthorized());
|
||||
},
|
||||
handlerReturn: new Promise((resolve) => {
|
||||
resolveResponse = resolve;
|
||||
}),
|
||||
};
|
||||
};
|
||||
/** hono web framework */
|
||||
const hono = (ctx) => {
|
||||
let resolveResponse;
|
||||
return {
|
||||
update: ctx.req.json(),
|
||||
header: ctx.req.headers.get(SECRET_HEADER) || undefined,
|
||||
end: () => {
|
||||
resolveResponse(ctx.body());
|
||||
},
|
||||
respond: (json) => {
|
||||
ctx.header('Content-Type", "application/json');
|
||||
resolveResponse(ctx.body(json));
|
||||
},
|
||||
unauthorized: () => {
|
||||
ctx.status(401);
|
||||
ctx.statusText(WRONG_TOKEN_ERROR);
|
||||
resolveResponse(ctx.body());
|
||||
},
|
||||
handlerReturn: new Promise((resolve) => {
|
||||
resolveResponse = resolve;
|
||||
}),
|
||||
};
|
||||
};
|
||||
/** worktop CloudFlare workers framework */
|
||||
const worktop = (req, res) => ({
|
||||
update: Promise.resolve(req.body.json()),
|
||||
header: req.headers.get(SECRET_HEADER),
|
||||
end: () => res.end(),
|
||||
respond: (json) => res.send(200, json),
|
||||
unauthorized: () => res.send(401, WRONG_TOKEN_ERROR),
|
||||
});
|
||||
// Please open a PR if you want to add another adapter
|
||||
exports.adapters = {
|
||||
express,
|
||||
koa,
|
||||
fastify,
|
||||
serveHttp,
|
||||
"std/http": stdHttp,
|
||||
oak,
|
||||
http,
|
||||
https: http,
|
||||
"aws-lambda": awsLambda,
|
||||
"aws-lambda-async": awsLambdaAsync,
|
||||
azure,
|
||||
"next-js": nextJs,
|
||||
sveltekit,
|
||||
cloudflare,
|
||||
"cloudflare-mod": cloudflareModule,
|
||||
hono,
|
||||
worktop,
|
||||
};
|
401
node_modules/grammy/out/convenience/inline_query.d.ts
generated
vendored
Normal file
401
node_modules/grammy/out/convenience/inline_query.d.ts
generated
vendored
Normal file
@ -0,0 +1,401 @@
|
||||
import { type InlineQueryResultArticle, type InlineQueryResultAudio, type InlineQueryResultCachedAudio, type InlineQueryResultCachedDocument, type InlineQueryResultCachedGif, type InlineQueryResultCachedMpeg4Gif, type InlineQueryResultCachedPhoto, type InlineQueryResultCachedSticker, type InlineQueryResultCachedVideo, type InlineQueryResultCachedVoice, type InlineQueryResultContact, type InlineQueryResultDocument, type InlineQueryResultGame, type InlineQueryResultGif, type InlineQueryResultLocation, type InlineQueryResultMpeg4Gif, type InlineQueryResultPhoto, type InlineQueryResultVenue, type InlineQueryResultVideo, type InlineQueryResultVoice, type InputContactMessageContent, type InputInvoiceMessageContent, type InputLocationMessageContent, type InputTextMessageContent, type InputVenueMessageContent, type LabeledPrice } from "../types.js";
|
||||
type InlineQueryResultOptions<T, K extends keyof T> = Omit<T, "type" | "id" | "input_message_content" | K>;
|
||||
type OptionalKeys<T> = {
|
||||
[K in keyof T]-?: undefined extends T[K] ? K : never;
|
||||
};
|
||||
type OptionalFields<T> = Pick<T, OptionalKeys<T>[keyof T]>;
|
||||
/**
|
||||
* Holds a number of helper methods for building `InlineQueryResult*` objects.
|
||||
*
|
||||
* For example, letting the user pick one out of three photos can be done like
|
||||
* this.
|
||||
*
|
||||
* ```ts
|
||||
* const results = [
|
||||
* InlineQueryResultBuilder.photo('id0', 'https://grammy.dev/images/Y.png'),
|
||||
* InlineQueryResultBuilder.photo('id1', 'https://grammy.dev/images/Y.png'),
|
||||
* InlineQueryResultBuilder.photo('id2', 'https://grammy.dev/images/Y.png'),
|
||||
* ];
|
||||
* await ctx.answerInlineQuery(results)
|
||||
* ```
|
||||
*
|
||||
* If you want the message content to be different from the content in the
|
||||
* inline query result, you can perform another method call on the resulting
|
||||
* objects.
|
||||
*
|
||||
* ```ts
|
||||
* const results = [
|
||||
* InlineQueryResultBuilder.photo("id0", "https://grammy.dev/images/Y.png")
|
||||
* .text("Picked photo 0!"),
|
||||
* InlineQueryResultBuilder.photo("id1", "https://grammy.dev/images/Y.png")
|
||||
* .text("Picked photo 1!"),
|
||||
* InlineQueryResultBuilder.photo("id2", "https://grammy.dev/images/Y.png")
|
||||
* .text("Picked photo 2!"),
|
||||
* ];
|
||||
* await ctx.answerInlineQuery(results)
|
||||
* ```
|
||||
*
|
||||
* Be sure to check the
|
||||
* [documentation](https://core.telegram.org/bots/api#inline-mode) on inline
|
||||
* mode.
|
||||
*/
|
||||
export declare const InlineQueryResultBuilder: {
|
||||
/**
|
||||
* Builds an InlineQueryResultArticle object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultarticle. Requires you
|
||||
* to specify the actual message content by calling another function on the
|
||||
* object returned from this method.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 Bytes
|
||||
* @param title Title of the result
|
||||
* @param options Remaining options
|
||||
*/
|
||||
article(id: string, title: string, options?: InlineQueryResultOptions<InlineQueryResultArticle, "title">): {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultArticle;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultArticle;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultArticle;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultArticle;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultArticle;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultAudio object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultaudio.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title
|
||||
* @param audio_url A valid URL for the audio file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
audio(id: string, title: string, audio_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultAudio, "title" | "audio_url">): InlineQueryResultAudio & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultAudio;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultAudio;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultAudio;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultAudio;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultAudio;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedAudio object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedaudio.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param audio_file_id A valid file identifier for the audio file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
audioCached(id: string, audio_file_id: string, options?: InlineQueryResultOptions<InlineQueryResultCachedAudio, "audio_file_id">): InlineQueryResultCachedAudio & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultCachedAudio;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultCachedAudio;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultCachedAudio;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultCachedAudio;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultCachedAudio;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultContact object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcontact.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 Bytes
|
||||
* @param phone_number Contact's phone number
|
||||
* @param first_name Contact's first name
|
||||
* @param options Remaining options
|
||||
*/
|
||||
contact(id: string, phone_number: string, first_name: string, options?: InlineQueryResultOptions<InlineQueryResultContact, "phone_number" | "first_name">): InlineQueryResultContact & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultContact;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultContact;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultContact;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultContact;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultContact;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultDocument object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultdocument with
|
||||
* mime_type set to "application/pdf".
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param document_url A valid URL for the file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
documentPdf(id: string, title: string, document_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultDocument, "mime_type" | "title" | "document_url">): InlineQueryResultDocument & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultDocument;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultDocument;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultDocument;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultDocument;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultDocument;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultDocument object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultdocument with
|
||||
* mime_type set to "application/zip".
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param document_url A valid URL for the file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
documentZip(id: string, title: string, document_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultDocument, "mime_type" | "title" | "document_url">): InlineQueryResultDocument & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultDocument;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultDocument;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultDocument;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultDocument;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultDocument;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedDocument object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcacheddocument.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param document_file_id A valid file identifier for the file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
documentCached(id: string, title: string, document_file_id: string, options?: InlineQueryResultOptions<InlineQueryResultCachedDocument, "title" | "document_file_id">): InlineQueryResultCachedDocument & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultCachedDocument;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultCachedDocument;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultCachedDocument;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultCachedDocument;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultCachedDocument;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultGame object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultgame.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param game_short_name Short name of the game
|
||||
* @param options Remaining options
|
||||
*/
|
||||
game(id: string, game_short_name: string, options?: InlineQueryResultOptions<InlineQueryResultGame, "game_short_name">): {
|
||||
reply_markup?: import("@grammyjs/types/markup.js").InlineKeyboardMarkup | undefined;
|
||||
type: string;
|
||||
id: string;
|
||||
game_short_name: string;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultGif object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultgif.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param gif_url A valid URL for the GIF file. File size must not exceed 1MB
|
||||
* @param thumbnail_url URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result
|
||||
* @param options Remaining options
|
||||
*/
|
||||
gif(id: string, gif_url: string | URL, thumbnail_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultGif, "gif_url" | "thumbnail_url">): InlineQueryResultGif & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultGif;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultGif;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultGif;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultGif;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultGif;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedGif object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedgif.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param gif_file_id A valid file identifier for the GIF file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
gifCached(id: string, gif_file_id: string, options?: InlineQueryResultOptions<InlineQueryResultCachedGif, "gif_file_id">): InlineQueryResultCachedGif & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultCachedGif;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultCachedGif;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultCachedGif;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultCachedGif;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultCachedGif;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultLocation object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultlocation.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 Bytes
|
||||
* @param title Location title
|
||||
* @param latitude Location latitude in degrees
|
||||
* @param longitude Location longitude in degrees
|
||||
* @param options Remaining options
|
||||
*/
|
||||
location(id: string, title: string, latitude: number, longitude: number, options?: InlineQueryResultOptions<InlineQueryResultLocation, "title" | "latitude" | "longitude">): InlineQueryResultLocation & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultLocation;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultLocation;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultLocation;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultLocation;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultLocation;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultMpeg4Gif object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultmpeg4gif.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param mpeg4_url A valid URL for the MPEG4 file. File size must not exceed 1MB
|
||||
* @param thumbnail_url URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result
|
||||
* @param options Remaining options
|
||||
*/
|
||||
mpeg4gif(id: string, mpeg4_url: string | URL, thumbnail_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultMpeg4Gif, "mpeg4_url" | "thumbnail_url">): InlineQueryResultMpeg4Gif & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultMpeg4Gif;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultMpeg4Gif;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultMpeg4Gif;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultMpeg4Gif;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultMpeg4Gif;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedMpeg4Gif object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedmpeg4gif.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param mpeg4_file_id A valid file identifier for the MPEG4 file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
mpeg4gifCached(id: string, mpeg4_file_id: string, options?: InlineQueryResultOptions<InlineQueryResultCachedMpeg4Gif, "mpeg4_file_id">): InlineQueryResultCachedMpeg4Gif & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultCachedMpeg4Gif;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultCachedMpeg4Gif;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultCachedMpeg4Gif;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultCachedMpeg4Gif;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultCachedMpeg4Gif;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultPhoto object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultphoto with the
|
||||
* thumbnail defaulting to the photo itself.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param photo_url A valid URL of the photo. Photo must be in JPEG format. Photo size must not exceed 5MB
|
||||
* @param options Remaining options
|
||||
*/
|
||||
photo(id: string, photo_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultPhoto, "photo_url">): InlineQueryResultPhoto & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultPhoto;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultPhoto;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultPhoto;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultPhoto;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultPhoto;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedPhoto object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedphoto.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param photo_file_id A valid file identifier of the photo
|
||||
* @param options Remaining options
|
||||
*/
|
||||
photoCached(id: string, photo_file_id: string, options?: InlineQueryResultOptions<InlineQueryResultCachedPhoto, "photo_file_id">): InlineQueryResultCachedPhoto & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultCachedPhoto;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultCachedPhoto;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultCachedPhoto;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultCachedPhoto;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultCachedPhoto;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedSticker object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedsticker.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param sticker_file_id A valid file identifier of the sticker
|
||||
* @param options Remaining options
|
||||
*/
|
||||
stickerCached(id: string, sticker_file_id: string, options?: InlineQueryResultOptions<InlineQueryResultCachedSticker, "sticker_file_id">): InlineQueryResultCachedSticker & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultCachedSticker;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultCachedSticker;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultCachedSticker;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultCachedSticker;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultCachedSticker;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultVenue object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultvenue.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 Bytes
|
||||
* @param title Title of the venue
|
||||
* @param latitude Latitude of the venue location in degrees
|
||||
* @param longitude Longitude of the venue location in degrees
|
||||
* @param address Address of the venue
|
||||
* @param options Remaining options
|
||||
*/
|
||||
venue(id: string, title: string, latitude: number, longitude: number, address: string, options?: InlineQueryResultOptions<InlineQueryResultVenue, "title" | "latitude" | "longitude" | "address">): InlineQueryResultVenue & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultVenue;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultVenue;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultVenue;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultVenue;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultVenue;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultVideo object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultvideo with mime_type
|
||||
* set to "text/html". This will send an embedded video player. Requires you
|
||||
* to specify the actual message content by calling another function on the
|
||||
* object returned from this method.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param video_url A valid URL for the embedded video player
|
||||
* @param thumbnail_url URL of the thumbnail (JPEG only) for the video
|
||||
* @param options Remaining options
|
||||
*/
|
||||
videoHtml(id: string, title: string, video_url: string | URL, thumbnail_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultVideo, "mime_type" | "title" | "video_url" | "thumbnail_url">): {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultVideo;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultVideo;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultVideo;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultVideo;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultVideo;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultVideo object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultvideo with mime_type
|
||||
* set to "video/mp4".
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param video_url A valid URL for the video file
|
||||
* @param thumbnail_url URL of the thumbnail (JPEG only) for the video
|
||||
* @param options Remaining options
|
||||
*/
|
||||
videoMp4(id: string, title: string, video_url: string | URL, thumbnail_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultVideo, "mime_type" | "title" | "video_url" | "thumbnail_url">): InlineQueryResultVideo & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultVideo;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultVideo;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultVideo;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultVideo;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultVideo;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedVideo object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedvideo.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param video_file_id A valid file identifier for the video file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
videoCached(id: string, title: string, video_file_id: string, options?: InlineQueryResultOptions<InlineQueryResultCachedVideo, "title" | "video_file_id">): InlineQueryResultCachedVideo & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultCachedVideo;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultCachedVideo;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultCachedVideo;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultCachedVideo;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultCachedVideo;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultVoice object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultvoice.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Voice message title
|
||||
* @param voice_url A valid URL for the voice recording
|
||||
* @param options Remaining options
|
||||
*/
|
||||
voice(id: string, title: string, voice_url: string | URL, options?: InlineQueryResultOptions<InlineQueryResultVoice, "title" | "voice_url">): InlineQueryResultVoice & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultVoice;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultVoice;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultVoice;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultVoice;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultVoice;
|
||||
};
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedVoice object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedvoice.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Voice message title
|
||||
* @param voice_file_id A valid file identifier for the voice message
|
||||
* @param options Remaining options
|
||||
*/
|
||||
voiceCached(id: string, title: string, voice_file_id: string, options?: InlineQueryResultOptions<InlineQueryResultCachedVoice, "title" | "voice_file_id">): InlineQueryResultCachedVoice & {
|
||||
text(message_text: string, options?: OptionalFields<InputTextMessageContent>): InlineQueryResultCachedVoice;
|
||||
location(latitude: number, longitude: number, options?: OptionalFields<InputLocationMessageContent>): InlineQueryResultCachedVoice;
|
||||
venue(title: string, latitude: number, longitude: number, address: string, options: OptionalFields<InputVenueMessageContent>): InlineQueryResultCachedVoice;
|
||||
contact(first_name: string, phone_number: string, options?: OptionalFields<InputContactMessageContent>): InlineQueryResultCachedVoice;
|
||||
invoice(title: string, description: string, payload: string, provider_token: string, currency: string, prices: LabeledPrice[], options?: OptionalFields<InputInvoiceMessageContent>): InlineQueryResultCachedVoice;
|
||||
};
|
||||
};
|
||||
export {};
|
461
node_modules/grammy/out/convenience/inline_query.js
generated
vendored
Normal file
461
node_modules/grammy/out/convenience/inline_query.js
generated
vendored
Normal file
@ -0,0 +1,461 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.InlineQueryResultBuilder = void 0;
|
||||
function inputMessage(queryTemplate) {
|
||||
return {
|
||||
...queryTemplate,
|
||||
...inputMessageMethods(queryTemplate),
|
||||
};
|
||||
}
|
||||
function inputMessageMethods(queryTemplate) {
|
||||
return {
|
||||
text(message_text, options = {}) {
|
||||
const content = {
|
||||
message_text,
|
||||
...options,
|
||||
};
|
||||
return { ...queryTemplate, input_message_content: content };
|
||||
},
|
||||
location(latitude, longitude, options = {}) {
|
||||
const content = {
|
||||
latitude,
|
||||
longitude,
|
||||
...options,
|
||||
};
|
||||
return { ...queryTemplate, input_message_content: content };
|
||||
},
|
||||
venue(title, latitude, longitude, address, options) {
|
||||
const content = {
|
||||
title,
|
||||
latitude,
|
||||
longitude,
|
||||
address,
|
||||
...options,
|
||||
};
|
||||
return { ...queryTemplate, input_message_content: content };
|
||||
},
|
||||
contact(first_name, phone_number, options = {}) {
|
||||
const content = {
|
||||
first_name,
|
||||
phone_number,
|
||||
...options,
|
||||
};
|
||||
return { ...queryTemplate, input_message_content: content };
|
||||
},
|
||||
invoice(title, description, payload, provider_token, currency, prices, options = {}) {
|
||||
const content = {
|
||||
title,
|
||||
description,
|
||||
payload,
|
||||
provider_token,
|
||||
currency,
|
||||
prices,
|
||||
...options,
|
||||
};
|
||||
return { ...queryTemplate, input_message_content: content };
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Holds a number of helper methods for building `InlineQueryResult*` objects.
|
||||
*
|
||||
* For example, letting the user pick one out of three photos can be done like
|
||||
* this.
|
||||
*
|
||||
* ```ts
|
||||
* const results = [
|
||||
* InlineQueryResultBuilder.photo('id0', 'https://grammy.dev/images/Y.png'),
|
||||
* InlineQueryResultBuilder.photo('id1', 'https://grammy.dev/images/Y.png'),
|
||||
* InlineQueryResultBuilder.photo('id2', 'https://grammy.dev/images/Y.png'),
|
||||
* ];
|
||||
* await ctx.answerInlineQuery(results)
|
||||
* ```
|
||||
*
|
||||
* If you want the message content to be different from the content in the
|
||||
* inline query result, you can perform another method call on the resulting
|
||||
* objects.
|
||||
*
|
||||
* ```ts
|
||||
* const results = [
|
||||
* InlineQueryResultBuilder.photo("id0", "https://grammy.dev/images/Y.png")
|
||||
* .text("Picked photo 0!"),
|
||||
* InlineQueryResultBuilder.photo("id1", "https://grammy.dev/images/Y.png")
|
||||
* .text("Picked photo 1!"),
|
||||
* InlineQueryResultBuilder.photo("id2", "https://grammy.dev/images/Y.png")
|
||||
* .text("Picked photo 2!"),
|
||||
* ];
|
||||
* await ctx.answerInlineQuery(results)
|
||||
* ```
|
||||
*
|
||||
* Be sure to check the
|
||||
* [documentation](https://core.telegram.org/bots/api#inline-mode) on inline
|
||||
* mode.
|
||||
*/
|
||||
exports.InlineQueryResultBuilder = {
|
||||
/**
|
||||
* Builds an InlineQueryResultArticle object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultarticle. Requires you
|
||||
* to specify the actual message content by calling another function on the
|
||||
* object returned from this method.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 Bytes
|
||||
* @param title Title of the result
|
||||
* @param options Remaining options
|
||||
*/
|
||||
article(id, title, options = {}) {
|
||||
return inputMessageMethods({ type: "article", id, title, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultAudio object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultaudio.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title
|
||||
* @param audio_url A valid URL for the audio file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
audio(id, title, audio_url, options = {}) {
|
||||
return inputMessage({
|
||||
type: "audio",
|
||||
id,
|
||||
title,
|
||||
audio_url: typeof audio_url === "string"
|
||||
? audio_url
|
||||
: audio_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedAudio object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedaudio.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param audio_file_id A valid file identifier for the audio file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
audioCached(id, audio_file_id, options = {}) {
|
||||
return inputMessage({ type: "audio", id, audio_file_id, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultContact object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcontact.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 Bytes
|
||||
* @param phone_number Contact's phone number
|
||||
* @param first_name Contact's first name
|
||||
* @param options Remaining options
|
||||
*/
|
||||
contact(id, phone_number, first_name, options = {}) {
|
||||
return inputMessage({ type: "contact", id, phone_number, first_name, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultDocument object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultdocument with
|
||||
* mime_type set to "application/pdf".
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param document_url A valid URL for the file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
documentPdf(id, title, document_url, options = {}) {
|
||||
return inputMessage({
|
||||
type: "document",
|
||||
mime_type: "application/pdf",
|
||||
id,
|
||||
title,
|
||||
document_url: typeof document_url === "string"
|
||||
? document_url
|
||||
: document_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultDocument object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultdocument with
|
||||
* mime_type set to "application/zip".
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param document_url A valid URL for the file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
documentZip(id, title, document_url, options = {}) {
|
||||
return inputMessage({
|
||||
type: "document",
|
||||
mime_type: "application/zip",
|
||||
id,
|
||||
title,
|
||||
document_url: typeof document_url === "string"
|
||||
? document_url
|
||||
: document_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedDocument object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcacheddocument.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param document_file_id A valid file identifier for the file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
documentCached(id, title, document_file_id, options = {}) {
|
||||
return inputMessage({ type: "document", id, title, document_file_id, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultGame object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultgame.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param game_short_name Short name of the game
|
||||
* @param options Remaining options
|
||||
*/
|
||||
game(id, game_short_name, options = {}) {
|
||||
return { type: "game", id, game_short_name, ...options };
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultGif object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultgif.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param gif_url A valid URL for the GIF file. File size must not exceed 1MB
|
||||
* @param thumbnail_url URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result
|
||||
* @param options Remaining options
|
||||
*/
|
||||
gif(id, gif_url, thumbnail_url, options = {}) {
|
||||
return inputMessage({
|
||||
type: "gif",
|
||||
id,
|
||||
gif_url: typeof gif_url === "string" ? gif_url : gif_url.href,
|
||||
thumbnail_url: typeof thumbnail_url === "string"
|
||||
? thumbnail_url
|
||||
: thumbnail_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedGif object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedgif.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param gif_file_id A valid file identifier for the GIF file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
gifCached(id, gif_file_id, options = {}) {
|
||||
return inputMessage({ type: "gif", id, gif_file_id, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultLocation object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultlocation.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 Bytes
|
||||
* @param title Location title
|
||||
* @param latitude Location latitude in degrees
|
||||
* @param longitude Location longitude in degrees
|
||||
* @param options Remaining options
|
||||
*/
|
||||
location(id, title, latitude, longitude, options = {}) {
|
||||
return inputMessage({ type: "location", id, title, latitude, longitude, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultMpeg4Gif object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultmpeg4gif.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param mpeg4_url A valid URL for the MPEG4 file. File size must not exceed 1MB
|
||||
* @param thumbnail_url URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result
|
||||
* @param options Remaining options
|
||||
*/
|
||||
mpeg4gif(id, mpeg4_url, thumbnail_url, options = {}) {
|
||||
return inputMessage({
|
||||
type: "mpeg4_gif",
|
||||
id,
|
||||
mpeg4_url: typeof mpeg4_url === "string"
|
||||
? mpeg4_url
|
||||
: mpeg4_url.href,
|
||||
thumbnail_url: typeof thumbnail_url === "string"
|
||||
? thumbnail_url
|
||||
: thumbnail_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedMpeg4Gif object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedmpeg4gif.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param mpeg4_file_id A valid file identifier for the MPEG4 file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
mpeg4gifCached(id, mpeg4_file_id, options = {}) {
|
||||
return inputMessage({ type: "mpeg4_gif", id, mpeg4_file_id, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultPhoto object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultphoto with the
|
||||
* thumbnail defaulting to the photo itself.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param photo_url A valid URL of the photo. Photo must be in JPEG format. Photo size must not exceed 5MB
|
||||
* @param options Remaining options
|
||||
*/
|
||||
photo(id, photo_url, options = {
|
||||
thumbnail_url: typeof photo_url === "string"
|
||||
? photo_url
|
||||
: photo_url.href,
|
||||
}) {
|
||||
return inputMessage({
|
||||
type: "photo",
|
||||
id,
|
||||
photo_url: typeof photo_url === "string"
|
||||
? photo_url
|
||||
: photo_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedPhoto object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedphoto.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param photo_file_id A valid file identifier of the photo
|
||||
* @param options Remaining options
|
||||
*/
|
||||
photoCached(id, photo_file_id, options = {}) {
|
||||
return inputMessage({ type: "photo", id, photo_file_id, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedSticker object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedsticker.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param sticker_file_id A valid file identifier of the sticker
|
||||
* @param options Remaining options
|
||||
*/
|
||||
stickerCached(id, sticker_file_id, options = {}) {
|
||||
return inputMessage({ type: "sticker", id, sticker_file_id, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultVenue object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultvenue.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 Bytes
|
||||
* @param title Title of the venue
|
||||
* @param latitude Latitude of the venue location in degrees
|
||||
* @param longitude Longitude of the venue location in degrees
|
||||
* @param address Address of the venue
|
||||
* @param options Remaining options
|
||||
*/
|
||||
venue(id, title, latitude, longitude, address, options = {}) {
|
||||
return inputMessage({
|
||||
type: "venue",
|
||||
id,
|
||||
title,
|
||||
latitude,
|
||||
longitude,
|
||||
address,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultVideo object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultvideo with mime_type
|
||||
* set to "text/html". This will send an embedded video player. Requires you
|
||||
* to specify the actual message content by calling another function on the
|
||||
* object returned from this method.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param video_url A valid URL for the embedded video player
|
||||
* @param thumbnail_url URL of the thumbnail (JPEG only) for the video
|
||||
* @param options Remaining options
|
||||
*/
|
||||
videoHtml(id, title, video_url, thumbnail_url, options = {}) {
|
||||
// require input message content by only returning methods
|
||||
return inputMessageMethods({
|
||||
type: "video",
|
||||
mime_type: "text/html",
|
||||
id,
|
||||
title,
|
||||
video_url: typeof video_url === "string"
|
||||
? video_url
|
||||
: video_url.href,
|
||||
thumbnail_url: typeof thumbnail_url === "string"
|
||||
? thumbnail_url
|
||||
: thumbnail_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultVideo object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultvideo with mime_type
|
||||
* set to "video/mp4".
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param video_url A valid URL for the video file
|
||||
* @param thumbnail_url URL of the thumbnail (JPEG only) for the video
|
||||
* @param options Remaining options
|
||||
*/
|
||||
videoMp4(id, title, video_url, thumbnail_url, options = {}) {
|
||||
return inputMessage({
|
||||
type: "video",
|
||||
mime_type: "video/mp4",
|
||||
id,
|
||||
title,
|
||||
video_url: typeof video_url === "string"
|
||||
? video_url
|
||||
: video_url.href,
|
||||
thumbnail_url: typeof thumbnail_url === "string"
|
||||
? thumbnail_url
|
||||
: thumbnail_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedVideo object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedvideo.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Title for the result
|
||||
* @param video_file_id A valid file identifier for the video file
|
||||
* @param options Remaining options
|
||||
*/
|
||||
videoCached(id, title, video_file_id, options = {}) {
|
||||
return inputMessage({ type: "video", id, title, video_file_id, ...options });
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultVoice object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultvoice.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Voice message title
|
||||
* @param voice_url A valid URL for the voice recording
|
||||
* @param options Remaining options
|
||||
*/
|
||||
voice(id, title, voice_url, options = {}) {
|
||||
return inputMessage({
|
||||
type: "voice",
|
||||
id,
|
||||
title,
|
||||
voice_url: typeof voice_url === "string"
|
||||
? voice_url
|
||||
: voice_url.href,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Builds an InlineQueryResultCachedVoice object as specified by
|
||||
* https://core.telegram.org/bots/api#inlinequeryresultcachedvoice.
|
||||
*
|
||||
* @param id Unique identifier for this result, 1-64 bytes
|
||||
* @param title Voice message title
|
||||
* @param voice_file_id A valid file identifier for the voice message
|
||||
* @param options Remaining options
|
||||
*/
|
||||
voiceCached(id, title, voice_file_id, options = {}) {
|
||||
return inputMessage({ type: "voice", id, title, voice_file_id, ...options });
|
||||
},
|
||||
};
|
72
node_modules/grammy/out/convenience/input_media.d.ts
generated
vendored
Normal file
72
node_modules/grammy/out/convenience/input_media.d.ts
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
import { type InputFile, type InputMediaAnimation, type InputMediaAudio, type InputMediaDocument, type InputMediaPhoto, type InputMediaVideo } from "../types.js";
|
||||
type InputMediaOptions<T> = Omit<T, "type" | "media">;
|
||||
/**
|
||||
* Holds a number of helper methods for building `InputMedia*` objects. They are
|
||||
* useful when sending media groups and when editing media messages.
|
||||
*
|
||||
* For example, media groups can be sent like this.
|
||||
*
|
||||
* ```ts
|
||||
* const paths = [
|
||||
* '/tmp/pic0.jpg',
|
||||
* '/tmp/pic1.jpg',
|
||||
* '/tmp/pic2.jpg',
|
||||
* ]
|
||||
* const files = paths.map((path) => new InputFile(path))
|
||||
* const media = files.map((file) => InputMediaBuilder.photo(file))
|
||||
* await bot.api.sendMediaGroup(chatId, media)
|
||||
* ```
|
||||
*
|
||||
* Media can be edited like this.
|
||||
*
|
||||
* ```ts
|
||||
* const file = new InputFile('/tmp/pic0.jpg')
|
||||
* const media = InputMediaBuilder.photo(file, {
|
||||
* caption: 'new caption'
|
||||
* })
|
||||
* await bot.api.editMessageMedia(chatId, messageId, media)
|
||||
* ```
|
||||
*/
|
||||
export declare const InputMediaBuilder: {
|
||||
/**
|
||||
* Creates a new `InputMediaPhoto` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediaphoto.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
photo(media: string | InputFile, options?: InputMediaOptions<InputMediaPhoto>): InputMediaPhoto;
|
||||
/**
|
||||
* Creates a new `InputMediaVideo` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediavideo.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
video(media: string | InputFile, options?: InputMediaOptions<InputMediaVideo>): InputMediaVideo;
|
||||
/**
|
||||
* Creates a new `InputMediaAnimation` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediaanimation.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
animation(media: string | InputFile, options?: InputMediaOptions<InputMediaAnimation>): InputMediaAnimation;
|
||||
/**
|
||||
* Creates a new `InputMediaAudio` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediaaudio.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
audio(media: string | InputFile, options?: InputMediaOptions<InputMediaAudio>): InputMediaAudio;
|
||||
/**
|
||||
* Creates a new `InputMediaDocument` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediadocument.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
document(media: string | InputFile, options?: InputMediaOptions<InputMediaDocument>): InputMediaDocument;
|
||||
};
|
||||
export {};
|
82
node_modules/grammy/out/convenience/input_media.js
generated
vendored
Normal file
82
node_modules/grammy/out/convenience/input_media.js
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.InputMediaBuilder = void 0;
|
||||
/**
|
||||
* Holds a number of helper methods for building `InputMedia*` objects. They are
|
||||
* useful when sending media groups and when editing media messages.
|
||||
*
|
||||
* For example, media groups can be sent like this.
|
||||
*
|
||||
* ```ts
|
||||
* const paths = [
|
||||
* '/tmp/pic0.jpg',
|
||||
* '/tmp/pic1.jpg',
|
||||
* '/tmp/pic2.jpg',
|
||||
* ]
|
||||
* const files = paths.map((path) => new InputFile(path))
|
||||
* const media = files.map((file) => InputMediaBuilder.photo(file))
|
||||
* await bot.api.sendMediaGroup(chatId, media)
|
||||
* ```
|
||||
*
|
||||
* Media can be edited like this.
|
||||
*
|
||||
* ```ts
|
||||
* const file = new InputFile('/tmp/pic0.jpg')
|
||||
* const media = InputMediaBuilder.photo(file, {
|
||||
* caption: 'new caption'
|
||||
* })
|
||||
* await bot.api.editMessageMedia(chatId, messageId, media)
|
||||
* ```
|
||||
*/
|
||||
exports.InputMediaBuilder = {
|
||||
/**
|
||||
* Creates a new `InputMediaPhoto` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediaphoto.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
photo(media, options = {}) {
|
||||
return { type: "photo", media, ...options };
|
||||
},
|
||||
/**
|
||||
* Creates a new `InputMediaVideo` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediavideo.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
video(media, options = {}) {
|
||||
return { type: "video", media, ...options };
|
||||
},
|
||||
/**
|
||||
* Creates a new `InputMediaAnimation` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediaanimation.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
animation(media, options = {}) {
|
||||
return { type: "animation", media, ...options };
|
||||
},
|
||||
/**
|
||||
* Creates a new `InputMediaAudio` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediaaudio.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
audio(media, options = {}) {
|
||||
return { type: "audio", media, ...options };
|
||||
},
|
||||
/**
|
||||
* Creates a new `InputMediaDocument` object as specified by
|
||||
* https://core.telegram.org/bots/api#inputmediadocument.
|
||||
*
|
||||
* @param media An `InputFile` instance or a file identifier
|
||||
* @param options Remaining optional options
|
||||
*/
|
||||
document(media, options = {}) {
|
||||
return { type: "document", media, ...options };
|
||||
},
|
||||
};
|
747
node_modules/grammy/out/convenience/keyboard.d.ts
generated
vendored
Normal file
747
node_modules/grammy/out/convenience/keyboard.d.ts
generated
vendored
Normal file
@ -0,0 +1,747 @@
|
||||
import { type InlineKeyboardButton, type KeyboardButton, type KeyboardButtonPollType, type KeyboardButtonRequestChat, type KeyboardButtonRequestUser, type LoginUrl, type SwitchInlineQueryChosenChat } from "../types.js";
|
||||
type KeyboardButtonSource = string | KeyboardButton;
|
||||
type KeyboardSource = KeyboardButtonSource[][] | Keyboard;
|
||||
/**
|
||||
* Use this class to simplify building a custom keyboard (something like this:
|
||||
* https://core.telegram.org/bots/features#keyboards).
|
||||
*
|
||||
* ```ts
|
||||
* // Build a custom keyboard:
|
||||
* const keyboard = new Keyboard()
|
||||
* .text('A').text('B').row()
|
||||
* .text('C').text('D')
|
||||
*
|
||||
* // Now you can send it like so:
|
||||
* await ctx.reply('Here is your custom keyboard!', {
|
||||
* reply_markup: keyboard
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* If you already have some source data which you would like to turn into a
|
||||
* keyboard button object, you can use the static equivalents which every button
|
||||
* has. You can use them to create a two-dimensional keyboard button array. The
|
||||
* resulting array can be turned into a keyboard instance.
|
||||
*
|
||||
* ```ts
|
||||
* const button = Keyboard.text('push my buttons')
|
||||
* const array = [[button]]
|
||||
* const keyboard = Keyboard.from(array)
|
||||
* ```
|
||||
*
|
||||
* If you want to create text buttons only, you can directly use a
|
||||
* two-dimensional string array and turn it into a keyboard.
|
||||
*
|
||||
* ```ts
|
||||
* const data = [['A', 'B'], ['C', 'D']]
|
||||
* const keyboard = Keyboard.from(data)
|
||||
* ```
|
||||
*
|
||||
* Be sure to check out the
|
||||
* [documentation](https://grammy.dev/plugins/keyboard.html#custom-keyboards) on
|
||||
* custom keyboards in grammY.
|
||||
*/
|
||||
export declare class Keyboard {
|
||||
readonly keyboard: KeyboardButton[][];
|
||||
/**
|
||||
* Requests clients to always show the keyboard when the regular keyboard is
|
||||
* hidden. Defaults to false, in which case the custom keyboard can be
|
||||
* hidden and opened with a keyboard icon.
|
||||
*/
|
||||
is_persistent?: boolean;
|
||||
/**
|
||||
* Show the current keyboard only to those users that are mentioned in the
|
||||
* text of the message object.
|
||||
*/
|
||||
selective?: boolean;
|
||||
/**
|
||||
* Hide the keyboard after a button is pressed.
|
||||
*/
|
||||
one_time_keyboard?: boolean;
|
||||
/**
|
||||
* Resize the current keyboard according to its buttons. Usually, this will
|
||||
* make the keyboard smaller.
|
||||
*/
|
||||
resize_keyboard?: boolean;
|
||||
/**
|
||||
* Placeholder to be shown in the input field when the keyboard is active.
|
||||
*/
|
||||
input_field_placeholder?: string;
|
||||
/**
|
||||
* Initialize a new `Keyboard` with an optional two-dimensional array of
|
||||
* `KeyboardButton` objects. This is the nested array that holds the custom
|
||||
* keyboard. It will be extended every time you call one of the provided
|
||||
* methods.
|
||||
*
|
||||
* @param keyboard An optional initial two-dimensional button array
|
||||
*/
|
||||
constructor(keyboard?: KeyboardButton[][]);
|
||||
/**
|
||||
* Allows you to add your own `KeyboardButton` objects if you already have
|
||||
* them for some reason. You most likely want to call one of the other
|
||||
* methods.
|
||||
*
|
||||
* @param buttons The buttons to add
|
||||
*/
|
||||
add(...buttons: KeyboardButton[]): this;
|
||||
/**
|
||||
* Adds a 'line break'. Call this method to make sure that the next added
|
||||
* buttons will be on a new row.
|
||||
*
|
||||
* You may pass a number of `KeyboardButton` objects if you already have the
|
||||
* instances for some reason. You most likely don't want to pass any
|
||||
* arguments to `row`.
|
||||
*
|
||||
* @param buttons A number of buttons to add to the next row
|
||||
*/
|
||||
row(...buttons: KeyboardButton[]): this;
|
||||
/**
|
||||
* Adds a new text button. This button will simply send the given text as a
|
||||
* text message back to your bot if a user clicks on it.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
text(text: string): this;
|
||||
/**
|
||||
* Creates a new text button. This button will simply send the given text as
|
||||
* a text message back to your bot if a user clicks on it.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static text(text: string): KeyboardButton.CommonButton;
|
||||
/**
|
||||
* Adds a new request user button. When the user presses the button, a list
|
||||
* of suitable users will be opened. Tapping on any user will send their
|
||||
* identifier to the bot in a “user_shared” service message. Available in
|
||||
* private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param requestId A signed 32-bit identifier of the request
|
||||
* @param options Options object for further requirements
|
||||
*/
|
||||
requestUser(text: string, requestId: number, options?: Omit<KeyboardButtonRequestUser, "request_id">): this;
|
||||
/**
|
||||
* Creates a new request user button. When the user presses the button, a
|
||||
* list of suitable users will be opened. Tapping on any user will send
|
||||
* their identifier to the bot in a “user_shared” service message. Available
|
||||
* in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param requestId A signed 32-bit identifier of the request
|
||||
* @param options Options object for further requirements
|
||||
*/
|
||||
static requestUser(text: string, requestId: number, options?: Omit<KeyboardButtonRequestUser, "request_id">): KeyboardButton.RequestUserButton;
|
||||
/**
|
||||
* Adds a new request chat button. When the user presses the button, a list
|
||||
* of suitable users will be opened. Tapping on a chat will send its
|
||||
* identifier to the bot in a “chat_shared” service message. Available in
|
||||
* private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param requestId A signed 32-bit identifier of the request
|
||||
* @param options Options object for further requirements
|
||||
*/
|
||||
requestChat(text: string, requestId: number, options?: Omit<KeyboardButtonRequestChat, "request_id">): this;
|
||||
/**
|
||||
* Creates a new request chat button. When the user presses the button, a
|
||||
* list of suitable users will be opened. Tapping on a chat will send its
|
||||
* identifier to the bot in a “chat_shared” service message. Available in
|
||||
* private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param requestId A signed 32-bit identifier of the request
|
||||
* @param options Options object for further requirements
|
||||
*/
|
||||
static requestChat(text: string, requestId: number, options?: Omit<KeyboardButtonRequestChat, "request_id">): KeyboardButton.RequestChatButton;
|
||||
/**
|
||||
* Adds a new contact request button. The user's phone number will be sent
|
||||
* as a contact when the button is pressed. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
requestContact(text: string): this;
|
||||
/**
|
||||
* Creates a new contact request button. The user's phone number will be
|
||||
* sent as a contact when the button is pressed. Available in private chats
|
||||
* only.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static requestContact(text: string): KeyboardButton.RequestContactButton;
|
||||
/**
|
||||
* Adds a new location request button. The user's current location will be
|
||||
* sent when the button is pressed. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
requestLocation(text: string): this;
|
||||
/**
|
||||
* Creates a new location request button. The user's current location will
|
||||
* be sent when the button is pressed. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static requestLocation(text: string): KeyboardButton.RequestLocationButton;
|
||||
/**
|
||||
* Adds a new poll request button. The user will be asked to create a poll
|
||||
* and send it to the bot when the button is pressed. Available in private
|
||||
* chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param type The type of permitted polls to create, omit if the user may
|
||||
* send a poll of any type
|
||||
*/
|
||||
requestPoll(text: string, type?: KeyboardButtonPollType["type"]): this;
|
||||
/**
|
||||
* Creates a new poll request button. The user will be asked to create a
|
||||
* poll and send it to the bot when the button is pressed. Available in
|
||||
* private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param type The type of permitted polls to create, omit if the user may
|
||||
* send a poll of any type
|
||||
*/
|
||||
static requestPoll(text: string, type?: KeyboardButtonPollType["type"]): KeyboardButton.RequestPollButton;
|
||||
/**
|
||||
* Adds a new web app button. The Web App that will be launched when the
|
||||
* user presses the button. The Web App will be able to send a
|
||||
* “web_app_data” service message. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url An HTTPS URL of a Web App to be opened with additional data
|
||||
*/
|
||||
webApp(text: string, url: string): this;
|
||||
/**
|
||||
* Creates a new web app button. The Web App that will be launched when the
|
||||
* user presses the button. The Web App will be able to send a
|
||||
* “web_app_data” service message. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url An HTTPS URL of a Web App to be opened with additional data
|
||||
*/
|
||||
static webApp(text: string, url: string): KeyboardButton.WebAppButton;
|
||||
/**
|
||||
* Make the current keyboard persistent. See
|
||||
* https://grammy.dev/plugins/keyboard.html#persistent-keyboards for more
|
||||
* details.
|
||||
*
|
||||
* Keyboards are not persistent by default, use this function to enable it
|
||||
* (without any parameters or pass `true`). Pass `false` to force the
|
||||
* keyboard to not persist.
|
||||
*
|
||||
* @param isEnabled `true` if the keyboard should persist, and `false` otherwise
|
||||
*/
|
||||
persistent(isEnabled?: boolean): this;
|
||||
/**
|
||||
* Make the current keyboard selective. See
|
||||
* https://grammy.dev/plugins/keyboard.html#selectively-send-custom-keyboards
|
||||
* for more details.
|
||||
*
|
||||
* Keyboards are non-selective by default, use this function to enable it
|
||||
* (without any parameters or pass `true`). Pass `false` to force the
|
||||
* keyboard to be non-selective.
|
||||
*
|
||||
* @param isEnabled `true` if the keyboard should be selective, and `false` otherwise
|
||||
*/
|
||||
selected(isEnabled?: boolean): this;
|
||||
/**
|
||||
* Make the current keyboard one-time. See
|
||||
* https://grammy.dev/plugins/keyboard.html#one-time-custom-keyboards for
|
||||
* more details.
|
||||
*
|
||||
* Keyboards are non-one-time by default, use this function to enable it
|
||||
* (without any parameters or pass `true`). Pass `false` to force the
|
||||
* keyboard to be non-one-time.
|
||||
*
|
||||
* @param isEnabled `true` if the keyboard should be one-time, and `false` otherwise
|
||||
*/
|
||||
oneTime(isEnabled?: boolean): this;
|
||||
/**
|
||||
* Make the current keyboard resized. See
|
||||
* https://grammy.dev/plugins/keyboard.html#resize-custom-keyboard for more
|
||||
* details.
|
||||
*
|
||||
* Keyboards are non-resized by default, use this function to enable it
|
||||
* (without any parameters or pass `true`). Pass `false` to force the
|
||||
* keyboard to be non-resized.
|
||||
*
|
||||
* @param isEnabled `true` if the keyboard should be resized, and `false` otherwise
|
||||
*/
|
||||
resized(isEnabled?: boolean): this;
|
||||
/**
|
||||
* Set the current keyboard's input field placeholder. See
|
||||
* https://grammy.dev/plugins/keyboard.html#input-field-placeholder for more
|
||||
* details.
|
||||
*
|
||||
* @param value The placeholder text
|
||||
*/
|
||||
placeholder(value: string): this;
|
||||
/**
|
||||
* Creates a new keyboard that contains the transposed grid of buttons of
|
||||
* this keyboard. This means that the resulting keyboard has the rows and
|
||||
* columns flipped.
|
||||
*
|
||||
* Note that buttons can only span multiple columns, but never multiple
|
||||
* rows. This means that if the given arrays have different lengths, some
|
||||
* buttons might flow up in the layout. In these cases, transposing a
|
||||
* keyboard a second time will not undo the first transposition.
|
||||
*
|
||||
* Here are some examples.
|
||||
*
|
||||
* ```
|
||||
* original transposed
|
||||
* [ a ] ~> [ a ]
|
||||
*
|
||||
* [ a ]
|
||||
* [a b c] ~> [ b ]
|
||||
* [ c ]
|
||||
*
|
||||
* [ a b ] [a c e]
|
||||
* [ c d ] ~> [ b d ]
|
||||
* [ e ]
|
||||
*
|
||||
* [ a b ] [a c d]
|
||||
* [ c ] ~> [ b e ]
|
||||
* [d e f] [ f ]
|
||||
* ```
|
||||
*/
|
||||
toTransposed(): Keyboard;
|
||||
/**
|
||||
* Creates a new keyboard with the same buttons but reflowed into a given
|
||||
* number of columns as if the buttons were text elements. Optionally, you
|
||||
* can specify if the flow should make sure to fill up the last row.
|
||||
*
|
||||
* This method is idempotent, so calling it a second time will effectively
|
||||
* clone this keyboard without reordering the buttons.
|
||||
*
|
||||
* Here are some examples.
|
||||
*
|
||||
* ```
|
||||
* original flowed
|
||||
* [ a ] ~> [ a ] (4 columns)
|
||||
*
|
||||
* [ a ]
|
||||
* [a b c] ~> [ b ] (1 column)
|
||||
* [ c ]
|
||||
*
|
||||
* [ a b ] [a b c]
|
||||
* [ c d ] ~> [ d e ] (3 columns)
|
||||
* [ e ]
|
||||
*
|
||||
* [ a b ] [abcde]
|
||||
* [ c ] ~> [ f ] (5 columns)
|
||||
* [d e f]
|
||||
*
|
||||
* [a b c] [ a ]
|
||||
* [d e f] ~> [b c d] (3 colums, { fillLastRow: true })
|
||||
* [g h i] [e f g]
|
||||
* [ j ] [h i j]
|
||||
* ```
|
||||
*
|
||||
* @param columns Maximum number of buttons per row
|
||||
* @param options Optional flowing behavior
|
||||
*/
|
||||
toFlowed(columns: number, options?: FlowOptions): Keyboard;
|
||||
/**
|
||||
* Creates and returns a deep copy of this keyboard.
|
||||
*
|
||||
* Optionally takes a new grid of buttons to replace the current buttons. If
|
||||
* specified, only the options will be cloned, and the given buttons will be
|
||||
* used instead.
|
||||
*/
|
||||
clone(keyboard?: KeyboardButton[][]): Keyboard;
|
||||
/**
|
||||
* Appends the buttons of the given keyboards to this keyboard. If other
|
||||
* options are specified in these keyboards, they will be ignored.
|
||||
*
|
||||
* @param sources A number of keyboards to append
|
||||
*/
|
||||
append(...sources: KeyboardSource[]): this;
|
||||
/**
|
||||
* Returns the keyboard that was build. Note that it doesn't return
|
||||
* `resize_keyboard` or other options that may be set. You don't usually
|
||||
* need to call this method. It is no longer useful.
|
||||
*/
|
||||
build(): KeyboardButton[][];
|
||||
/**
|
||||
* Turns a two-dimensional keyboard button array into a keyboard instance.
|
||||
* You can use the static button builder methods to create keyboard button
|
||||
* objects.
|
||||
*
|
||||
* @param source A two-dimensional button array
|
||||
*/
|
||||
static from(source: KeyboardSource): Keyboard;
|
||||
}
|
||||
type InlineKeyboardSource = InlineKeyboardButton[][] | InlineKeyboard;
|
||||
/**
|
||||
* Use this class to simplify building an inline keyboard (something like this:
|
||||
* https://core.telegram.org/bots/features#inline-keyboards).
|
||||
*
|
||||
* ```ts
|
||||
* // Build an inline keyboard:
|
||||
* const keyboard = new InlineKeyboard()
|
||||
* .text('A').text('B', 'callback-data').row()
|
||||
* .text('C').text('D').row()
|
||||
* .url('Telegram', 'telegram.org')
|
||||
*
|
||||
* // Send the keyboard:
|
||||
* await ctx.reply('Here is your inline keyboard!', {
|
||||
* reply_markup: keyboard
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* If you already have some source data which you would like to turn into an
|
||||
* inline button object, you can use the static equivalents which every inline
|
||||
* button has. You can use them to create a two-dimensional inline button array.
|
||||
* The resulting array can be turned into a keyboard instance.
|
||||
*
|
||||
* ```ts
|
||||
* const button = InlineKeyboard.text('GO', 'go')
|
||||
* const array = [[button]]
|
||||
* const keyboard = InlineKeyboard.from(array)
|
||||
* ```
|
||||
*
|
||||
* Be sure to to check the
|
||||
* [documentation](https://grammy.dev/plugins/keyboard.html#inline-keyboards) on
|
||||
* inline keyboards in grammY.
|
||||
*/
|
||||
export declare class InlineKeyboard {
|
||||
readonly inline_keyboard: InlineKeyboardButton[][];
|
||||
/**
|
||||
* Initialize a new `InlineKeyboard` with an optional two-dimensional array
|
||||
* of `InlineKeyboardButton` objects. This is the nested array that holds
|
||||
* the inline keyboard. It will be extended every time you call one of the
|
||||
* provided methods.
|
||||
*
|
||||
* @param inline_keyboard An optional initial two-dimensional button array
|
||||
*/
|
||||
constructor(inline_keyboard?: InlineKeyboardButton[][]);
|
||||
/**
|
||||
* Allows you to add your own `InlineKeyboardButton` objects if you already
|
||||
* have them for some reason. You most likely want to call one of the other
|
||||
* methods.
|
||||
*
|
||||
* @param buttons The buttons to add
|
||||
*/
|
||||
add(...buttons: InlineKeyboardButton[]): this;
|
||||
/**
|
||||
* Adds a 'line break'. Call this method to make sure that the next added
|
||||
* buttons will be on a new row.
|
||||
*
|
||||
* You may pass a number of `InlineKeyboardButton` objects if you already
|
||||
* have the instances for some reason. You most likely don't want to pass
|
||||
* any arguments to `row`.
|
||||
*
|
||||
* @param buttons A number of buttons to add to the next row
|
||||
*/
|
||||
row(...buttons: InlineKeyboardButton[]): this;
|
||||
/**
|
||||
* Adds a new URL button. Telegram clients will open the provided URL when
|
||||
* the button is pressed.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url HTTP or tg:// url to be opened when the button is pressed. Links tg://user?id=<user_id> can be used to mention a user by their ID without using a username, if this is allowed by their privacy settings.
|
||||
*/
|
||||
url(text: string, url: string): this;
|
||||
/**
|
||||
* Creates a new URL button. Telegram clients will open the provided URL
|
||||
* when the button is pressed.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url HTTP or tg:// url to be opened when the button is pressed. Links tg://user?id=<user_id> can be used to mention a user by their ID without using a username, if this is allowed by their privacy settings.
|
||||
*/
|
||||
static url(text: string, url: string): InlineKeyboardButton.UrlButton;
|
||||
/**
|
||||
* Adds a new callback query button. The button contains a text and a custom
|
||||
* payload. This payload will be sent back to your bot when the button is
|
||||
* pressed. If you omit the payload, the display text will be sent back to
|
||||
* your bot.
|
||||
*
|
||||
* Your bot will receive an update every time a user presses any of the text
|
||||
* buttons. You can listen to these updates like this:
|
||||
* ```ts
|
||||
* // Specific buttons:
|
||||
* bot.callbackQuery('button-data', ctx => { ... })
|
||||
* // Any button of any inline keyboard:
|
||||
* bot.on('callback_query:data', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param data The callback data to send back to your bot (default = text)
|
||||
*/
|
||||
text(text: string, data?: string): this;
|
||||
/**
|
||||
* Creates a new callback query button. The button contains a text and a
|
||||
* custom payload. This payload will be sent back to your bot when the
|
||||
* button is pressed. If you omit the payload, the display text will be sent
|
||||
* back to your bot.
|
||||
*
|
||||
* Your bot will receive an update every time a user presses any of the text
|
||||
* buttons. You can listen to these updates like this:
|
||||
* ```ts
|
||||
* // Specific buttons:
|
||||
* bot.callbackQuery('button-data', ctx => { ... })
|
||||
* // Any button of any inline keyboard:
|
||||
* bot.on('callback_query:data', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param data The callback data to send back to your bot (default = text)
|
||||
*/
|
||||
static text(text: string, data?: string): InlineKeyboardButton.CallbackButton;
|
||||
/**
|
||||
* Adds a new web app button, confer https://core.telegram.org/bots/webapps
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url An HTTPS URL of a Web App to be opened with additional data
|
||||
*/
|
||||
webApp(text: string, url: string): this;
|
||||
/**
|
||||
* Creates a new web app button, confer https://core.telegram.org/bots/webapps
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url An HTTPS URL of a Web App to be opened with additional data
|
||||
*/
|
||||
static webApp(text: string, url: string): InlineKeyboardButton.WebAppButton;
|
||||
/**
|
||||
* Adds a new login button. This can be used as a replacement for the
|
||||
* Telegram Login Widget. You must specify an HTTPS URL used to
|
||||
* automatically authorize the user.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param loginUrl The login URL as string or `LoginUrl` object
|
||||
*/
|
||||
login(text: string, loginUrl: string | LoginUrl): this;
|
||||
/**
|
||||
* Creates a new login button. This can be used as a replacement for the
|
||||
* Telegram Login Widget. You must specify an HTTPS URL used to
|
||||
* automatically authorize the user.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param loginUrl The login URL as string or `LoginUrl` object
|
||||
*/
|
||||
static login(text: string, loginUrl: string | LoginUrl): InlineKeyboardButton.LoginButton;
|
||||
/**
|
||||
* Adds a new inline query button. Telegram clients will let the user pick a
|
||||
* chat when this button is pressed. This will start an inline query. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The (optional) inline query string to prefill
|
||||
*/
|
||||
switchInline(text: string, query?: string): this;
|
||||
/**
|
||||
* Creates a new inline query button. Telegram clients will let the user pick a
|
||||
* chat when this button is pressed. This will start an inline query. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The (optional) inline query string to prefill
|
||||
*/
|
||||
static switchInline(text: string, query?: string): InlineKeyboardButton.SwitchInlineButton;
|
||||
/**
|
||||
* Adds a new inline query button that acts on the current chat. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it. This will start an inline
|
||||
* query.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The (optional) inline query string to prefill
|
||||
*/
|
||||
switchInlineCurrent(text: string, query?: string): this;
|
||||
/**
|
||||
* Creates a new inline query button that acts on the current chat. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it. This will start an inline
|
||||
* query.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The (optional) inline query string to prefill
|
||||
*/
|
||||
static switchInlineCurrent(text: string, query?: string): InlineKeyboardButton.SwitchInlineCurrentChatButton;
|
||||
/**
|
||||
* Adds a new inline query button. Telegram clients will let the user pick a
|
||||
* chat when this button is pressed. This will start an inline query. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The query object describing which chats can be picked
|
||||
*/
|
||||
switchInlineChosen(text: string, query?: SwitchInlineQueryChosenChat): this;
|
||||
/**
|
||||
* Creates a new inline query button. Telegram clients will let the user pick a
|
||||
* chat when this button is pressed. This will start an inline query. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The query object describing which chats can be picked
|
||||
*/
|
||||
static switchInlineChosen(text: string, query?: SwitchInlineQueryChosenChat): InlineKeyboardButton.SwitchInlineChosenChatButton;
|
||||
/**
|
||||
* Adds a new game query button, confer
|
||||
* https://core.telegram.org/bots/api#games
|
||||
*
|
||||
* This type of button must always be the first button in the first row.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
game(text: string): this;
|
||||
/**
|
||||
* Creates a new game query button, confer
|
||||
* https://core.telegram.org/bots/api#games
|
||||
*
|
||||
* This type of button must always be the first button in the first row.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static game(text: string): InlineKeyboardButton.GameButton;
|
||||
/**
|
||||
* Adds a new payment button, confer
|
||||
* https://core.telegram.org/bots/api#payments
|
||||
*
|
||||
* This type of button must always be the first button in the first row and
|
||||
* can only be used in invoice messages.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
pay(text: string): this;
|
||||
/**
|
||||
* Create a new payment button, confer
|
||||
* https://core.telegram.org/bots/api#payments
|
||||
*
|
||||
* This type of button must always be the first button in the first row and
|
||||
* can only be used in invoice messages.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static pay(text: string): InlineKeyboardButton.PayButton;
|
||||
/**
|
||||
* Creates a new inline keyboard that contains the transposed grid of
|
||||
* buttons of this inline keyboard. This means that the resulting inline
|
||||
* keyboard has the rows and columns flipped.
|
||||
*
|
||||
* Note that inline buttons can only span multiple columns, but never
|
||||
* multiple rows. This means that if the given arrays have different
|
||||
* lengths, some buttons might flow up in the layout. In these cases,
|
||||
* transposing an inline keyboard a second time will not undo the first
|
||||
* transposition.
|
||||
*
|
||||
* Here are some examples.
|
||||
*
|
||||
* ```
|
||||
* original transposed
|
||||
* [ a ] ~> [ a ]
|
||||
*
|
||||
* [ a ]
|
||||
* [a b c] ~> [ b ]
|
||||
* [ c ]
|
||||
*
|
||||
* [ a b ] [a c e]
|
||||
* [ c d ] ~> [ b d ]
|
||||
* [ e ]
|
||||
*
|
||||
* [ a b ] [a c d]
|
||||
* [ c ] ~> [ b e ]
|
||||
* [d e f] [ f ]
|
||||
* ```
|
||||
*/
|
||||
toTransposed(): InlineKeyboard;
|
||||
/**
|
||||
* Creates a new inline keyboard with the same buttons but reflowed into a
|
||||
* given number of columns as if the buttons were text elements. Optionally,
|
||||
* you can specify if the flow should make sure to fill up the last row.
|
||||
*
|
||||
* This method is idempotent, so calling it a second time will effectively
|
||||
* clone this inline keyboard without reordering the buttons.
|
||||
*
|
||||
* Here are some examples.
|
||||
*
|
||||
* ```
|
||||
* original flowed
|
||||
* [ a ] ~> [ a ] (4 columns)
|
||||
*
|
||||
* [ a ]
|
||||
* [a b c] ~> [ b ] (1 column)
|
||||
* [ c ]
|
||||
*
|
||||
* [ a b ] [a b c]
|
||||
* [ c d ] ~> [ d e ] (3 columns)
|
||||
* [ e ]
|
||||
*
|
||||
* [ a b ] [abcde]
|
||||
* [ c ] ~> [ f ] (5 columns)
|
||||
* [d e f]
|
||||
*
|
||||
* [a b c] [ a ]
|
||||
* [d e f] ~> [b c d] (3 colums, { fillLastRow: true })
|
||||
* [g h i] [e f g]
|
||||
* [ j ] [h i j]
|
||||
* ```
|
||||
*
|
||||
* @param columns Maximum number of buttons per row
|
||||
* @param options Optional flowing behavior
|
||||
*/
|
||||
toFlowed(columns: number, options?: FlowOptions): InlineKeyboard;
|
||||
/**
|
||||
* Creates and returns a deep copy of this inline keyboard.
|
||||
*/
|
||||
clone(): InlineKeyboard;
|
||||
/**
|
||||
* Appends the buttons of the given inline keyboards to this keyboard.
|
||||
*
|
||||
* @param sources A number of inline keyboards to append
|
||||
*/
|
||||
append(...sources: InlineKeyboardSource[]): this;
|
||||
/**
|
||||
* Turns a two-dimensional inline button array into an inline keyboard
|
||||
* instance. You can use the static button builder methods to create inline
|
||||
* button objects.
|
||||
*
|
||||
* @param source A two-dimensional inline button array
|
||||
*/
|
||||
static from(source: InlineKeyboardSource): InlineKeyboard;
|
||||
}
|
||||
interface FlowOptions {
|
||||
/** Set to `true` to completely fill up the last row */
|
||||
fillLastRow?: boolean;
|
||||
}
|
||||
export {};
|
910
node_modules/grammy/out/convenience/keyboard.js
generated
vendored
Normal file
910
node_modules/grammy/out/convenience/keyboard.js
generated
vendored
Normal file
@ -0,0 +1,910 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.InlineKeyboard = exports.Keyboard = void 0;
|
||||
/**
|
||||
* Use this class to simplify building a custom keyboard (something like this:
|
||||
* https://core.telegram.org/bots/features#keyboards).
|
||||
*
|
||||
* ```ts
|
||||
* // Build a custom keyboard:
|
||||
* const keyboard = new Keyboard()
|
||||
* .text('A').text('B').row()
|
||||
* .text('C').text('D')
|
||||
*
|
||||
* // Now you can send it like so:
|
||||
* await ctx.reply('Here is your custom keyboard!', {
|
||||
* reply_markup: keyboard
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* If you already have some source data which you would like to turn into a
|
||||
* keyboard button object, you can use the static equivalents which every button
|
||||
* has. You can use them to create a two-dimensional keyboard button array. The
|
||||
* resulting array can be turned into a keyboard instance.
|
||||
*
|
||||
* ```ts
|
||||
* const button = Keyboard.text('push my buttons')
|
||||
* const array = [[button]]
|
||||
* const keyboard = Keyboard.from(array)
|
||||
* ```
|
||||
*
|
||||
* If you want to create text buttons only, you can directly use a
|
||||
* two-dimensional string array and turn it into a keyboard.
|
||||
*
|
||||
* ```ts
|
||||
* const data = [['A', 'B'], ['C', 'D']]
|
||||
* const keyboard = Keyboard.from(data)
|
||||
* ```
|
||||
*
|
||||
* Be sure to check out the
|
||||
* [documentation](https://grammy.dev/plugins/keyboard.html#custom-keyboards) on
|
||||
* custom keyboards in grammY.
|
||||
*/
|
||||
class Keyboard {
|
||||
/**
|
||||
* Initialize a new `Keyboard` with an optional two-dimensional array of
|
||||
* `KeyboardButton` objects. This is the nested array that holds the custom
|
||||
* keyboard. It will be extended every time you call one of the provided
|
||||
* methods.
|
||||
*
|
||||
* @param keyboard An optional initial two-dimensional button array
|
||||
*/
|
||||
constructor(keyboard = [[]]) {
|
||||
this.keyboard = keyboard;
|
||||
}
|
||||
/**
|
||||
* Allows you to add your own `KeyboardButton` objects if you already have
|
||||
* them for some reason. You most likely want to call one of the other
|
||||
* methods.
|
||||
*
|
||||
* @param buttons The buttons to add
|
||||
*/
|
||||
add(...buttons) {
|
||||
var _a;
|
||||
(_a = this.keyboard[this.keyboard.length - 1]) === null || _a === void 0 ? void 0 : _a.push(...buttons);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Adds a 'line break'. Call this method to make sure that the next added
|
||||
* buttons will be on a new row.
|
||||
*
|
||||
* You may pass a number of `KeyboardButton` objects if you already have the
|
||||
* instances for some reason. You most likely don't want to pass any
|
||||
* arguments to `row`.
|
||||
*
|
||||
* @param buttons A number of buttons to add to the next row
|
||||
*/
|
||||
row(...buttons) {
|
||||
this.keyboard.push(buttons);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Adds a new text button. This button will simply send the given text as a
|
||||
* text message back to your bot if a user clicks on it.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
text(text) {
|
||||
return this.add(Keyboard.text(text));
|
||||
}
|
||||
/**
|
||||
* Creates a new text button. This button will simply send the given text as
|
||||
* a text message back to your bot if a user clicks on it.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static text(text) {
|
||||
return { text };
|
||||
}
|
||||
/**
|
||||
* Adds a new request user button. When the user presses the button, a list
|
||||
* of suitable users will be opened. Tapping on any user will send their
|
||||
* identifier to the bot in a “user_shared” service message. Available in
|
||||
* private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param requestId A signed 32-bit identifier of the request
|
||||
* @param options Options object for further requirements
|
||||
*/
|
||||
requestUser(text, requestId, options = {}) {
|
||||
return this.add(Keyboard.requestUser(text, requestId, options));
|
||||
}
|
||||
/**
|
||||
* Creates a new request user button. When the user presses the button, a
|
||||
* list of suitable users will be opened. Tapping on any user will send
|
||||
* their identifier to the bot in a “user_shared” service message. Available
|
||||
* in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param requestId A signed 32-bit identifier of the request
|
||||
* @param options Options object for further requirements
|
||||
*/
|
||||
static requestUser(text, requestId, options = {}) {
|
||||
return { text, request_user: { request_id: requestId, ...options } };
|
||||
}
|
||||
/**
|
||||
* Adds a new request chat button. When the user presses the button, a list
|
||||
* of suitable users will be opened. Tapping on a chat will send its
|
||||
* identifier to the bot in a “chat_shared” service message. Available in
|
||||
* private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param requestId A signed 32-bit identifier of the request
|
||||
* @param options Options object for further requirements
|
||||
*/
|
||||
requestChat(text, requestId, options = {
|
||||
chat_is_channel: false,
|
||||
}) {
|
||||
return this.add(Keyboard.requestChat(text, requestId, options));
|
||||
}
|
||||
/**
|
||||
* Creates a new request chat button. When the user presses the button, a
|
||||
* list of suitable users will be opened. Tapping on a chat will send its
|
||||
* identifier to the bot in a “chat_shared” service message. Available in
|
||||
* private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param requestId A signed 32-bit identifier of the request
|
||||
* @param options Options object for further requirements
|
||||
*/
|
||||
static requestChat(text, requestId, options = {
|
||||
chat_is_channel: false,
|
||||
}) {
|
||||
return { text, request_chat: { request_id: requestId, ...options } };
|
||||
}
|
||||
/**
|
||||
* Adds a new contact request button. The user's phone number will be sent
|
||||
* as a contact when the button is pressed. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
requestContact(text) {
|
||||
return this.add(Keyboard.requestContact(text));
|
||||
}
|
||||
/**
|
||||
* Creates a new contact request button. The user's phone number will be
|
||||
* sent as a contact when the button is pressed. Available in private chats
|
||||
* only.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static requestContact(text) {
|
||||
return { text, request_contact: true };
|
||||
}
|
||||
/**
|
||||
* Adds a new location request button. The user's current location will be
|
||||
* sent when the button is pressed. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
requestLocation(text) {
|
||||
return this.add(Keyboard.requestLocation(text));
|
||||
}
|
||||
/**
|
||||
* Creates a new location request button. The user's current location will
|
||||
* be sent when the button is pressed. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static requestLocation(text) {
|
||||
return { text, request_location: true };
|
||||
}
|
||||
/**
|
||||
* Adds a new poll request button. The user will be asked to create a poll
|
||||
* and send it to the bot when the button is pressed. Available in private
|
||||
* chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param type The type of permitted polls to create, omit if the user may
|
||||
* send a poll of any type
|
||||
*/
|
||||
requestPoll(text, type) {
|
||||
return this.add(Keyboard.requestPoll(text, type));
|
||||
}
|
||||
/**
|
||||
* Creates a new poll request button. The user will be asked to create a
|
||||
* poll and send it to the bot when the button is pressed. Available in
|
||||
* private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param type The type of permitted polls to create, omit if the user may
|
||||
* send a poll of any type
|
||||
*/
|
||||
static requestPoll(text, type) {
|
||||
return { text, request_poll: { type } };
|
||||
}
|
||||
/**
|
||||
* Adds a new web app button. The Web App that will be launched when the
|
||||
* user presses the button. The Web App will be able to send a
|
||||
* “web_app_data” service message. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url An HTTPS URL of a Web App to be opened with additional data
|
||||
*/
|
||||
webApp(text, url) {
|
||||
return this.add(Keyboard.webApp(text, url));
|
||||
}
|
||||
/**
|
||||
* Creates a new web app button. The Web App that will be launched when the
|
||||
* user presses the button. The Web App will be able to send a
|
||||
* “web_app_data” service message. Available in private chats only.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url An HTTPS URL of a Web App to be opened with additional data
|
||||
*/
|
||||
static webApp(text, url) {
|
||||
return { text, web_app: { url } };
|
||||
}
|
||||
/**
|
||||
* Make the current keyboard persistent. See
|
||||
* https://grammy.dev/plugins/keyboard.html#persistent-keyboards for more
|
||||
* details.
|
||||
*
|
||||
* Keyboards are not persistent by default, use this function to enable it
|
||||
* (without any parameters or pass `true`). Pass `false` to force the
|
||||
* keyboard to not persist.
|
||||
*
|
||||
* @param isEnabled `true` if the keyboard should persist, and `false` otherwise
|
||||
*/
|
||||
persistent(isEnabled = true) {
|
||||
this.is_persistent = isEnabled;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Make the current keyboard selective. See
|
||||
* https://grammy.dev/plugins/keyboard.html#selectively-send-custom-keyboards
|
||||
* for more details.
|
||||
*
|
||||
* Keyboards are non-selective by default, use this function to enable it
|
||||
* (without any parameters or pass `true`). Pass `false` to force the
|
||||
* keyboard to be non-selective.
|
||||
*
|
||||
* @param isEnabled `true` if the keyboard should be selective, and `false` otherwise
|
||||
*/
|
||||
selected(isEnabled = true) {
|
||||
this.selective = isEnabled;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Make the current keyboard one-time. See
|
||||
* https://grammy.dev/plugins/keyboard.html#one-time-custom-keyboards for
|
||||
* more details.
|
||||
*
|
||||
* Keyboards are non-one-time by default, use this function to enable it
|
||||
* (without any parameters or pass `true`). Pass `false` to force the
|
||||
* keyboard to be non-one-time.
|
||||
*
|
||||
* @param isEnabled `true` if the keyboard should be one-time, and `false` otherwise
|
||||
*/
|
||||
oneTime(isEnabled = true) {
|
||||
this.one_time_keyboard = isEnabled;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Make the current keyboard resized. See
|
||||
* https://grammy.dev/plugins/keyboard.html#resize-custom-keyboard for more
|
||||
* details.
|
||||
*
|
||||
* Keyboards are non-resized by default, use this function to enable it
|
||||
* (without any parameters or pass `true`). Pass `false` to force the
|
||||
* keyboard to be non-resized.
|
||||
*
|
||||
* @param isEnabled `true` if the keyboard should be resized, and `false` otherwise
|
||||
*/
|
||||
resized(isEnabled = true) {
|
||||
this.resize_keyboard = isEnabled;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Set the current keyboard's input field placeholder. See
|
||||
* https://grammy.dev/plugins/keyboard.html#input-field-placeholder for more
|
||||
* details.
|
||||
*
|
||||
* @param value The placeholder text
|
||||
*/
|
||||
placeholder(value) {
|
||||
this.input_field_placeholder = value;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Creates a new keyboard that contains the transposed grid of buttons of
|
||||
* this keyboard. This means that the resulting keyboard has the rows and
|
||||
* columns flipped.
|
||||
*
|
||||
* Note that buttons can only span multiple columns, but never multiple
|
||||
* rows. This means that if the given arrays have different lengths, some
|
||||
* buttons might flow up in the layout. In these cases, transposing a
|
||||
* keyboard a second time will not undo the first transposition.
|
||||
*
|
||||
* Here are some examples.
|
||||
*
|
||||
* ```
|
||||
* original transposed
|
||||
* [ a ] ~> [ a ]
|
||||
*
|
||||
* [ a ]
|
||||
* [a b c] ~> [ b ]
|
||||
* [ c ]
|
||||
*
|
||||
* [ a b ] [a c e]
|
||||
* [ c d ] ~> [ b d ]
|
||||
* [ e ]
|
||||
*
|
||||
* [ a b ] [a c d]
|
||||
* [ c ] ~> [ b e ]
|
||||
* [d e f] [ f ]
|
||||
* ```
|
||||
*/
|
||||
toTransposed() {
|
||||
const original = this.keyboard;
|
||||
const transposed = transpose(original);
|
||||
return this.clone(transposed);
|
||||
}
|
||||
/**
|
||||
* Creates a new keyboard with the same buttons but reflowed into a given
|
||||
* number of columns as if the buttons were text elements. Optionally, you
|
||||
* can specify if the flow should make sure to fill up the last row.
|
||||
*
|
||||
* This method is idempotent, so calling it a second time will effectively
|
||||
* clone this keyboard without reordering the buttons.
|
||||
*
|
||||
* Here are some examples.
|
||||
*
|
||||
* ```
|
||||
* original flowed
|
||||
* [ a ] ~> [ a ] (4 columns)
|
||||
*
|
||||
* [ a ]
|
||||
* [a b c] ~> [ b ] (1 column)
|
||||
* [ c ]
|
||||
*
|
||||
* [ a b ] [a b c]
|
||||
* [ c d ] ~> [ d e ] (3 columns)
|
||||
* [ e ]
|
||||
*
|
||||
* [ a b ] [abcde]
|
||||
* [ c ] ~> [ f ] (5 columns)
|
||||
* [d e f]
|
||||
*
|
||||
* [a b c] [ a ]
|
||||
* [d e f] ~> [b c d] (3 colums, { fillLastRow: true })
|
||||
* [g h i] [e f g]
|
||||
* [ j ] [h i j]
|
||||
* ```
|
||||
*
|
||||
* @param columns Maximum number of buttons per row
|
||||
* @param options Optional flowing behavior
|
||||
*/
|
||||
toFlowed(columns, options = {}) {
|
||||
const original = this.keyboard;
|
||||
const flowed = reflow(original, columns, options);
|
||||
return this.clone(flowed);
|
||||
}
|
||||
/**
|
||||
* Creates and returns a deep copy of this keyboard.
|
||||
*
|
||||
* Optionally takes a new grid of buttons to replace the current buttons. If
|
||||
* specified, only the options will be cloned, and the given buttons will be
|
||||
* used instead.
|
||||
*/
|
||||
clone(keyboard = this.keyboard) {
|
||||
const clone = new Keyboard(keyboard.map((row) => row.slice()));
|
||||
clone.is_persistent = this.is_persistent;
|
||||
clone.selective = this.selective;
|
||||
clone.one_time_keyboard = this.one_time_keyboard;
|
||||
clone.resize_keyboard = this.resize_keyboard;
|
||||
clone.input_field_placeholder = this.input_field_placeholder;
|
||||
return clone;
|
||||
}
|
||||
/**
|
||||
* Appends the buttons of the given keyboards to this keyboard. If other
|
||||
* options are specified in these keyboards, they will be ignored.
|
||||
*
|
||||
* @param sources A number of keyboards to append
|
||||
*/
|
||||
append(...sources) {
|
||||
for (const source of sources) {
|
||||
const keyboard = Keyboard.from(source);
|
||||
this.keyboard.push(...keyboard.keyboard.map((row) => row.slice()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Returns the keyboard that was build. Note that it doesn't return
|
||||
* `resize_keyboard` or other options that may be set. You don't usually
|
||||
* need to call this method. It is no longer useful.
|
||||
*/
|
||||
build() {
|
||||
return this.keyboard;
|
||||
}
|
||||
/**
|
||||
* Turns a two-dimensional keyboard button array into a keyboard instance.
|
||||
* You can use the static button builder methods to create keyboard button
|
||||
* objects.
|
||||
*
|
||||
* @param source A two-dimensional button array
|
||||
*/
|
||||
static from(source) {
|
||||
if (source instanceof Keyboard)
|
||||
return source.clone();
|
||||
function toButton(btn) {
|
||||
return typeof btn === "string" ? Keyboard.text(btn) : btn;
|
||||
}
|
||||
return new Keyboard(source.map((row) => row.map(toButton)));
|
||||
}
|
||||
}
|
||||
exports.Keyboard = Keyboard;
|
||||
/**
|
||||
* Use this class to simplify building an inline keyboard (something like this:
|
||||
* https://core.telegram.org/bots/features#inline-keyboards).
|
||||
*
|
||||
* ```ts
|
||||
* // Build an inline keyboard:
|
||||
* const keyboard = new InlineKeyboard()
|
||||
* .text('A').text('B', 'callback-data').row()
|
||||
* .text('C').text('D').row()
|
||||
* .url('Telegram', 'telegram.org')
|
||||
*
|
||||
* // Send the keyboard:
|
||||
* await ctx.reply('Here is your inline keyboard!', {
|
||||
* reply_markup: keyboard
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* If you already have some source data which you would like to turn into an
|
||||
* inline button object, you can use the static equivalents which every inline
|
||||
* button has. You can use them to create a two-dimensional inline button array.
|
||||
* The resulting array can be turned into a keyboard instance.
|
||||
*
|
||||
* ```ts
|
||||
* const button = InlineKeyboard.text('GO', 'go')
|
||||
* const array = [[button]]
|
||||
* const keyboard = InlineKeyboard.from(array)
|
||||
* ```
|
||||
*
|
||||
* Be sure to to check the
|
||||
* [documentation](https://grammy.dev/plugins/keyboard.html#inline-keyboards) on
|
||||
* inline keyboards in grammY.
|
||||
*/
|
||||
class InlineKeyboard {
|
||||
/**
|
||||
* Initialize a new `InlineKeyboard` with an optional two-dimensional array
|
||||
* of `InlineKeyboardButton` objects. This is the nested array that holds
|
||||
* the inline keyboard. It will be extended every time you call one of the
|
||||
* provided methods.
|
||||
*
|
||||
* @param inline_keyboard An optional initial two-dimensional button array
|
||||
*/
|
||||
constructor(inline_keyboard = [[]]) {
|
||||
this.inline_keyboard = inline_keyboard;
|
||||
}
|
||||
/**
|
||||
* Allows you to add your own `InlineKeyboardButton` objects if you already
|
||||
* have them for some reason. You most likely want to call one of the other
|
||||
* methods.
|
||||
*
|
||||
* @param buttons The buttons to add
|
||||
*/
|
||||
add(...buttons) {
|
||||
var _a;
|
||||
(_a = this.inline_keyboard[this.inline_keyboard.length - 1]) === null || _a === void 0 ? void 0 : _a.push(...buttons);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Adds a 'line break'. Call this method to make sure that the next added
|
||||
* buttons will be on a new row.
|
||||
*
|
||||
* You may pass a number of `InlineKeyboardButton` objects if you already
|
||||
* have the instances for some reason. You most likely don't want to pass
|
||||
* any arguments to `row`.
|
||||
*
|
||||
* @param buttons A number of buttons to add to the next row
|
||||
*/
|
||||
row(...buttons) {
|
||||
this.inline_keyboard.push(buttons);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Adds a new URL button. Telegram clients will open the provided URL when
|
||||
* the button is pressed.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url HTTP or tg:// url to be opened when the button is pressed. Links tg://user?id=<user_id> can be used to mention a user by their ID without using a username, if this is allowed by their privacy settings.
|
||||
*/
|
||||
url(text, url) {
|
||||
return this.add(InlineKeyboard.url(text, url));
|
||||
}
|
||||
/**
|
||||
* Creates a new URL button. Telegram clients will open the provided URL
|
||||
* when the button is pressed.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url HTTP or tg:// url to be opened when the button is pressed. Links tg://user?id=<user_id> can be used to mention a user by their ID without using a username, if this is allowed by their privacy settings.
|
||||
*/
|
||||
static url(text, url) {
|
||||
return { text, url };
|
||||
}
|
||||
/**
|
||||
* Adds a new callback query button. The button contains a text and a custom
|
||||
* payload. This payload will be sent back to your bot when the button is
|
||||
* pressed. If you omit the payload, the display text will be sent back to
|
||||
* your bot.
|
||||
*
|
||||
* Your bot will receive an update every time a user presses any of the text
|
||||
* buttons. You can listen to these updates like this:
|
||||
* ```ts
|
||||
* // Specific buttons:
|
||||
* bot.callbackQuery('button-data', ctx => { ... })
|
||||
* // Any button of any inline keyboard:
|
||||
* bot.on('callback_query:data', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param data The callback data to send back to your bot (default = text)
|
||||
*/
|
||||
text(text, data = text) {
|
||||
return this.add(InlineKeyboard.text(text, data));
|
||||
}
|
||||
/**
|
||||
* Creates a new callback query button. The button contains a text and a
|
||||
* custom payload. This payload will be sent back to your bot when the
|
||||
* button is pressed. If you omit the payload, the display text will be sent
|
||||
* back to your bot.
|
||||
*
|
||||
* Your bot will receive an update every time a user presses any of the text
|
||||
* buttons. You can listen to these updates like this:
|
||||
* ```ts
|
||||
* // Specific buttons:
|
||||
* bot.callbackQuery('button-data', ctx => { ... })
|
||||
* // Any button of any inline keyboard:
|
||||
* bot.on('callback_query:data', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param data The callback data to send back to your bot (default = text)
|
||||
*/
|
||||
static text(text, data = text) {
|
||||
return { text, callback_data: data };
|
||||
}
|
||||
/**
|
||||
* Adds a new web app button, confer https://core.telegram.org/bots/webapps
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url An HTTPS URL of a Web App to be opened with additional data
|
||||
*/
|
||||
webApp(text, url) {
|
||||
return this.add(InlineKeyboard.webApp(text, url));
|
||||
}
|
||||
/**
|
||||
* Creates a new web app button, confer https://core.telegram.org/bots/webapps
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param url An HTTPS URL of a Web App to be opened with additional data
|
||||
*/
|
||||
static webApp(text, url) {
|
||||
return { text, web_app: { url } };
|
||||
}
|
||||
/**
|
||||
* Adds a new login button. This can be used as a replacement for the
|
||||
* Telegram Login Widget. You must specify an HTTPS URL used to
|
||||
* automatically authorize the user.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param loginUrl The login URL as string or `LoginUrl` object
|
||||
*/
|
||||
login(text, loginUrl) {
|
||||
return this.add(InlineKeyboard.login(text, loginUrl));
|
||||
}
|
||||
/**
|
||||
* Creates a new login button. This can be used as a replacement for the
|
||||
* Telegram Login Widget. You must specify an HTTPS URL used to
|
||||
* automatically authorize the user.
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param loginUrl The login URL as string or `LoginUrl` object
|
||||
*/
|
||||
static login(text, loginUrl) {
|
||||
return {
|
||||
text,
|
||||
login_url: typeof loginUrl === "string"
|
||||
? { url: loginUrl }
|
||||
: loginUrl,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Adds a new inline query button. Telegram clients will let the user pick a
|
||||
* chat when this button is pressed. This will start an inline query. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The (optional) inline query string to prefill
|
||||
*/
|
||||
switchInline(text, query = "") {
|
||||
return this.add(InlineKeyboard.switchInline(text, query));
|
||||
}
|
||||
/**
|
||||
* Creates a new inline query button. Telegram clients will let the user pick a
|
||||
* chat when this button is pressed. This will start an inline query. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The (optional) inline query string to prefill
|
||||
*/
|
||||
static switchInline(text, query = "") {
|
||||
return { text, switch_inline_query: query };
|
||||
}
|
||||
/**
|
||||
* Adds a new inline query button that acts on the current chat. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it. This will start an inline
|
||||
* query.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The (optional) inline query string to prefill
|
||||
*/
|
||||
switchInlineCurrent(text, query = "") {
|
||||
return this.add(InlineKeyboard.switchInlineCurrent(text, query));
|
||||
}
|
||||
/**
|
||||
* Creates a new inline query button that acts on the current chat. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it. This will start an inline
|
||||
* query.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The (optional) inline query string to prefill
|
||||
*/
|
||||
static switchInlineCurrent(text, query = "") {
|
||||
return { text, switch_inline_query_current_chat: query };
|
||||
}
|
||||
/**
|
||||
* Adds a new inline query button. Telegram clients will let the user pick a
|
||||
* chat when this button is pressed. This will start an inline query. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The query object describing which chats can be picked
|
||||
*/
|
||||
switchInlineChosen(text, query = {}) {
|
||||
return this.add(InlineKeyboard.switchInlineChosen(text, query));
|
||||
}
|
||||
/**
|
||||
* Creates a new inline query button. Telegram clients will let the user pick a
|
||||
* chat when this button is pressed. This will start an inline query. The
|
||||
* selected chat will be prefilled with the name of your bot. You may
|
||||
* provide a text that is specified along with it.
|
||||
*
|
||||
* Your bot will in turn receive updates for inline queries. You can listen
|
||||
* to inline query updates like this:
|
||||
* ```ts
|
||||
* bot.on('inline_query', ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* @param text The text to display
|
||||
* @param query The query object describing which chats can be picked
|
||||
*/
|
||||
static switchInlineChosen(text, query = {}) {
|
||||
return { text, switch_inline_query_chosen_chat: query };
|
||||
}
|
||||
/**
|
||||
* Adds a new game query button, confer
|
||||
* https://core.telegram.org/bots/api#games
|
||||
*
|
||||
* This type of button must always be the first button in the first row.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
game(text) {
|
||||
return this.add(InlineKeyboard.game(text));
|
||||
}
|
||||
/**
|
||||
* Creates a new game query button, confer
|
||||
* https://core.telegram.org/bots/api#games
|
||||
*
|
||||
* This type of button must always be the first button in the first row.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static game(text) {
|
||||
return { text, callback_game: {} };
|
||||
}
|
||||
/**
|
||||
* Adds a new payment button, confer
|
||||
* https://core.telegram.org/bots/api#payments
|
||||
*
|
||||
* This type of button must always be the first button in the first row and
|
||||
* can only be used in invoice messages.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
pay(text) {
|
||||
return this.add(InlineKeyboard.pay(text));
|
||||
}
|
||||
/**
|
||||
* Create a new payment button, confer
|
||||
* https://core.telegram.org/bots/api#payments
|
||||
*
|
||||
* This type of button must always be the first button in the first row and
|
||||
* can only be used in invoice messages.
|
||||
*
|
||||
* @param text The text to display
|
||||
*/
|
||||
static pay(text) {
|
||||
return { text, pay: true };
|
||||
}
|
||||
/**
|
||||
* Creates a new inline keyboard that contains the transposed grid of
|
||||
* buttons of this inline keyboard. This means that the resulting inline
|
||||
* keyboard has the rows and columns flipped.
|
||||
*
|
||||
* Note that inline buttons can only span multiple columns, but never
|
||||
* multiple rows. This means that if the given arrays have different
|
||||
* lengths, some buttons might flow up in the layout. In these cases,
|
||||
* transposing an inline keyboard a second time will not undo the first
|
||||
* transposition.
|
||||
*
|
||||
* Here are some examples.
|
||||
*
|
||||
* ```
|
||||
* original transposed
|
||||
* [ a ] ~> [ a ]
|
||||
*
|
||||
* [ a ]
|
||||
* [a b c] ~> [ b ]
|
||||
* [ c ]
|
||||
*
|
||||
* [ a b ] [a c e]
|
||||
* [ c d ] ~> [ b d ]
|
||||
* [ e ]
|
||||
*
|
||||
* [ a b ] [a c d]
|
||||
* [ c ] ~> [ b e ]
|
||||
* [d e f] [ f ]
|
||||
* ```
|
||||
*/
|
||||
toTransposed() {
|
||||
const original = this.inline_keyboard;
|
||||
const transposed = transpose(original);
|
||||
return new InlineKeyboard(transposed);
|
||||
}
|
||||
/**
|
||||
* Creates a new inline keyboard with the same buttons but reflowed into a
|
||||
* given number of columns as if the buttons were text elements. Optionally,
|
||||
* you can specify if the flow should make sure to fill up the last row.
|
||||
*
|
||||
* This method is idempotent, so calling it a second time will effectively
|
||||
* clone this inline keyboard without reordering the buttons.
|
||||
*
|
||||
* Here are some examples.
|
||||
*
|
||||
* ```
|
||||
* original flowed
|
||||
* [ a ] ~> [ a ] (4 columns)
|
||||
*
|
||||
* [ a ]
|
||||
* [a b c] ~> [ b ] (1 column)
|
||||
* [ c ]
|
||||
*
|
||||
* [ a b ] [a b c]
|
||||
* [ c d ] ~> [ d e ] (3 columns)
|
||||
* [ e ]
|
||||
*
|
||||
* [ a b ] [abcde]
|
||||
* [ c ] ~> [ f ] (5 columns)
|
||||
* [d e f]
|
||||
*
|
||||
* [a b c] [ a ]
|
||||
* [d e f] ~> [b c d] (3 colums, { fillLastRow: true })
|
||||
* [g h i] [e f g]
|
||||
* [ j ] [h i j]
|
||||
* ```
|
||||
*
|
||||
* @param columns Maximum number of buttons per row
|
||||
* @param options Optional flowing behavior
|
||||
*/
|
||||
toFlowed(columns, options = {}) {
|
||||
const original = this.inline_keyboard;
|
||||
const flowed = reflow(original, columns, options);
|
||||
return new InlineKeyboard(flowed);
|
||||
}
|
||||
/**
|
||||
* Creates and returns a deep copy of this inline keyboard.
|
||||
*/
|
||||
clone() {
|
||||
return new InlineKeyboard(this.inline_keyboard.map((row) => row.slice()));
|
||||
}
|
||||
/**
|
||||
* Appends the buttons of the given inline keyboards to this keyboard.
|
||||
*
|
||||
* @param sources A number of inline keyboards to append
|
||||
*/
|
||||
append(...sources) {
|
||||
for (const source of sources) {
|
||||
const keyboard = InlineKeyboard.from(source);
|
||||
this.inline_keyboard.push(...keyboard.inline_keyboard.map((row) => row.slice()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Turns a two-dimensional inline button array into an inline keyboard
|
||||
* instance. You can use the static button builder methods to create inline
|
||||
* button objects.
|
||||
*
|
||||
* @param source A two-dimensional inline button array
|
||||
*/
|
||||
static from(source) {
|
||||
if (source instanceof InlineKeyboard)
|
||||
return source.clone();
|
||||
return new InlineKeyboard(source.map((row) => row.slice()));
|
||||
}
|
||||
}
|
||||
exports.InlineKeyboard = InlineKeyboard;
|
||||
function transpose(grid) {
|
||||
var _a;
|
||||
const transposed = [];
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
const row = grid[i];
|
||||
for (let j = 0; j < row.length; j++) {
|
||||
const button = row[j];
|
||||
((_a = transposed[j]) !== null && _a !== void 0 ? _a : (transposed[j] = [])).push(button);
|
||||
}
|
||||
}
|
||||
return transposed;
|
||||
}
|
||||
function reflow(grid, columns, { fillLastRow = false }) {
|
||||
var _a;
|
||||
let first = columns;
|
||||
if (fillLastRow) {
|
||||
const buttonCount = grid
|
||||
.map((row) => row.length)
|
||||
.reduce((a, b) => a + b, 0);
|
||||
first = buttonCount % columns;
|
||||
}
|
||||
const reflowed = [];
|
||||
for (const row of grid) {
|
||||
for (const button of row) {
|
||||
const at = Math.max(0, reflowed.length - 1);
|
||||
const max = at === 0 ? first : columns;
|
||||
let next = ((_a = reflowed[at]) !== null && _a !== void 0 ? _a : (reflowed[at] = []));
|
||||
if (next.length === max) {
|
||||
next = [];
|
||||
reflowed.push(next);
|
||||
}
|
||||
next.push(button);
|
||||
}
|
||||
}
|
||||
return reflowed;
|
||||
}
|
338
node_modules/grammy/out/convenience/session.d.ts
generated
vendored
Normal file
338
node_modules/grammy/out/convenience/session.d.ts
generated
vendored
Normal file
@ -0,0 +1,338 @@
|
||||
import { type MiddlewareFn } from "../composer.js";
|
||||
import { type Context } from "../context.js";
|
||||
type MaybePromise<T> = Promise<T> | T;
|
||||
/**
|
||||
* A session flavor is a context flavor that holds session data under
|
||||
* `ctx.session`.
|
||||
*
|
||||
* Session middleware will load the session data of a specific chat from your
|
||||
* storage solution, and make it available to you on the context object. Check
|
||||
* out the
|
||||
* [documentation](https://doc.deno.land/https://deno.land/x/grammy/mod.ts/~/session)
|
||||
* on session middleware to know more, and read the section about sessions on
|
||||
* the [website](https://grammy.dev/plugins/session.html).
|
||||
*/
|
||||
export interface SessionFlavor<S> {
|
||||
/**
|
||||
* Session data on the context object.
|
||||
*
|
||||
* **WARNING:** You have to make sure that your session data is not
|
||||
* undefined by _providing an initial value to the session middleware_, or by
|
||||
* making sure that `ctx.session` is assigned if it is empty! The type
|
||||
* system does not include `| undefined` because this is really annoying to
|
||||
* work with.
|
||||
*
|
||||
* Accessing `ctx.session` by reading or writing will throw if
|
||||
* `getSessionKey(ctx) === undefined` for the respective context object
|
||||
* `ctx`.
|
||||
*/
|
||||
get session(): S;
|
||||
set session(session: S | null | undefined);
|
||||
}
|
||||
/**
|
||||
* A lazy session flavor is a context flavor that holds a promise of some
|
||||
* session data under `ctx.session`.
|
||||
*
|
||||
* Lazy session middleware will provide this promise lazily on the context
|
||||
* object. Once you access `ctx.session`, the storage will be queried and the
|
||||
* session data becomes available. If you access `ctx.session` again for the
|
||||
* same context object, the cached value will be used. Check out the
|
||||
* [documentation](https://doc.deno.land/https://deno.land/x/grammy/mod.ts/~/lazySession)
|
||||
* on lazy session middleware to know more, and read the section about lazy
|
||||
* sessions on the
|
||||
* [website](https://grammy.dev/plugins/session.html#lazy-sessions).
|
||||
*/
|
||||
export interface LazySessionFlavor<S> {
|
||||
/**
|
||||
* Session data on the context object, potentially a promise.
|
||||
*
|
||||
* **WARNING:** You have to make sure that your session data is not
|
||||
* undefined by _providing a default value to the session middleware_, or by
|
||||
* making sure that `ctx.session` is assigned if it is empty! The type
|
||||
* system does not include `| undefined` because this is really annoying to
|
||||
* work with.
|
||||
*
|
||||
* Accessing `ctx.session` by reading or writing will throw iff
|
||||
* `getSessionKey(ctx) === undefined` holds for the respective context
|
||||
* object `ctx`.
|
||||
*/
|
||||
get session(): MaybePromise<S>;
|
||||
set session(session: MaybePromise<S | null | undefined>);
|
||||
}
|
||||
/**
|
||||
* A storage adapter is an abstraction that provides read, write, and delete
|
||||
* access to a storage solution of any kind. Storage adapters are used to keep
|
||||
* session middleware independent of your database provider, and they allow you
|
||||
* to pass your own storage solution.
|
||||
*/
|
||||
export interface StorageAdapter<T> {
|
||||
/**
|
||||
* Reads a value for the given key from the storage. May return the value or
|
||||
* undefined, or a promise of either.
|
||||
*/
|
||||
read: (key: string) => MaybePromise<T | undefined>;
|
||||
/**
|
||||
* Writes a value for the given key to the storage.
|
||||
*/
|
||||
write: (key: string, value: T) => MaybePromise<void>;
|
||||
/**
|
||||
* Deletes a value for the given key from the storage.
|
||||
*/
|
||||
delete: (key: string) => MaybePromise<void>;
|
||||
/**
|
||||
* Checks whether a key exists in the storage.
|
||||
*/
|
||||
has?: (key: string) => MaybePromise<boolean>;
|
||||
/**
|
||||
* Lists all keys.
|
||||
*/
|
||||
readAllKeys?: () => Iterable<string> | AsyncIterable<string>;
|
||||
/**
|
||||
* Lists all values.
|
||||
*/
|
||||
readAllValues?: () => Iterable<T> | AsyncIterable<T>;
|
||||
/**
|
||||
* Lists all keys with their values.
|
||||
*/
|
||||
readAllEntries?: () => Iterable<[key: string, value: T]> | AsyncIterable<[key: string, value: T]>;
|
||||
}
|
||||
/**
|
||||
* Options for session middleware.
|
||||
*/
|
||||
export interface SessionOptions<S, C extends Context = Context> {
|
||||
type?: "single";
|
||||
/**
|
||||
* **Recommended to use.**
|
||||
*
|
||||
* A function that produces an initial value for `ctx.session`. This
|
||||
* function will be called every time the storage solution returns undefined
|
||||
* for a given session key. Make sure to create a new value every time, such
|
||||
* that different context objects do that accidentally share the same
|
||||
* session data.
|
||||
*/
|
||||
initial?: () => S;
|
||||
/**
|
||||
* This option lets you generate your own session keys per context object.
|
||||
* The session key determines how to map the different session objects to
|
||||
* your chats and users. Check out the
|
||||
* [documentation](https://grammy.dev/plugins/session.html#how-to-use-sessions)
|
||||
* on the website about how to use session middleware to know how session
|
||||
* keys are used.
|
||||
*
|
||||
* The default implementation will store sessions per chat, as determined by
|
||||
* `ctx.chat?.id`.
|
||||
*/
|
||||
getSessionKey?: (ctx: Omit<C, "session">) => MaybePromise<string | undefined>;
|
||||
/**
|
||||
* A storage adapter to your storage solution. Provides read, write, and
|
||||
* delete access to the session middleware.
|
||||
*
|
||||
* Consider using a [known storage
|
||||
* adapter](https://grammy.dev/plugins/session.html#known-storage-adapters)
|
||||
* instead of rolling your own implementation of this.
|
||||
*
|
||||
* The default implementation will store session in memory. The data will be
|
||||
* lost whenever your bot restarts.
|
||||
*/
|
||||
storage?: StorageAdapter<S>;
|
||||
}
|
||||
/**
|
||||
* Options for session middleware if multi sessions are used. Specify `"type":
|
||||
* "multi"` in the options to use multi sessions.
|
||||
*/
|
||||
export type MultiSessionOptions<S, C extends Context> = S extends Record<string, any> ? {
|
||||
type: "multi";
|
||||
} & MultiSessionOptionsRecord<S, C> : never;
|
||||
type MultiSessionOptionsRecord<S extends Record<string, unknown>, C extends Context> = {
|
||||
[K in keyof S]: SessionOptions<S[K], C>;
|
||||
};
|
||||
/**
|
||||
* Session middleware provides a persistent data storage for your bot. You can
|
||||
* use it to let your bot remember any data you want, for example the messages
|
||||
* it sent or received in the past. This is done by attaching _session data_ to
|
||||
* every chat. The stored data is then provided on the context object under
|
||||
* `ctx.session`.
|
||||
*
|
||||
* > **What is a session?** Simply put, the session of a chat is a little
|
||||
* > persistent storage that is attached to it. As an example, your bot can send
|
||||
* > a message to a chat and store the ID of that message in the corresponding
|
||||
* > session. The next time your bot receives an update from that chat, the
|
||||
* > session will still contain that ID.
|
||||
* >
|
||||
* > Session data can be stored in a database, in a file, or simply in memory.
|
||||
* > grammY only supports memory sessions out of the box, but you can use
|
||||
* > third-party session middleware to connect to other storage solutions. Note
|
||||
* > that memory sessions will be lost when you stop your bot and the process
|
||||
* > exits, so they are usually not useful in production.
|
||||
*
|
||||
* Whenever your bot receives an update, the first thing the session middleware
|
||||
* will do is to load the correct session from your storage solution. This
|
||||
* object is then provided on `ctx.session` while your other middleware is
|
||||
* running. As soon as your bot is done handling the update, the middleware
|
||||
* takes over again and writes back the session object to your storage. This
|
||||
* allows you to modify the session object arbitrarily in your middleware, and
|
||||
* to stop worrying about the database.
|
||||
*
|
||||
* ```ts
|
||||
* bot.use(session())
|
||||
*
|
||||
* bot.on('message', ctx => {
|
||||
* // The session object is persisted across updates!
|
||||
* const session = ctx.session
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* It is recommended to make use of the `initial` option in the configuration
|
||||
* object, which correctly initializes session objects for new chats.
|
||||
*
|
||||
* You can delete the session data by setting `ctx.session` to `null` or
|
||||
* `undefined`.
|
||||
*
|
||||
* Check out the [documentation](https://grammy.dev/plugins/session.html) on the
|
||||
* website to know more about how sessions work in grammY.
|
||||
*
|
||||
* @param options Optional configuration to pass to the session middleware
|
||||
*/
|
||||
export declare function session<S, C extends Context>(options?: SessionOptions<S, C> | MultiSessionOptions<S, C>): MiddlewareFn<C & SessionFlavor<S>>;
|
||||
/**
|
||||
* > This is an advanced function of grammY.
|
||||
*
|
||||
* Generally speaking, lazy sessions work just like normal sessions—just they
|
||||
* are loaded on demand. Except for a few `async`s and `await`s here and there,
|
||||
* their usage looks 100 % identical.
|
||||
*
|
||||
* Instead of directly querying the storage every time an update arrives, lazy
|
||||
* sessions quickly do this _once you access_ `ctx.session`. This can
|
||||
* significantly reduce the database traffic (especially when your bot is added
|
||||
* to group chats), because it skips a read and a wrote operation for all
|
||||
* updates that the bot does not react to.
|
||||
*
|
||||
* ```ts
|
||||
* // The options are identical
|
||||
* bot.use(lazySession({ storage: ... }))
|
||||
*
|
||||
* bot.on('message', async ctx => {
|
||||
* // The session object is persisted across updates!
|
||||
* const session = await ctx.session
|
||||
* // ^
|
||||
* // |
|
||||
* // This plain property access (no function call) will trigger the database query!
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* Check out the
|
||||
* [documentation](https://grammy.dev/plugins/session.html#lazy-sessions) on the
|
||||
* website to know more about how lazy sessions work in grammY.
|
||||
*
|
||||
* @param options Optional configuration to pass to the session middleware
|
||||
*/
|
||||
export declare function lazySession<S, C extends Context>(options?: SessionOptions<S, C>): MiddlewareFn<C & LazySessionFlavor<S>>;
|
||||
/**
|
||||
* When enhancing a storage adapter, it needs to be able to store additional
|
||||
* information. It does this by wrapping the actual data inside an object, and
|
||||
* adding more properties to this wrapper.
|
||||
*
|
||||
* This interface defines the additional properties that need to be stored by a
|
||||
* storage adapter that supports enhanced sessions.
|
||||
*/
|
||||
export interface Enhance<T> {
|
||||
/** Version */
|
||||
v?: number;
|
||||
/** Data */
|
||||
__d: T;
|
||||
/** Expiry date */
|
||||
e?: number;
|
||||
}
|
||||
/** Options for enhanced sessions */
|
||||
export interface MigrationOptions<T> {
|
||||
/** The original storage adapter that will be enhanced */
|
||||
storage: StorageAdapter<Enhance<T>>;
|
||||
/**
|
||||
* A set of session migrations, defined as an object mapping from version
|
||||
* numbers to migration functions that transform data to the respective
|
||||
* version.
|
||||
*/
|
||||
migrations?: Migrations;
|
||||
/**
|
||||
* Number of milliseconds after the last write operation until the session
|
||||
* data expires.
|
||||
*/
|
||||
millisecondsToLive?: number;
|
||||
}
|
||||
/**
|
||||
* A mapping from version numbers to session migration functions. Each entry in
|
||||
* this object has a version number as a key, and a function as a value.
|
||||
*
|
||||
* For a key `n`, the respective value should be a function that takes the
|
||||
* previous session data and migrates it to conform with the data that is used
|
||||
* by version `n`. The previous session data is defined by the next key less
|
||||
* than `n`, such as `n-1`. Versions don't have to be integers, nor do all
|
||||
* versions have to be adjacent. For example, you can use `[1, 1.5, 4]` as
|
||||
* versions. If `n` is the lowest value in the set of keys, the function stored
|
||||
* for `n` can be used to migrate session data that was stored before migrations
|
||||
* were used.
|
||||
*/
|
||||
export interface Migrations {
|
||||
[version: number]: (old: any) => any;
|
||||
}
|
||||
/**
|
||||
* You can use this function to transform an existing storage adapter, and add
|
||||
* more features to it. Currently, you can add session migrations and expiry
|
||||
* dates.
|
||||
*
|
||||
* You can use this function like so:
|
||||
* ```ts
|
||||
* const storage = ... // define your storage adapter
|
||||
* const enhanced = enhanceStorage({ storage, millisecondsToLive: 500 })
|
||||
* bot.use(session({ storage: enhanced }))
|
||||
* ```
|
||||
*
|
||||
* @param options Session enhancing options
|
||||
* @returns The enhanced storage adapter
|
||||
*/
|
||||
export declare function enhanceStorage<T>(options: MigrationOptions<T>): StorageAdapter<T>;
|
||||
/**
|
||||
* The memory session storage is a built-in storage adapter that saves your
|
||||
* session data in RAM using a regular JavaScript `Map` object. If you use this
|
||||
* storage adapter, all sessions will be lost when your process terminates or
|
||||
* restarts. Hence, you should only use it for short-lived data that is not
|
||||
* important to persist.
|
||||
*
|
||||
* This class is used as default if you do not provide a storage adapter, e.g.
|
||||
* to your database.
|
||||
*
|
||||
* This storage adapter features expiring sessions. When instantiating this class
|
||||
* yourself, you can pass a time to live in milliseconds that will be used for
|
||||
* each session object. If a session for a user expired, the session data will
|
||||
* be discarded on its first read, and a fresh session object as returned by the
|
||||
* `initial` option (or undefined) will be put into place.
|
||||
*/
|
||||
export declare class MemorySessionStorage<S> implements StorageAdapter<S> {
|
||||
private readonly timeToLive?;
|
||||
/**
|
||||
* Internally used `Map` instance that stores the session data
|
||||
*/
|
||||
protected readonly storage: Map<string, {
|
||||
session: S;
|
||||
expires?: number | undefined;
|
||||
}>;
|
||||
/**
|
||||
* Constructs a new memory session storage with the given time to live. Note
|
||||
* that this storage adapter will not store your data permanently.
|
||||
*
|
||||
* @param timeToLive TTL in milliseconds, default is `Infinity`
|
||||
*/
|
||||
constructor(timeToLive?: number | undefined);
|
||||
read(key: string): S | undefined;
|
||||
/**
|
||||
* @deprecated Use {@link readAllValues} instead
|
||||
*/
|
||||
readAll(): S[];
|
||||
readAllKeys(): string[];
|
||||
readAllValues(): S[];
|
||||
readAllEntries(): [string, S][];
|
||||
has(key: string): boolean;
|
||||
write(key: string, value: S): void;
|
||||
delete(key: string): void;
|
||||
}
|
||||
export {};
|
447
node_modules/grammy/out/convenience/session.js
generated
vendored
Normal file
447
node_modules/grammy/out/convenience/session.js
generated
vendored
Normal file
@ -0,0 +1,447 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MemorySessionStorage = exports.enhanceStorage = exports.lazySession = exports.session = void 0;
|
||||
const platform_node_js_1 = require("../platform.node.js");
|
||||
const debug = (0, platform_node_js_1.debug)("grammy:session");
|
||||
/**
|
||||
* Session middleware provides a persistent data storage for your bot. You can
|
||||
* use it to let your bot remember any data you want, for example the messages
|
||||
* it sent or received in the past. This is done by attaching _session data_ to
|
||||
* every chat. The stored data is then provided on the context object under
|
||||
* `ctx.session`.
|
||||
*
|
||||
* > **What is a session?** Simply put, the session of a chat is a little
|
||||
* > persistent storage that is attached to it. As an example, your bot can send
|
||||
* > a message to a chat and store the ID of that message in the corresponding
|
||||
* > session. The next time your bot receives an update from that chat, the
|
||||
* > session will still contain that ID.
|
||||
* >
|
||||
* > Session data can be stored in a database, in a file, or simply in memory.
|
||||
* > grammY only supports memory sessions out of the box, but you can use
|
||||
* > third-party session middleware to connect to other storage solutions. Note
|
||||
* > that memory sessions will be lost when you stop your bot and the process
|
||||
* > exits, so they are usually not useful in production.
|
||||
*
|
||||
* Whenever your bot receives an update, the first thing the session middleware
|
||||
* will do is to load the correct session from your storage solution. This
|
||||
* object is then provided on `ctx.session` while your other middleware is
|
||||
* running. As soon as your bot is done handling the update, the middleware
|
||||
* takes over again and writes back the session object to your storage. This
|
||||
* allows you to modify the session object arbitrarily in your middleware, and
|
||||
* to stop worrying about the database.
|
||||
*
|
||||
* ```ts
|
||||
* bot.use(session())
|
||||
*
|
||||
* bot.on('message', ctx => {
|
||||
* // The session object is persisted across updates!
|
||||
* const session = ctx.session
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* It is recommended to make use of the `initial` option in the configuration
|
||||
* object, which correctly initializes session objects for new chats.
|
||||
*
|
||||
* You can delete the session data by setting `ctx.session` to `null` or
|
||||
* `undefined`.
|
||||
*
|
||||
* Check out the [documentation](https://grammy.dev/plugins/session.html) on the
|
||||
* website to know more about how sessions work in grammY.
|
||||
*
|
||||
* @param options Optional configuration to pass to the session middleware
|
||||
*/
|
||||
function session(options = {}) {
|
||||
return options.type === "multi"
|
||||
? strictMultiSession(options)
|
||||
: strictSingleSession(options);
|
||||
}
|
||||
exports.session = session;
|
||||
function strictSingleSession(options) {
|
||||
const { initial, storage, getSessionKey, custom } = fillDefaults(options);
|
||||
return async (ctx, next) => {
|
||||
const propSession = new PropertySession(storage, ctx, "session", initial);
|
||||
const key = await getSessionKey(ctx);
|
||||
await propSession.init(key, { custom, lazy: false });
|
||||
await next(); // no catch: do not write back if middleware throws
|
||||
await propSession.finish();
|
||||
};
|
||||
}
|
||||
function strictMultiSession(options) {
|
||||
const props = Object.keys(options).filter((k) => k !== "type");
|
||||
const defaults = Object.fromEntries(props.map((prop) => [prop, fillDefaults(options[prop])]));
|
||||
return async (ctx, next) => {
|
||||
ctx.session = {};
|
||||
const propSessions = await Promise.all(props.map(async (prop) => {
|
||||
const { initial, storage, getSessionKey, custom } = defaults[prop];
|
||||
const s = new PropertySession(
|
||||
// @ts-ignore cannot express that the storage works for a concrete prop
|
||||
storage, ctx.session, prop, initial);
|
||||
const key = await getSessionKey(ctx);
|
||||
await s.init(key, { custom, lazy: false });
|
||||
return s;
|
||||
}));
|
||||
await next(); // no catch: do not write back if middleware throws
|
||||
if (ctx.session == null)
|
||||
propSessions.forEach((s) => s.delete());
|
||||
await Promise.all(propSessions.map((s) => s.finish()));
|
||||
};
|
||||
}
|
||||
/**
|
||||
* > This is an advanced function of grammY.
|
||||
*
|
||||
* Generally speaking, lazy sessions work just like normal sessions—just they
|
||||
* are loaded on demand. Except for a few `async`s and `await`s here and there,
|
||||
* their usage looks 100 % identical.
|
||||
*
|
||||
* Instead of directly querying the storage every time an update arrives, lazy
|
||||
* sessions quickly do this _once you access_ `ctx.session`. This can
|
||||
* significantly reduce the database traffic (especially when your bot is added
|
||||
* to group chats), because it skips a read and a wrote operation for all
|
||||
* updates that the bot does not react to.
|
||||
*
|
||||
* ```ts
|
||||
* // The options are identical
|
||||
* bot.use(lazySession({ storage: ... }))
|
||||
*
|
||||
* bot.on('message', async ctx => {
|
||||
* // The session object is persisted across updates!
|
||||
* const session = await ctx.session
|
||||
* // ^
|
||||
* // |
|
||||
* // This plain property access (no function call) will trigger the database query!
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* Check out the
|
||||
* [documentation](https://grammy.dev/plugins/session.html#lazy-sessions) on the
|
||||
* website to know more about how lazy sessions work in grammY.
|
||||
*
|
||||
* @param options Optional configuration to pass to the session middleware
|
||||
*/
|
||||
function lazySession(options = {}) {
|
||||
if (options.type !== undefined && options.type !== "single") {
|
||||
throw new Error("Cannot use lazy multi sessions!");
|
||||
}
|
||||
const { initial, storage, getSessionKey, custom } = fillDefaults(options);
|
||||
return async (ctx, next) => {
|
||||
const propSession = new PropertySession(
|
||||
// @ts-ignore suppress promise nature of values
|
||||
storage, ctx, "session", initial);
|
||||
const key = await getSessionKey(ctx);
|
||||
await propSession.init(key, { custom, lazy: true });
|
||||
await next(); // no catch: do not write back if middleware throws
|
||||
await propSession.finish();
|
||||
};
|
||||
}
|
||||
exports.lazySession = lazySession;
|
||||
/**
|
||||
* Internal class that manages a single property on the session. Can be used
|
||||
* both in a strict and a lazy way. Works by using `Object.defineProperty` to
|
||||
* install `O[P]`.
|
||||
*/
|
||||
// deno-lint-ignore ban-types
|
||||
class PropertySession {
|
||||
constructor(storage, obj, prop, initial) {
|
||||
this.storage = storage;
|
||||
this.obj = obj;
|
||||
this.prop = prop;
|
||||
this.initial = initial;
|
||||
this.fetching = false;
|
||||
this.read = false;
|
||||
this.wrote = false;
|
||||
}
|
||||
/** Performs a read op and stores the result in `this.value` */
|
||||
load() {
|
||||
if (this.key === undefined) {
|
||||
// No session key provided, cannot load
|
||||
return;
|
||||
}
|
||||
if (this.wrote) {
|
||||
// Value was set, no need to load
|
||||
return;
|
||||
}
|
||||
// Perform read op if not cached
|
||||
if (this.promise === undefined) {
|
||||
this.fetching = true;
|
||||
this.promise = Promise.resolve(this.storage.read(this.key))
|
||||
.then((val) => {
|
||||
var _a;
|
||||
this.fetching = false;
|
||||
// Check for write op in the meantime
|
||||
if (this.wrote) {
|
||||
// Discard read op
|
||||
return this.value;
|
||||
}
|
||||
// Store received value in `this.value`
|
||||
if (val !== undefined) {
|
||||
this.value = val;
|
||||
return val;
|
||||
}
|
||||
// No value, need to initialize
|
||||
val = (_a = this.initial) === null || _a === void 0 ? void 0 : _a.call(this);
|
||||
if (val !== undefined) {
|
||||
// Wrote initial value
|
||||
this.wrote = true;
|
||||
this.value = val;
|
||||
}
|
||||
return val;
|
||||
});
|
||||
}
|
||||
return this.promise;
|
||||
}
|
||||
async init(key, opts) {
|
||||
this.key = key;
|
||||
if (!opts.lazy)
|
||||
await this.load();
|
||||
Object.defineProperty(this.obj, this.prop, {
|
||||
enumerable: true,
|
||||
get: () => {
|
||||
if (key === undefined) {
|
||||
const msg = undef("access", opts);
|
||||
throw new Error(msg);
|
||||
}
|
||||
this.read = true;
|
||||
if (!opts.lazy || this.wrote)
|
||||
return this.value;
|
||||
this.load();
|
||||
return this.fetching ? this.promise : this.value;
|
||||
},
|
||||
set: (v) => {
|
||||
if (key === undefined) {
|
||||
const msg = undef("assign", opts);
|
||||
throw new Error(msg);
|
||||
}
|
||||
this.wrote = true;
|
||||
this.fetching = false;
|
||||
this.value = v;
|
||||
},
|
||||
});
|
||||
}
|
||||
delete() {
|
||||
Object.assign(this.obj, { [this.prop]: undefined });
|
||||
}
|
||||
async finish() {
|
||||
if (this.key !== undefined) {
|
||||
if (this.read)
|
||||
await this.load();
|
||||
if (this.read || this.wrote) {
|
||||
const value = await this.value;
|
||||
if (value == null)
|
||||
await this.storage.delete(this.key);
|
||||
else
|
||||
await this.storage.write(this.key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function fillDefaults(opts = {}) {
|
||||
let { getSessionKey = defaultGetSessionKey, initial, storage } = opts;
|
||||
if (storage == null) {
|
||||
debug("Storing session data in memory, all data will be lost when the bot restarts.");
|
||||
storage = new MemorySessionStorage();
|
||||
}
|
||||
const custom = getSessionKey !== defaultGetSessionKey;
|
||||
return { initial, storage, getSessionKey, custom };
|
||||
}
|
||||
/** Stores session data per chat by default */
|
||||
function defaultGetSessionKey(ctx) {
|
||||
var _a;
|
||||
return (_a = ctx.chat) === null || _a === void 0 ? void 0 : _a.id.toString();
|
||||
}
|
||||
/** Returns a useful error message for when the session key is undefined */
|
||||
function undef(op, opts) {
|
||||
const { lazy = false, custom } = opts;
|
||||
const reason = custom
|
||||
? "the custom `getSessionKey` function returned undefined for this update"
|
||||
: "this update does not belong to a chat, so the session key is undefined";
|
||||
return `Cannot ${op} ${lazy ? "lazy " : ""}session data because ${reason}!`;
|
||||
}
|
||||
function isEnhance(value) {
|
||||
return value === undefined ||
|
||||
typeof value === "object" && value !== null && "__d" in value;
|
||||
}
|
||||
/**
|
||||
* You can use this function to transform an existing storage adapter, and add
|
||||
* more features to it. Currently, you can add session migrations and expiry
|
||||
* dates.
|
||||
*
|
||||
* You can use this function like so:
|
||||
* ```ts
|
||||
* const storage = ... // define your storage adapter
|
||||
* const enhanced = enhanceStorage({ storage, millisecondsToLive: 500 })
|
||||
* bot.use(session({ storage: enhanced }))
|
||||
* ```
|
||||
*
|
||||
* @param options Session enhancing options
|
||||
* @returns The enhanced storage adapter
|
||||
*/
|
||||
function enhanceStorage(options) {
|
||||
let { storage, millisecondsToLive, migrations } = options;
|
||||
storage = compatStorage(storage);
|
||||
if (millisecondsToLive !== undefined) {
|
||||
storage = timeoutStorage(storage, millisecondsToLive);
|
||||
}
|
||||
if (migrations !== undefined) {
|
||||
storage = migrationStorage(storage, migrations);
|
||||
}
|
||||
return wrapStorage(storage);
|
||||
}
|
||||
exports.enhanceStorage = enhanceStorage;
|
||||
function compatStorage(storage) {
|
||||
return {
|
||||
read: async (k) => {
|
||||
const v = await storage.read(k);
|
||||
return isEnhance(v) ? v : { __d: v };
|
||||
},
|
||||
write: (k, v) => storage.write(k, v),
|
||||
delete: (k) => storage.delete(k),
|
||||
};
|
||||
}
|
||||
function timeoutStorage(storage, millisecondsToLive) {
|
||||
const ttlStorage = {
|
||||
read: async (k) => {
|
||||
const value = await storage.read(k);
|
||||
if (value === undefined)
|
||||
return undefined;
|
||||
if (value.e === undefined) {
|
||||
await ttlStorage.write(k, value);
|
||||
return value;
|
||||
}
|
||||
if (value.e < Date.now()) {
|
||||
await ttlStorage.delete(k);
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
write: async (k, v) => {
|
||||
v.e = addExpiryDate(v, millisecondsToLive).expires;
|
||||
await storage.write(k, v);
|
||||
},
|
||||
delete: (k) => storage.delete(k),
|
||||
};
|
||||
return ttlStorage;
|
||||
}
|
||||
function migrationStorage(storage, migrations) {
|
||||
const versions = Object.keys(migrations)
|
||||
.map((v) => parseInt(v))
|
||||
.sort((a, b) => a - b);
|
||||
const count = versions.length;
|
||||
if (count === 0)
|
||||
throw new Error("No migrations given!");
|
||||
const earliest = versions[0];
|
||||
const last = count - 1;
|
||||
const latest = versions[last];
|
||||
const index = new Map();
|
||||
versions.forEach((v, i) => index.set(v, i)); // inverse array lookup
|
||||
function nextAfter(current) {
|
||||
// TODO: use `findLastIndex` with Node 18
|
||||
let i = last;
|
||||
while (current <= versions[i])
|
||||
i--;
|
||||
return i;
|
||||
// return versions.findLastIndex((v) => v < current)
|
||||
}
|
||||
return {
|
||||
read: async (k) => {
|
||||
var _a;
|
||||
const val = await storage.read(k);
|
||||
if (val === undefined)
|
||||
return val;
|
||||
let { __d: value, v: current = earliest - 1 } = val;
|
||||
let i = 1 + ((_a = index.get(current)) !== null && _a !== void 0 ? _a : nextAfter(current));
|
||||
for (; i < count; i++)
|
||||
value = migrations[versions[i]](value);
|
||||
return { ...val, v: latest, __d: value };
|
||||
},
|
||||
write: (k, v) => storage.write(k, { v: latest, ...v }),
|
||||
delete: (k) => storage.delete(k),
|
||||
};
|
||||
}
|
||||
function wrapStorage(storage) {
|
||||
return {
|
||||
read: (k) => Promise.resolve(storage.read(k)).then((v) => v === null || v === void 0 ? void 0 : v.__d),
|
||||
write: (k, v) => storage.write(k, { __d: v }),
|
||||
delete: (k) => storage.delete(k),
|
||||
};
|
||||
}
|
||||
// === Memory storage adapter
|
||||
/**
|
||||
* The memory session storage is a built-in storage adapter that saves your
|
||||
* session data in RAM using a regular JavaScript `Map` object. If you use this
|
||||
* storage adapter, all sessions will be lost when your process terminates or
|
||||
* restarts. Hence, you should only use it for short-lived data that is not
|
||||
* important to persist.
|
||||
*
|
||||
* This class is used as default if you do not provide a storage adapter, e.g.
|
||||
* to your database.
|
||||
*
|
||||
* This storage adapter features expiring sessions. When instantiating this class
|
||||
* yourself, you can pass a time to live in milliseconds that will be used for
|
||||
* each session object. If a session for a user expired, the session data will
|
||||
* be discarded on its first read, and a fresh session object as returned by the
|
||||
* `initial` option (or undefined) will be put into place.
|
||||
*/
|
||||
class MemorySessionStorage {
|
||||
/**
|
||||
* Constructs a new memory session storage with the given time to live. Note
|
||||
* that this storage adapter will not store your data permanently.
|
||||
*
|
||||
* @param timeToLive TTL in milliseconds, default is `Infinity`
|
||||
*/
|
||||
constructor(timeToLive) {
|
||||
this.timeToLive = timeToLive;
|
||||
/**
|
||||
* Internally used `Map` instance that stores the session data
|
||||
*/
|
||||
this.storage = new Map();
|
||||
}
|
||||
read(key) {
|
||||
const value = this.storage.get(key);
|
||||
if (value === undefined)
|
||||
return undefined;
|
||||
if (value.expires !== undefined && value.expires < Date.now()) {
|
||||
this.delete(key);
|
||||
return undefined;
|
||||
}
|
||||
return value.session;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link readAllValues} instead
|
||||
*/
|
||||
readAll() {
|
||||
return this.readAllValues();
|
||||
}
|
||||
readAllKeys() {
|
||||
return Array.from(this.storage.keys());
|
||||
}
|
||||
readAllValues() {
|
||||
return Array
|
||||
.from(this.storage.keys())
|
||||
.map((key) => this.read(key))
|
||||
.filter((value) => value !== undefined);
|
||||
}
|
||||
readAllEntries() {
|
||||
return Array.from(this.storage.keys())
|
||||
.map((key) => [key, this.read(key)])
|
||||
.filter((pair) => pair[1] !== undefined);
|
||||
}
|
||||
has(key) {
|
||||
return this.storage.has(key);
|
||||
}
|
||||
write(key, value) {
|
||||
this.storage.set(key, addExpiryDate(value, this.timeToLive));
|
||||
}
|
||||
delete(key) {
|
||||
this.storage.delete(key);
|
||||
}
|
||||
}
|
||||
exports.MemorySessionStorage = MemorySessionStorage;
|
||||
function addExpiryDate(value, ttl) {
|
||||
if (ttl !== undefined && ttl < Infinity) {
|
||||
const now = Date.now();
|
||||
return { session: value, expires: now + ttl };
|
||||
}
|
||||
else {
|
||||
return { session: value };
|
||||
}
|
||||
}
|
32
node_modules/grammy/out/convenience/webhook.d.ts
generated
vendored
Normal file
32
node_modules/grammy/out/convenience/webhook.d.ts
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
import { type Bot } from "../bot.js";
|
||||
import { type Context } from "../context.js";
|
||||
import { type FrameworkAdapter, type SupportedFrameworks } from "./frameworks.js";
|
||||
export interface WebhookOptions {
|
||||
/** An optional strategy to handle timeouts (default: 'throw') */
|
||||
onTimeout?: "throw" | "return" | ((...args: any[]) => unknown);
|
||||
/** An optional number of timeout milliseconds (default: 10_000) */
|
||||
timeoutMilliseconds?: number;
|
||||
/** An optional string to compare to X-Telegram-Bot-Api-Secret-Token */
|
||||
secretToken?: string;
|
||||
}
|
||||
/**
|
||||
* Creates a callback function that you can pass to a web framework (such as
|
||||
* express) if you want to run your bot via webhooks. Use it like this:
|
||||
* ```ts
|
||||
* const app = express() // or whatever you're using
|
||||
* const bot = new Bot('<token>')
|
||||
*
|
||||
* app.use(webhookCallback(bot, 'express'))
|
||||
* ```
|
||||
*
|
||||
* Confer the grammY
|
||||
* [documentation](https://grammy.dev/guide/deployment-types.html) to read more
|
||||
* about how to run your bot with webhooks.
|
||||
*
|
||||
* @param bot The bot for which to create a callback
|
||||
* @param adapter An optional string identifying the framework (default: 'express')
|
||||
* @param onTimeout An optional strategy to handle timeouts (default: 'throw')
|
||||
* @param timeoutMilliseconds An optional number of timeout milliseconds (default: 10_000)
|
||||
*/
|
||||
export declare function webhookCallback<C extends Context = Context>(bot: Bot<C>, adapter?: SupportedFrameworks | FrameworkAdapter, onTimeout?: WebhookOptions["onTimeout"], timeoutMilliseconds?: WebhookOptions["timeoutMilliseconds"], secretToken?: WebhookOptions["secretToken"]): (...args: any[]) => any;
|
||||
export declare function webhookCallback<C extends Context = Context>(bot: Bot<C>, adapter?: SupportedFrameworks | FrameworkAdapter, webhookOptions?: WebhookOptions): (...args: any[]) => any;
|
72
node_modules/grammy/out/convenience/webhook.js
generated
vendored
Normal file
72
node_modules/grammy/out/convenience/webhook.js
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.webhookCallback = void 0;
|
||||
const platform_node_js_1 = require("../platform.node.js");
|
||||
const frameworks_js_1 = require("./frameworks.js");
|
||||
const debugErr = (0, platform_node_js_1.debug)("grammy:error");
|
||||
const callbackAdapter = (update, callback, header, unauthorized = () => callback('"unauthorized"')) => ({
|
||||
update: Promise.resolve(update),
|
||||
respond: callback,
|
||||
header,
|
||||
unauthorized,
|
||||
});
|
||||
const adapters = { ...frameworks_js_1.adapters, callback: callbackAdapter };
|
||||
function webhookCallback(bot, adapter = platform_node_js_1.defaultAdapter, onTimeout = "throw", timeoutMilliseconds = 10000, secretToken) {
|
||||
const { onTimeout: timeout = "throw", timeoutMilliseconds: ms = 10000, secretToken: token, } = typeof onTimeout === "object"
|
||||
? onTimeout
|
||||
: { onTimeout, timeoutMilliseconds, secretToken };
|
||||
let initialized = false;
|
||||
const server = typeof adapter === "string"
|
||||
? adapters[adapter]
|
||||
: adapter;
|
||||
return async (...args) => {
|
||||
const { update, respond, unauthorized, end, handlerReturn, header } = server(...args);
|
||||
if (!initialized) {
|
||||
// Will dedupe concurrently incoming calls from several updates
|
||||
await bot.init();
|
||||
initialized = true;
|
||||
}
|
||||
if (header !== token) {
|
||||
await unauthorized();
|
||||
// TODO: investigate deno bug that happens when this console logging is removed
|
||||
console.log(handlerReturn);
|
||||
return handlerReturn;
|
||||
}
|
||||
let usedWebhookReply = false;
|
||||
const webhookReplyEnvelope = {
|
||||
async send(json) {
|
||||
usedWebhookReply = true;
|
||||
await respond(json);
|
||||
},
|
||||
};
|
||||
await timeoutIfNecessary(bot.handleUpdate(await update, webhookReplyEnvelope), typeof timeout === "function" ? () => timeout(...args) : timeout, ms);
|
||||
if (!usedWebhookReply)
|
||||
end === null || end === void 0 ? void 0 : end();
|
||||
return handlerReturn;
|
||||
};
|
||||
}
|
||||
exports.webhookCallback = webhookCallback;
|
||||
function timeoutIfNecessary(task, onTimeout, timeout) {
|
||||
if (timeout === Infinity)
|
||||
return task;
|
||||
return new Promise((resolve, reject) => {
|
||||
const handle = setTimeout(() => {
|
||||
if (onTimeout === "throw") {
|
||||
reject(new Error(`Request timed out after ${timeout} ms`));
|
||||
}
|
||||
else {
|
||||
if (typeof onTimeout === "function")
|
||||
onTimeout();
|
||||
resolve();
|
||||
}
|
||||
const now = Date.now();
|
||||
task.finally(() => {
|
||||
const diff = Date.now() - now;
|
||||
debugErr(`Request completed ${diff} ms after timeout!`);
|
||||
});
|
||||
}, timeout);
|
||||
task.then(resolve)
|
||||
.catch(reject)
|
||||
.finally(() => clearTimeout(handle));
|
||||
});
|
||||
}
|
1377
node_modules/grammy/out/core/api.d.ts
generated
vendored
Normal file
1377
node_modules/grammy/out/core/api.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1596
node_modules/grammy/out/core/api.js
generated
vendored
Normal file
1596
node_modules/grammy/out/core/api.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
163
node_modules/grammy/out/core/client.d.ts
generated
vendored
Normal file
163
node_modules/grammy/out/core/client.d.ts
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
/// <reference types="node-fetch" />
|
||||
import { type ApiMethods as Telegram, type ApiResponse, type Opts } from "../types.js";
|
||||
export type Methods<R extends RawApi> = string & keyof R;
|
||||
/**
|
||||
* Represents the raw Telegram Bot API with all methods specified 1:1 as
|
||||
* documented on the website (https://core.telegram.org/bots/api).
|
||||
*
|
||||
* Every method takes an optional `AbortSignal` object that allows to cancel the
|
||||
* API call if desired.
|
||||
*/
|
||||
export type RawApi = {
|
||||
[M in keyof Telegram]: Parameters<Telegram[M]>[0] extends undefined ? (signal?: AbortSignal) => Promise<ReturnType<Telegram[M]>> : (args: Opts<M>, signal?: AbortSignal) => Promise<ReturnType<Telegram[M]>>;
|
||||
};
|
||||
export type Payload<M extends Methods<R>, R extends RawApi> = M extends unknown ? R[M] extends (signal?: AbortSignal) => unknown ? {} : R[M] extends (args: any, signal?: AbortSignal) => unknown ? Parameters<R[M]>[0] : never : never;
|
||||
/**
|
||||
* Small utility interface that abstracts from webhook reply calls of different
|
||||
* web frameworks.
|
||||
*/
|
||||
export interface WebhookReplyEnvelope {
|
||||
send?: (payload: string) => void | Promise<void>;
|
||||
}
|
||||
/**
|
||||
* Type of a function that can perform an API call. Used for Transformers.
|
||||
*/
|
||||
export type ApiCallFn<R extends RawApi = RawApi> = <M extends Methods<R>>(method: M, payload: Payload<M, R>, signal?: AbortSignal) => Promise<ApiResponse<ApiCallResult<M, R>>>;
|
||||
type ApiCallResult<M extends Methods<R>, R extends RawApi> = R[M] extends (...args: unknown[]) => unknown ? Awaited<ReturnType<R[M]>> : never;
|
||||
/**
|
||||
* API call transformers are functions that can access and modify the method and
|
||||
* payload of an API call on the fly. This can be useful if you want to
|
||||
* implement rate limiting or other things against the Telegram Bot API.
|
||||
*
|
||||
* Confer the grammY
|
||||
* [documentation](https://grammy.dev/advanced/transformers.html) to read more
|
||||
* about how to use transformers.
|
||||
*/
|
||||
export type Transformer<R extends RawApi = RawApi> = <M extends Methods<R>>(prev: ApiCallFn<R>, method: M, payload: Payload<M, R>, signal?: AbortSignal) => Promise<ApiResponse<ApiCallResult<M, R>>>;
|
||||
export type TransformerConsumer<R extends RawApi = RawApi> = TransformableApi<R>["use"];
|
||||
/**
|
||||
* A transformable API enhances the `RawApi` type by transformers.
|
||||
*/
|
||||
export interface TransformableApi<R extends RawApi = RawApi> {
|
||||
/**
|
||||
* Access to the raw API that the transformers will be installed on.
|
||||
*/
|
||||
raw: R;
|
||||
/**
|
||||
* Can be used to register any number of transformers on the API.
|
||||
*/
|
||||
use: (...transformers: Transformer<R>[]) => this;
|
||||
/**
|
||||
* Returns a readonly list or the currently installed transformers. The list
|
||||
* is sorted by time of installation where index 0 represents the
|
||||
* transformer that was installed first.
|
||||
*/
|
||||
installedTransformers: Transformer<R>[];
|
||||
}
|
||||
/**
|
||||
* Options to pass to the API client that eventually connects to the Telegram
|
||||
* Bot API server and makes the HTTP requests.
|
||||
*/
|
||||
export interface ApiClientOptions {
|
||||
/**
|
||||
* Root URL of the Telegram Bot API server. Default:
|
||||
* https://api.telegram.org
|
||||
*/
|
||||
apiRoot?: string;
|
||||
/**
|
||||
* URL builder function for API calls. Can be used to modify which API
|
||||
* server should be called.
|
||||
*
|
||||
* @param root The URL that was passed in `apiRoot`, or its default value
|
||||
* @param token The bot's token that was passed when creating the bot
|
||||
* @param method The API method to be called, e.g. `getMe`
|
||||
* @returns The URL that will be fetched during the API call
|
||||
*/
|
||||
buildUrl?: (root: string, token: string, method: string) => string | URL;
|
||||
/**
|
||||
* Maximum number of seconds that a request to the Bot API server may take.
|
||||
* If a request has not completed before this time has elapsed, grammY
|
||||
* aborts the request and errors. Without such a timeout, networking issues
|
||||
* may cause your bot to leave open a connection indefinitely, which may
|
||||
* effectively make your bot freeze.
|
||||
*
|
||||
* You probably do not have to care about this option. In rare cases, you
|
||||
* may want to adjust it if you are transferring large files via slow
|
||||
* connections to your own Bot API server.
|
||||
*
|
||||
* The default number of seconds is `500`, which corresponds to 8 minutes
|
||||
* and 20 seconds. Note that this is also the value that is hard-coded in
|
||||
* the official Bot API server, so you cannot perform any successful
|
||||
* requests that exceed this time frame (even if you would allow it in
|
||||
* grammY). Setting this option to higher than the default only makes sense
|
||||
* with a custom Bot API server.
|
||||
*/
|
||||
timeoutSeconds?: number;
|
||||
/**
|
||||
* If the bot is running on webhooks, as soon as the bot receives an update
|
||||
* from Telegram, it is possible to make up to one API call in the response
|
||||
* to the webhook request. As a benefit, this saves your bot from making up
|
||||
* to one HTTP request per update. However, there are a number of drawbacks
|
||||
* to using this:
|
||||
* 1) You will not be able to handle potential errors of the respective API
|
||||
* call. This includes rate limiting errors, so sent messages can be
|
||||
* swallowed by the Bot API server and there is no way to detect if a
|
||||
* message was actually sent or not.
|
||||
* 2) More importantly, you also won't have access to the response object,
|
||||
* so e.g. calling `sendMessage` will not give you access to the message
|
||||
* you sent.
|
||||
* 3) Furthermore, it is not possible to cancel the request. The
|
||||
* `AbortSignal` will be disregarded.
|
||||
* 4) Note also that the types in grammY do not reflect the consequences of
|
||||
* a performed webhook callback! For instance, they indicate that you
|
||||
* always receive a response object, so it is your own responsibility to
|
||||
* make sure you're not screwing up while using this minor performance
|
||||
* optimization.
|
||||
*
|
||||
* With this warning out of the way, here is what you can do with the
|
||||
* `canUseWebhookReply` option: it can be used to pass a function that
|
||||
* determines whether to use webhook reply for the given method. It will
|
||||
* only be invoked if the payload can be sent as JSON. It will not be
|
||||
* invoked again for a given update after it returned `true`, indicating
|
||||
* that the API call should be performed as a webhook send. In other words,
|
||||
* subsequent API calls (during the same update) will always perform their
|
||||
* own HTTP requests.
|
||||
*
|
||||
* @param method The method to call
|
||||
*/
|
||||
canUseWebhookReply?: (method: string) => boolean;
|
||||
/**
|
||||
* Base configuration for `fetch` calls. Specify any additional parameters
|
||||
* to use when fetching a method of the Telegram Bot API. Default: `{
|
||||
* compress: true }` (Node), `{}` (Deno)
|
||||
*/
|
||||
baseFetchConfig?: Omit<NonNullable<Parameters<typeof fetch>[1]>, "method" | "headers" | "body">;
|
||||
/**
|
||||
* When the network connection is unreliable and some API requests fail
|
||||
* because of that, grammY will throw errors that tell you exactly which
|
||||
* requests failed. However, the error messages do not disclose the fetched
|
||||
* URL as it contains your bot's token. Logging it may lead to token leaks.
|
||||
*
|
||||
* If you are sure that no logs are ever posted in Telegram chats, GitHub
|
||||
* issues, or otherwise shared, you can set this option to `true` in order
|
||||
* to obtain more detailed logs that may help you debug your bot. The
|
||||
* default value is `false`, meaning that the bot token is not logged.
|
||||
*/
|
||||
sensitiveLogs?: boolean;
|
||||
}
|
||||
/**
|
||||
* Creates a new transformable API, i.e. an object that lets you perform raw API
|
||||
* calls to the Telegram Bot API server but pass the calls through a stack of
|
||||
* transformers before. This will create a new API client instance under the
|
||||
* hood that will be used to connect to the Telegram servers. You therefore need
|
||||
* to pass the bot token. In addition, you may pass API client options as well
|
||||
* as a webhook reply envelope that allows the client to perform up to one HTTP
|
||||
* request in response to a webhook call if this is desired.
|
||||
*
|
||||
* @param token The bot's token
|
||||
* @param options A number of options to pass to the created API client
|
||||
* @param webhookReplyEnvelope The webhook reply envelope that will be used
|
||||
*/
|
||||
export declare function createRawApi<R extends RawApi>(token: string, options?: ApiClientOptions, webhookReplyEnvelope?: WebhookReplyEnvelope): TransformableApi<R>;
|
||||
import { AbortSignal, fetch } from "./../shim.node.js";
|
||||
export {};
|
180
node_modules/grammy/out/core/client.js
generated
vendored
Normal file
180
node_modules/grammy/out/core/client.js
generated
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createRawApi = void 0;
|
||||
const platform_node_js_1 = require("../platform.node.js");
|
||||
const error_js_1 = require("./error.js");
|
||||
const payload_js_1 = require("./payload.js");
|
||||
const debug = (0, platform_node_js_1.debug)("grammy:core");
|
||||
// Transformer base functions
|
||||
function concatTransformer(prev, trans) {
|
||||
return (method, payload, signal) => trans(prev, method, payload, signal);
|
||||
}
|
||||
class ApiClient {
|
||||
constructor(token, options = {}, webhookReplyEnvelope = {}) {
|
||||
var _a, _b, _c, _d, _e;
|
||||
this.token = token;
|
||||
this.webhookReplyEnvelope = webhookReplyEnvelope;
|
||||
this.hasUsedWebhookReply = false;
|
||||
this.installedTransformers = [];
|
||||
this.call = async (method, p, signal) => {
|
||||
const payload = p !== null && p !== void 0 ? p : {};
|
||||
debug(`Calling ${method}`);
|
||||
// General config
|
||||
const opts = this.options;
|
||||
const formDataRequired = (0, payload_js_1.requiresFormDataUpload)(payload);
|
||||
// Short-circuit on webhook reply
|
||||
if (this.webhookReplyEnvelope.send !== undefined &&
|
||||
!this.hasUsedWebhookReply &&
|
||||
!formDataRequired &&
|
||||
opts.canUseWebhookReply(method)) {
|
||||
this.hasUsedWebhookReply = true;
|
||||
const config = (0, payload_js_1.createJsonPayload)({ ...payload, method });
|
||||
await this.webhookReplyEnvelope.send(config.body);
|
||||
return { ok: true, result: true };
|
||||
}
|
||||
// Handle timeouts and errors in the underlying form-data stream
|
||||
const controller = createAbortControllerFromSignal(signal);
|
||||
const timeout = createTimeout(controller, opts.timeoutSeconds, method);
|
||||
const streamErr = createStreamError(controller);
|
||||
// Build request URL and config
|
||||
const url = opts.buildUrl(opts.apiRoot, this.token, method);
|
||||
const config = formDataRequired
|
||||
? (0, payload_js_1.createFormDataPayload)(payload, (err) => streamErr.catch(err))
|
||||
: (0, payload_js_1.createJsonPayload)(payload);
|
||||
const sig = controller.signal;
|
||||
const options = { ...opts.baseFetchConfig, signal: sig, ...config };
|
||||
// Perform fetch call, and handle networking errors
|
||||
const successPromise = (0, shim_node_js_1.fetch)(url instanceof URL ? url.href : url, options).catch((0, error_js_1.toHttpError)(method, opts.sensitiveLogs));
|
||||
// Those are the three possible outcomes of the fetch call:
|
||||
const operations = [successPromise, streamErr.promise, timeout.promise];
|
||||
// Wait for result
|
||||
try {
|
||||
const res = await Promise.race(operations);
|
||||
return await res.json();
|
||||
}
|
||||
finally {
|
||||
if (timeout.handle !== undefined)
|
||||
clearTimeout(timeout.handle);
|
||||
}
|
||||
};
|
||||
const apiRoot = (_a = options.apiRoot) !== null && _a !== void 0 ? _a : "https://api.telegram.org";
|
||||
this.options = {
|
||||
apiRoot,
|
||||
buildUrl: (_b = options.buildUrl) !== null && _b !== void 0 ? _b : ((root, token, method) => `${root}/bot${token}/${method}`),
|
||||
timeoutSeconds: (_c = options.timeoutSeconds) !== null && _c !== void 0 ? _c : 500,
|
||||
baseFetchConfig: {
|
||||
...(0, platform_node_js_1.baseFetchConfig)(apiRoot),
|
||||
...options.baseFetchConfig,
|
||||
},
|
||||
canUseWebhookReply: (_d = options.canUseWebhookReply) !== null && _d !== void 0 ? _d : (() => false),
|
||||
sensitiveLogs: (_e = options.sensitiveLogs) !== null && _e !== void 0 ? _e : false,
|
||||
};
|
||||
if (this.options.apiRoot.endsWith("/")) {
|
||||
throw new Error(`Remove the trailing '/' from the 'apiRoot' option (use '${this.options.apiRoot.substring(0, this.options.apiRoot.length - 1)}' instead of '${this.options.apiRoot}')`);
|
||||
}
|
||||
}
|
||||
use(...transformers) {
|
||||
this.call = transformers.reduce(concatTransformer, this.call);
|
||||
this.installedTransformers.push(...transformers);
|
||||
return this;
|
||||
}
|
||||
async callApi(method, payload, signal) {
|
||||
const data = await this.call(method, payload, signal);
|
||||
if (data.ok)
|
||||
return data.result;
|
||||
else
|
||||
throw (0, error_js_1.toGrammyError)(data, method, payload);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a new transformable API, i.e. an object that lets you perform raw API
|
||||
* calls to the Telegram Bot API server but pass the calls through a stack of
|
||||
* transformers before. This will create a new API client instance under the
|
||||
* hood that will be used to connect to the Telegram servers. You therefore need
|
||||
* to pass the bot token. In addition, you may pass API client options as well
|
||||
* as a webhook reply envelope that allows the client to perform up to one HTTP
|
||||
* request in response to a webhook call if this is desired.
|
||||
*
|
||||
* @param token The bot's token
|
||||
* @param options A number of options to pass to the created API client
|
||||
* @param webhookReplyEnvelope The webhook reply envelope that will be used
|
||||
*/
|
||||
function createRawApi(token, options, webhookReplyEnvelope) {
|
||||
const client = new ApiClient(token, options, webhookReplyEnvelope);
|
||||
const proxyHandler = {
|
||||
get(_, m) {
|
||||
return m === "toJSON"
|
||||
? "__internal"
|
||||
: client.callApi.bind(client, m);
|
||||
},
|
||||
...proxyMethods,
|
||||
};
|
||||
const raw = new Proxy({}, proxyHandler);
|
||||
const installedTransformers = client.installedTransformers;
|
||||
const api = {
|
||||
raw,
|
||||
installedTransformers,
|
||||
use: (...t) => {
|
||||
client.use(...t);
|
||||
return api;
|
||||
},
|
||||
};
|
||||
return api;
|
||||
}
|
||||
exports.createRawApi = createRawApi;
|
||||
const proxyMethods = {
|
||||
set() {
|
||||
return false;
|
||||
},
|
||||
defineProperty() {
|
||||
return false;
|
||||
},
|
||||
deleteProperty() {
|
||||
return false;
|
||||
},
|
||||
ownKeys() {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
/** Creates a timeout error which aborts a given controller */
|
||||
function createTimeout(controller, seconds, method) {
|
||||
let handle = undefined;
|
||||
const promise = new Promise((_, reject) => {
|
||||
handle = setTimeout(() => {
|
||||
const msg = `Request to '${method}' timed out after ${seconds} seconds`;
|
||||
reject(new Error(msg));
|
||||
controller.abort();
|
||||
}, 1000 * seconds);
|
||||
});
|
||||
return { promise, handle };
|
||||
}
|
||||
/** Creates a stream error which abort a given controller */
|
||||
function createStreamError(abortController) {
|
||||
let onError = (err) => {
|
||||
// Re-throw by default, but will be overwritten immediately
|
||||
throw err;
|
||||
};
|
||||
const promise = new Promise((_, reject) => {
|
||||
onError = (err) => {
|
||||
reject(err);
|
||||
abortController.abort();
|
||||
};
|
||||
});
|
||||
return { promise, catch: onError };
|
||||
}
|
||||
function createAbortControllerFromSignal(signal) {
|
||||
const abortController = new shim_node_js_1.AbortController();
|
||||
if (signal === undefined)
|
||||
return abortController;
|
||||
const sig = signal;
|
||||
function abort() {
|
||||
abortController.abort();
|
||||
sig.removeEventListener("abort", abort);
|
||||
}
|
||||
if (sig.aborted)
|
||||
abort();
|
||||
else
|
||||
sig.addEventListener("abort", abort);
|
||||
return { abort, signal: abortController.signal };
|
||||
}
|
||||
const shim_node_js_1 = require("./../shim.node.js");
|
53
node_modules/grammy/out/core/error.d.ts
generated
vendored
Normal file
53
node_modules/grammy/out/core/error.d.ts
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
import { type ApiError, type ResponseParameters } from "../types.js";
|
||||
/**
|
||||
* This class represents errors that are thrown by grammY because the Telegram
|
||||
* Bot API responded with an error.
|
||||
*
|
||||
* Instances of this class hold the information that the Telegram backend
|
||||
* returned.
|
||||
*
|
||||
* If this error is thrown, grammY could successfully communicate with the
|
||||
* Telegram Bot API servers, however, an error code was returned for the
|
||||
* respective method call.
|
||||
*/
|
||||
export declare class GrammyError extends Error implements ApiError {
|
||||
/** The called method name which caused this error to be thrown. */
|
||||
readonly method: string;
|
||||
/** The payload that was passed when calling the method. */
|
||||
readonly payload: Record<string, unknown>;
|
||||
/** Flag that this request was unsuccessful. Always `false`. */
|
||||
readonly ok: false;
|
||||
/** An integer holding Telegram's error code. Subject to change. */
|
||||
readonly error_code: number;
|
||||
/** A human-readable description of the error. */
|
||||
readonly description: string;
|
||||
/** Further parameters that may help to automatically handle the error. */
|
||||
readonly parameters: ResponseParameters;
|
||||
constructor(message: string, err: ApiError,
|
||||
/** The called method name which caused this error to be thrown. */
|
||||
method: string,
|
||||
/** The payload that was passed when calling the method. */
|
||||
payload: Record<string, unknown>);
|
||||
}
|
||||
export declare function toGrammyError(err: ApiError, method: string, payload: Record<string, unknown>): GrammyError;
|
||||
/**
|
||||
* This class represents errors that are thrown by grammY because an HTTP call
|
||||
* to the Telegram Bot API failed.
|
||||
*
|
||||
* Instances of this class hold the error object that was created because the
|
||||
* fetch call failed. It can be inspected to determine why exactly the network
|
||||
* request failed.
|
||||
*
|
||||
* If an [API transformer
|
||||
* function](https://grammy.dev/advanced/transformers.html) throws an error,
|
||||
* grammY will regard this as if the network request failed. The contained error
|
||||
* will then be the error that was thrown by the transformer function.
|
||||
*/
|
||||
export declare class HttpError extends Error {
|
||||
/** The thrown error object. */
|
||||
readonly error: unknown;
|
||||
constructor(message: string,
|
||||
/** The thrown error object. */
|
||||
error: unknown);
|
||||
}
|
||||
export declare function toHttpError(method: string, sensitiveLogs: boolean): (err: unknown) => never;
|
77
node_modules/grammy/out/core/error.js
generated
vendored
Normal file
77
node_modules/grammy/out/core/error.js
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.toHttpError = exports.HttpError = exports.toGrammyError = exports.GrammyError = void 0;
|
||||
/**
|
||||
* This class represents errors that are thrown by grammY because the Telegram
|
||||
* Bot API responded with an error.
|
||||
*
|
||||
* Instances of this class hold the information that the Telegram backend
|
||||
* returned.
|
||||
*
|
||||
* If this error is thrown, grammY could successfully communicate with the
|
||||
* Telegram Bot API servers, however, an error code was returned for the
|
||||
* respective method call.
|
||||
*/
|
||||
class GrammyError extends Error {
|
||||
constructor(message, err,
|
||||
/** The called method name which caused this error to be thrown. */
|
||||
method,
|
||||
/** The payload that was passed when calling the method. */
|
||||
payload) {
|
||||
var _a;
|
||||
super(`${message} (${err.error_code}: ${err.description})`);
|
||||
this.method = method;
|
||||
this.payload = payload;
|
||||
/** Flag that this request was unsuccessful. Always `false`. */
|
||||
this.ok = false;
|
||||
this.name = "GrammyError";
|
||||
this.error_code = err.error_code;
|
||||
this.description = err.description;
|
||||
this.parameters = (_a = err.parameters) !== null && _a !== void 0 ? _a : {};
|
||||
}
|
||||
}
|
||||
exports.GrammyError = GrammyError;
|
||||
function toGrammyError(err, method, payload) {
|
||||
return new GrammyError(`Call to '${method}' failed!`, err, method, payload);
|
||||
}
|
||||
exports.toGrammyError = toGrammyError;
|
||||
/**
|
||||
* This class represents errors that are thrown by grammY because an HTTP call
|
||||
* to the Telegram Bot API failed.
|
||||
*
|
||||
* Instances of this class hold the error object that was created because the
|
||||
* fetch call failed. It can be inspected to determine why exactly the network
|
||||
* request failed.
|
||||
*
|
||||
* If an [API transformer
|
||||
* function](https://grammy.dev/advanced/transformers.html) throws an error,
|
||||
* grammY will regard this as if the network request failed. The contained error
|
||||
* will then be the error that was thrown by the transformer function.
|
||||
*/
|
||||
class HttpError extends Error {
|
||||
constructor(message,
|
||||
/** The thrown error object. */
|
||||
error) {
|
||||
super(message);
|
||||
this.error = error;
|
||||
this.name = "HttpError";
|
||||
}
|
||||
}
|
||||
exports.HttpError = HttpError;
|
||||
function isTelegramError(err) {
|
||||
return (typeof err === "object" &&
|
||||
err !== null &&
|
||||
"status" in err &&
|
||||
"statusText" in err);
|
||||
}
|
||||
function toHttpError(method, sensitiveLogs) {
|
||||
return (err) => {
|
||||
let msg = `Network request for '${method}' failed!`;
|
||||
if (isTelegramError(err))
|
||||
msg += ` (${err.status}: ${err.statusText})`;
|
||||
if (sensitiveLogs && err instanceof Error)
|
||||
msg += ` ${err.message}`;
|
||||
throw new HttpError(msg, err);
|
||||
};
|
||||
}
|
||||
exports.toHttpError = toHttpError;
|
40
node_modules/grammy/out/core/payload.d.ts
generated
vendored
Normal file
40
node_modules/grammy/out/core/payload.d.ts
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
/// <reference types="node" />
|
||||
/**
|
||||
* Determines for a given payload if it may be sent as JSON, or if it has to be
|
||||
* uploaded via multipart/form-data. Returns `true` in the latter case and
|
||||
* `false` in the former.
|
||||
*
|
||||
* @param payload The payload to analyze
|
||||
*/
|
||||
export declare function requiresFormDataUpload(payload: unknown): boolean;
|
||||
/**
|
||||
* Turns a payload into an options object that can be passed to a `fetch` call
|
||||
* by setting the necessary headers and method. May only be called for payloads
|
||||
* `P` that let `requiresFormDataUpload(P)` return `false`.
|
||||
*
|
||||
* @param payload The payload to wrap
|
||||
*/
|
||||
export declare function createJsonPayload(payload: Record<string, unknown>): {
|
||||
method: string;
|
||||
headers: {
|
||||
"content-type": string;
|
||||
connection: string;
|
||||
};
|
||||
body: string;
|
||||
};
|
||||
/**
|
||||
* Turns a payload into an options object that can be passed to a `fetch` call
|
||||
* by setting the necessary headers and method. Note that this method creates a
|
||||
* multipart/form-data stream under the hood. If possible, a JSON payload should
|
||||
* be created instead for performance reasons.
|
||||
*
|
||||
* @param payload The payload to wrap
|
||||
*/
|
||||
export declare function createFormDataPayload(payload: Record<string, unknown>, onError: (err: unknown) => void): {
|
||||
method: string;
|
||||
headers: {
|
||||
"content-type": string;
|
||||
connection: string;
|
||||
};
|
||||
body: import("stream").Readable;
|
||||
};
|
200
node_modules/grammy/out/core/payload.js
generated
vendored
Normal file
200
node_modules/grammy/out/core/payload.js
generated
vendored
Normal file
@ -0,0 +1,200 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createFormDataPayload = exports.createJsonPayload = exports.requiresFormDataUpload = void 0;
|
||||
const platform_node_js_1 = require("../platform.node.js");
|
||||
const types_js_1 = require("../types.js");
|
||||
// === Payload types (JSON vs. form data)
|
||||
/**
|
||||
* Determines for a given payload if it may be sent as JSON, or if it has to be
|
||||
* uploaded via multipart/form-data. Returns `true` in the latter case and
|
||||
* `false` in the former.
|
||||
*
|
||||
* @param payload The payload to analyze
|
||||
*/
|
||||
function requiresFormDataUpload(payload) {
|
||||
return payload instanceof types_js_1.InputFile || (typeof payload === "object" &&
|
||||
payload !== null &&
|
||||
Object.values(payload).some((v) => Array.isArray(v)
|
||||
? v.some(requiresFormDataUpload)
|
||||
: v instanceof types_js_1.InputFile || requiresFormDataUpload(v)));
|
||||
}
|
||||
exports.requiresFormDataUpload = requiresFormDataUpload;
|
||||
/**
|
||||
* Calls `JSON.stringify` but removes `null` values from objects before
|
||||
* serialization
|
||||
*
|
||||
* @param value value
|
||||
* @returns stringified value
|
||||
*/
|
||||
function str(value) {
|
||||
return JSON.stringify(value, (_, v) => v !== null && v !== void 0 ? v : undefined);
|
||||
}
|
||||
/**
|
||||
* Turns a payload into an options object that can be passed to a `fetch` call
|
||||
* by setting the necessary headers and method. May only be called for payloads
|
||||
* `P` that let `requiresFormDataUpload(P)` return `false`.
|
||||
*
|
||||
* @param payload The payload to wrap
|
||||
*/
|
||||
function createJsonPayload(payload) {
|
||||
return {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
connection: "keep-alive",
|
||||
},
|
||||
body: str(payload),
|
||||
};
|
||||
}
|
||||
exports.createJsonPayload = createJsonPayload;
|
||||
async function* protectItr(itr, onError) {
|
||||
try {
|
||||
yield* itr;
|
||||
}
|
||||
catch (err) {
|
||||
onError(err);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Turns a payload into an options object that can be passed to a `fetch` call
|
||||
* by setting the necessary headers and method. Note that this method creates a
|
||||
* multipart/form-data stream under the hood. If possible, a JSON payload should
|
||||
* be created instead for performance reasons.
|
||||
*
|
||||
* @param payload The payload to wrap
|
||||
*/
|
||||
function createFormDataPayload(payload, onError) {
|
||||
const boundary = createBoundary();
|
||||
const itr = payloadToMultipartItr(payload, boundary);
|
||||
const safeItr = protectItr(itr, onError);
|
||||
const stream = (0, platform_node_js_1.itrToStream)(safeItr);
|
||||
return {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": `multipart/form-data; boundary=${boundary}`,
|
||||
connection: "keep-alive",
|
||||
},
|
||||
body: stream,
|
||||
};
|
||||
}
|
||||
exports.createFormDataPayload = createFormDataPayload;
|
||||
// === Form data creation
|
||||
function createBoundary() {
|
||||
// Taken from Deno std lib
|
||||
return "----------" + randomId(32);
|
||||
}
|
||||
function randomId(length = 16) {
|
||||
return Array.from(Array(length))
|
||||
.map(() => Math.random().toString(36)[2] || 0)
|
||||
.join("");
|
||||
}
|
||||
const enc = new TextEncoder();
|
||||
/**
|
||||
* Takes a payload object and produces a valid multipart/form-data stream. The
|
||||
* stream is an iterator of `Uint8Array` objects. You also need to specify the
|
||||
* boundary string that was used in the Content-Type header of the HTTP request.
|
||||
*
|
||||
* @param payload a payload object
|
||||
* @param boundary the boundary string to use between the parts
|
||||
*/
|
||||
async function* payloadToMultipartItr(payload, boundary) {
|
||||
const files = extractFiles(payload);
|
||||
// Start multipart/form-data protocol
|
||||
yield enc.encode(`--${boundary}\r\n`);
|
||||
// Send all payload fields
|
||||
const separator = enc.encode(`\r\n--${boundary}\r\n`);
|
||||
let first = true;
|
||||
for (const [key, value] of Object.entries(payload)) {
|
||||
if (value == null)
|
||||
continue;
|
||||
if (!first)
|
||||
yield separator;
|
||||
yield valuePart(key, typeof value === "object" ? str(value) : value);
|
||||
first = false;
|
||||
}
|
||||
// Send all files
|
||||
for (const { id, origin, file } of files) {
|
||||
if (!first)
|
||||
yield separator;
|
||||
yield* filePart(id, origin, file);
|
||||
first = false;
|
||||
}
|
||||
// End multipart/form-data protocol
|
||||
yield enc.encode(`\r\n--${boundary}--\r\n`);
|
||||
}
|
||||
/**
|
||||
* Replaces all instances of `InputFile` in a given payload by attach://
|
||||
* strings. This alters the passed object. After calling this method, the
|
||||
* payload object can be stringified.
|
||||
*
|
||||
* Returns a list of `InputFile` instances along with the random identifiers
|
||||
* that were used in the corresponding attach:// strings, as well as the origin
|
||||
* keys of the original payload object.
|
||||
*
|
||||
* @param value a payload object, or a part of it
|
||||
* @param key the origin key of the payload object, if a part of it is passed
|
||||
* @returns the cleaned payload object
|
||||
*/
|
||||
function extractFiles(value) {
|
||||
if (typeof value !== "object" || value === null)
|
||||
return [];
|
||||
return Object.entries(value).flatMap(([k, v]) => {
|
||||
if (Array.isArray(v))
|
||||
return v.flatMap((p) => extractFiles(p));
|
||||
else if (v instanceof types_js_1.InputFile) {
|
||||
const id = randomId();
|
||||
// Overwrite `InputFile` instance with attach:// string
|
||||
Object.assign(value, { [k]: `attach://${id}` });
|
||||
const origin = k === "media" &&
|
||||
"type" in value && typeof value.type === "string"
|
||||
? value.type // use `type` for `InputMedia*`
|
||||
: k; // use property key otherwise
|
||||
return { id, origin, file: v };
|
||||
}
|
||||
else
|
||||
return extractFiles(v);
|
||||
});
|
||||
}
|
||||
/** Turns a regular value into a `Uint8Array` */
|
||||
function valuePart(key, value) {
|
||||
return enc.encode(`content-disposition:form-data;name="${key}"\r\n\r\n${value}`);
|
||||
}
|
||||
/** Turns an InputFile into a generator of `Uint8Array`s */
|
||||
async function* filePart(id, origin, input) {
|
||||
const filename = input.filename || `${origin}.${getExt(origin)}`;
|
||||
if (filename.includes("\r") || filename.includes("\n")) {
|
||||
throw new Error(`File paths cannot contain carriage-return (\\r) \
|
||||
or newline (\\n) characters! Filename for property '${origin}' was:
|
||||
"""
|
||||
${filename}
|
||||
"""`);
|
||||
}
|
||||
yield enc.encode(`content-disposition:form-data;name="${id}";filename=${filename}\r\ncontent-type:application/octet-stream\r\n\r\n`);
|
||||
const data = await input.toRaw();
|
||||
if (data instanceof Uint8Array)
|
||||
yield data;
|
||||
else
|
||||
yield* data;
|
||||
}
|
||||
/** Returns the default file extension for an API property name */
|
||||
function getExt(key) {
|
||||
switch (key) {
|
||||
case "certificate":
|
||||
return "pem";
|
||||
case "photo":
|
||||
case "thumbnail":
|
||||
return "jpg";
|
||||
case "voice":
|
||||
return "ogg";
|
||||
case "audio":
|
||||
return "mp3";
|
||||
case "animation":
|
||||
case "video":
|
||||
case "video_note":
|
||||
return "mp4";
|
||||
case "sticker":
|
||||
return "webp";
|
||||
default:
|
||||
return "dat";
|
||||
}
|
||||
}
|
533
node_modules/grammy/out/filter.d.ts
generated
vendored
Normal file
533
node_modules/grammy/out/filter.d.ts
generated
vendored
Normal file
@ -0,0 +1,533 @@
|
||||
import { type AliasProps, type Context } from "./context.js";
|
||||
import { type Update } from "./types.js";
|
||||
type FilterFunction<C extends Context, D extends C> = (ctx: C) => ctx is D;
|
||||
/**
|
||||
* > This is an advanced function of grammY.
|
||||
*
|
||||
* Takes a filter query and turns it into a predicate function that can check in
|
||||
* constant time whether a given context object satisfies the query. The created
|
||||
* predicate can be passed to `bot.filter` and will narrow down the context
|
||||
* accordingly.
|
||||
*
|
||||
* This function is used internally by `bot.on` but exposed for advanced usage
|
||||
* like the following.
|
||||
* ```ts
|
||||
* // Listens for updates except forwards of messages or channel posts
|
||||
* bot.drop(matchFilter(':forward_date'), ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* Check out the
|
||||
* [documentation](https://doc.deno.land/https://deno.land/x/grammy/mod.ts/~/Composer)
|
||||
* of `bot.on` for examples. In addition, the
|
||||
* [website](https://grammy.dev/guide/filter-queries.html) contains more
|
||||
* information about how filter queries work in grammY.
|
||||
*
|
||||
* @param filter A filter query or an array of filter queries
|
||||
*/
|
||||
export declare function matchFilter<C extends Context, Q extends FilterQuery>(filter: Q | Q[]): FilterFunction<C, Filter<C, Q>>;
|
||||
export declare function parse(filter: FilterQuery | FilterQuery[]): string[][];
|
||||
export declare function preprocess(filter: string[]): string[][];
|
||||
declare const UPDATE_KEYS: {
|
||||
readonly message: {
|
||||
readonly new_chat_members: {
|
||||
readonly me: {};
|
||||
readonly is_bot: {};
|
||||
readonly is_premium: {};
|
||||
readonly added_to_attachment_menu: {};
|
||||
};
|
||||
readonly left_chat_member: {
|
||||
readonly me: {};
|
||||
readonly is_bot: {};
|
||||
readonly is_premium: {};
|
||||
readonly added_to_attachment_menu: {};
|
||||
};
|
||||
readonly group_chat_created: {};
|
||||
readonly supergroup_chat_created: {};
|
||||
readonly migrate_to_chat_id: {};
|
||||
readonly migrate_from_chat_id: {};
|
||||
readonly successful_payment: {};
|
||||
readonly user_shared: {};
|
||||
readonly chat_shared: {};
|
||||
readonly connected_website: {};
|
||||
readonly write_access_allowed: {};
|
||||
readonly passport_data: {};
|
||||
readonly forum_topic_created: {};
|
||||
readonly forum_topic_edited: {
|
||||
readonly name: {};
|
||||
readonly icon_custom_emoji_id: {};
|
||||
};
|
||||
readonly forum_topic_closed: {};
|
||||
readonly forum_topic_reopened: {};
|
||||
readonly general_forum_topic_hidden: {};
|
||||
readonly general_forum_topic_unhidden: {};
|
||||
readonly sticker: {
|
||||
readonly is_video: {};
|
||||
readonly is_animated: {};
|
||||
readonly premium_animation: {};
|
||||
};
|
||||
readonly video_note: {};
|
||||
readonly voice: {};
|
||||
readonly contact: {};
|
||||
readonly dice: {};
|
||||
readonly poll: {};
|
||||
readonly venue: {};
|
||||
readonly new_chat_title: {};
|
||||
readonly new_chat_photo: {};
|
||||
readonly delete_chat_photo: {};
|
||||
readonly message_auto_delete_timer_changed: {};
|
||||
readonly pinned_message: {};
|
||||
readonly invoice: {};
|
||||
readonly proximity_alert_triggered: {};
|
||||
readonly video_chat_scheduled: {};
|
||||
readonly video_chat_started: {};
|
||||
readonly video_chat_ended: {};
|
||||
readonly video_chat_participants_invited: {};
|
||||
readonly web_app_data: {};
|
||||
readonly forward_date: {};
|
||||
readonly is_topic_message: {};
|
||||
readonly is_automatic_forward: {};
|
||||
readonly text: {};
|
||||
readonly animation: {};
|
||||
readonly audio: {};
|
||||
readonly document: {};
|
||||
readonly photo: {};
|
||||
readonly video: {};
|
||||
readonly game: {};
|
||||
readonly location: {};
|
||||
readonly entities: {
|
||||
readonly mention: {};
|
||||
readonly hashtag: {};
|
||||
readonly cashtag: {};
|
||||
readonly bot_command: {};
|
||||
readonly url: {};
|
||||
readonly email: {};
|
||||
readonly phone_number: {};
|
||||
readonly bold: {};
|
||||
readonly italic: {};
|
||||
readonly underline: {};
|
||||
readonly strikethrough: {};
|
||||
readonly spoiler: {};
|
||||
readonly code: {};
|
||||
readonly pre: {};
|
||||
readonly text_link: {};
|
||||
readonly text_mention: {};
|
||||
readonly custom_emoji: {};
|
||||
};
|
||||
readonly caption_entities: {
|
||||
readonly mention: {};
|
||||
readonly hashtag: {};
|
||||
readonly cashtag: {};
|
||||
readonly bot_command: {};
|
||||
readonly url: {};
|
||||
readonly email: {};
|
||||
readonly phone_number: {};
|
||||
readonly bold: {};
|
||||
readonly italic: {};
|
||||
readonly underline: {};
|
||||
readonly strikethrough: {};
|
||||
readonly spoiler: {};
|
||||
readonly code: {};
|
||||
readonly pre: {};
|
||||
readonly text_link: {};
|
||||
readonly text_mention: {};
|
||||
readonly custom_emoji: {};
|
||||
};
|
||||
readonly has_media_spoiler: {};
|
||||
readonly caption: {};
|
||||
};
|
||||
readonly edited_message: {
|
||||
readonly new_chat_members: {
|
||||
readonly me: {};
|
||||
readonly is_bot: {};
|
||||
readonly is_premium: {};
|
||||
readonly added_to_attachment_menu: {};
|
||||
};
|
||||
readonly left_chat_member: {
|
||||
readonly me: {};
|
||||
readonly is_bot: {};
|
||||
readonly is_premium: {};
|
||||
readonly added_to_attachment_menu: {};
|
||||
};
|
||||
readonly group_chat_created: {};
|
||||
readonly supergroup_chat_created: {};
|
||||
readonly migrate_to_chat_id: {};
|
||||
readonly migrate_from_chat_id: {};
|
||||
readonly successful_payment: {};
|
||||
readonly user_shared: {};
|
||||
readonly chat_shared: {};
|
||||
readonly connected_website: {};
|
||||
readonly write_access_allowed: {};
|
||||
readonly passport_data: {};
|
||||
readonly forum_topic_created: {};
|
||||
readonly forum_topic_edited: {
|
||||
readonly name: {};
|
||||
readonly icon_custom_emoji_id: {};
|
||||
};
|
||||
readonly forum_topic_closed: {};
|
||||
readonly forum_topic_reopened: {};
|
||||
readonly general_forum_topic_hidden: {};
|
||||
readonly general_forum_topic_unhidden: {};
|
||||
readonly sticker: {
|
||||
readonly is_video: {};
|
||||
readonly is_animated: {};
|
||||
readonly premium_animation: {};
|
||||
};
|
||||
readonly video_note: {};
|
||||
readonly voice: {};
|
||||
readonly contact: {};
|
||||
readonly dice: {};
|
||||
readonly poll: {};
|
||||
readonly venue: {};
|
||||
readonly new_chat_title: {};
|
||||
readonly new_chat_photo: {};
|
||||
readonly delete_chat_photo: {};
|
||||
readonly message_auto_delete_timer_changed: {};
|
||||
readonly pinned_message: {};
|
||||
readonly invoice: {};
|
||||
readonly proximity_alert_triggered: {};
|
||||
readonly video_chat_scheduled: {};
|
||||
readonly video_chat_started: {};
|
||||
readonly video_chat_ended: {};
|
||||
readonly video_chat_participants_invited: {};
|
||||
readonly web_app_data: {};
|
||||
readonly forward_date: {};
|
||||
readonly is_topic_message: {};
|
||||
readonly is_automatic_forward: {};
|
||||
readonly text: {};
|
||||
readonly animation: {};
|
||||
readonly audio: {};
|
||||
readonly document: {};
|
||||
readonly photo: {};
|
||||
readonly video: {};
|
||||
readonly game: {};
|
||||
readonly location: {};
|
||||
readonly entities: {
|
||||
readonly mention: {};
|
||||
readonly hashtag: {};
|
||||
readonly cashtag: {};
|
||||
readonly bot_command: {};
|
||||
readonly url: {};
|
||||
readonly email: {};
|
||||
readonly phone_number: {};
|
||||
readonly bold: {};
|
||||
readonly italic: {};
|
||||
readonly underline: {};
|
||||
readonly strikethrough: {};
|
||||
readonly spoiler: {};
|
||||
readonly code: {};
|
||||
readonly pre: {};
|
||||
readonly text_link: {};
|
||||
readonly text_mention: {};
|
||||
readonly custom_emoji: {};
|
||||
};
|
||||
readonly caption_entities: {
|
||||
readonly mention: {};
|
||||
readonly hashtag: {};
|
||||
readonly cashtag: {};
|
||||
readonly bot_command: {};
|
||||
readonly url: {};
|
||||
readonly email: {};
|
||||
readonly phone_number: {};
|
||||
readonly bold: {};
|
||||
readonly italic: {};
|
||||
readonly underline: {};
|
||||
readonly strikethrough: {};
|
||||
readonly spoiler: {};
|
||||
readonly code: {};
|
||||
readonly pre: {};
|
||||
readonly text_link: {};
|
||||
readonly text_mention: {};
|
||||
readonly custom_emoji: {};
|
||||
};
|
||||
readonly has_media_spoiler: {};
|
||||
readonly caption: {};
|
||||
};
|
||||
readonly channel_post: {
|
||||
readonly channel_chat_created: {};
|
||||
readonly sticker: {
|
||||
readonly is_video: {};
|
||||
readonly is_animated: {};
|
||||
readonly premium_animation: {};
|
||||
};
|
||||
readonly video_note: {};
|
||||
readonly voice: {};
|
||||
readonly contact: {};
|
||||
readonly dice: {};
|
||||
readonly poll: {};
|
||||
readonly venue: {};
|
||||
readonly new_chat_title: {};
|
||||
readonly new_chat_photo: {};
|
||||
readonly delete_chat_photo: {};
|
||||
readonly message_auto_delete_timer_changed: {};
|
||||
readonly pinned_message: {};
|
||||
readonly invoice: {};
|
||||
readonly proximity_alert_triggered: {};
|
||||
readonly video_chat_scheduled: {};
|
||||
readonly video_chat_started: {};
|
||||
readonly video_chat_ended: {};
|
||||
readonly video_chat_participants_invited: {};
|
||||
readonly web_app_data: {};
|
||||
readonly forward_date: {};
|
||||
readonly is_topic_message: {};
|
||||
readonly is_automatic_forward: {};
|
||||
readonly text: {};
|
||||
readonly animation: {};
|
||||
readonly audio: {};
|
||||
readonly document: {};
|
||||
readonly photo: {};
|
||||
readonly video: {};
|
||||
readonly game: {};
|
||||
readonly location: {};
|
||||
readonly entities: {
|
||||
readonly mention: {};
|
||||
readonly hashtag: {};
|
||||
readonly cashtag: {};
|
||||
readonly bot_command: {};
|
||||
readonly url: {};
|
||||
readonly email: {};
|
||||
readonly phone_number: {};
|
||||
readonly bold: {};
|
||||
readonly italic: {};
|
||||
readonly underline: {};
|
||||
readonly strikethrough: {};
|
||||
readonly spoiler: {};
|
||||
readonly code: {};
|
||||
readonly pre: {};
|
||||
readonly text_link: {};
|
||||
readonly text_mention: {};
|
||||
readonly custom_emoji: {};
|
||||
};
|
||||
readonly caption_entities: {
|
||||
readonly mention: {};
|
||||
readonly hashtag: {};
|
||||
readonly cashtag: {};
|
||||
readonly bot_command: {};
|
||||
readonly url: {};
|
||||
readonly email: {};
|
||||
readonly phone_number: {};
|
||||
readonly bold: {};
|
||||
readonly italic: {};
|
||||
readonly underline: {};
|
||||
readonly strikethrough: {};
|
||||
readonly spoiler: {};
|
||||
readonly code: {};
|
||||
readonly pre: {};
|
||||
readonly text_link: {};
|
||||
readonly text_mention: {};
|
||||
readonly custom_emoji: {};
|
||||
};
|
||||
readonly has_media_spoiler: {};
|
||||
readonly caption: {};
|
||||
};
|
||||
readonly edited_channel_post: {
|
||||
readonly channel_chat_created: {};
|
||||
readonly sticker: {
|
||||
readonly is_video: {};
|
||||
readonly is_animated: {};
|
||||
readonly premium_animation: {};
|
||||
};
|
||||
readonly video_note: {};
|
||||
readonly voice: {};
|
||||
readonly contact: {};
|
||||
readonly dice: {};
|
||||
readonly poll: {};
|
||||
readonly venue: {};
|
||||
readonly new_chat_title: {};
|
||||
readonly new_chat_photo: {};
|
||||
readonly delete_chat_photo: {};
|
||||
readonly message_auto_delete_timer_changed: {};
|
||||
readonly pinned_message: {};
|
||||
readonly invoice: {};
|
||||
readonly proximity_alert_triggered: {};
|
||||
readonly video_chat_scheduled: {};
|
||||
readonly video_chat_started: {};
|
||||
readonly video_chat_ended: {};
|
||||
readonly video_chat_participants_invited: {};
|
||||
readonly web_app_data: {};
|
||||
readonly forward_date: {};
|
||||
readonly is_topic_message: {};
|
||||
readonly is_automatic_forward: {};
|
||||
readonly text: {};
|
||||
readonly animation: {};
|
||||
readonly audio: {};
|
||||
readonly document: {};
|
||||
readonly photo: {};
|
||||
readonly video: {};
|
||||
readonly game: {};
|
||||
readonly location: {};
|
||||
readonly entities: {
|
||||
readonly mention: {};
|
||||
readonly hashtag: {};
|
||||
readonly cashtag: {};
|
||||
readonly bot_command: {};
|
||||
readonly url: {};
|
||||
readonly email: {};
|
||||
readonly phone_number: {};
|
||||
readonly bold: {};
|
||||
readonly italic: {};
|
||||
readonly underline: {};
|
||||
readonly strikethrough: {};
|
||||
readonly spoiler: {};
|
||||
readonly code: {};
|
||||
readonly pre: {};
|
||||
readonly text_link: {};
|
||||
readonly text_mention: {};
|
||||
readonly custom_emoji: {};
|
||||
};
|
||||
readonly caption_entities: {
|
||||
readonly mention: {};
|
||||
readonly hashtag: {};
|
||||
readonly cashtag: {};
|
||||
readonly bot_command: {};
|
||||
readonly url: {};
|
||||
readonly email: {};
|
||||
readonly phone_number: {};
|
||||
readonly bold: {};
|
||||
readonly italic: {};
|
||||
readonly underline: {};
|
||||
readonly strikethrough: {};
|
||||
readonly spoiler: {};
|
||||
readonly code: {};
|
||||
readonly pre: {};
|
||||
readonly text_link: {};
|
||||
readonly text_mention: {};
|
||||
readonly custom_emoji: {};
|
||||
};
|
||||
readonly has_media_spoiler: {};
|
||||
readonly caption: {};
|
||||
};
|
||||
readonly inline_query: {};
|
||||
readonly chosen_inline_result: {};
|
||||
readonly callback_query: {
|
||||
readonly data: {};
|
||||
readonly game_short_name: {};
|
||||
};
|
||||
readonly shipping_query: {};
|
||||
readonly pre_checkout_query: {};
|
||||
readonly poll: {};
|
||||
readonly poll_answer: {};
|
||||
readonly my_chat_member: {
|
||||
readonly from: {
|
||||
readonly me: {};
|
||||
readonly is_bot: {};
|
||||
readonly is_premium: {};
|
||||
readonly added_to_attachment_menu: {};
|
||||
};
|
||||
};
|
||||
readonly chat_member: {
|
||||
readonly from: {
|
||||
readonly me: {};
|
||||
readonly is_bot: {};
|
||||
readonly is_premium: {};
|
||||
readonly added_to_attachment_menu: {};
|
||||
};
|
||||
};
|
||||
readonly chat_join_request: {};
|
||||
};
|
||||
type KeyOf<T> = string & keyof T;
|
||||
type S = typeof UPDATE_KEYS;
|
||||
type L1S = KeyOf<S>;
|
||||
type L2S<L1 extends L1S = L1S> = L1 extends unknown ? `${L1}:${KeyOf<S[L1]>}` : never;
|
||||
type L3S<L1 extends L1S = L1S> = L1 extends unknown ? L3S_<L1> : never;
|
||||
type L3S_<L1 extends L1S, L2 extends KeyOf<S[L1]> = KeyOf<S[L1]>> = L2 extends unknown ? `${L1}:${L2}:${KeyOf<S[L1][L2]>}` : never;
|
||||
type L123 = L1S | L2S | L3S;
|
||||
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>;
|
||||
type CollapseL1<Q extends string, L extends L1Shortcuts = Exclude<L1Shortcuts, "">> = Q | (L extends string ? Q extends typeof L1_SHORTCUTS[L][number] ? L : never : never);
|
||||
type CollapseL2<Q extends string, L extends L2Shortcuts = Exclude<L2Shortcuts, "">> = Q | (L extends string ? Q extends typeof L2_SHORTCUTS[L][number] ? L : never : never);
|
||||
type AllValidFilterQueries = InjectShortcuts;
|
||||
/**
|
||||
* Represents a filter query that can be passed to `bot.on`. There are three
|
||||
* different kinds of filter queries: Level 1, Level 2, and Level 3. Check out
|
||||
* the [website](https://grammy.dev/guide/filter-queries.html) to read about how
|
||||
* filter queries work in grammY, and how to use them.
|
||||
*
|
||||
* Here are three brief examples:
|
||||
* ```ts
|
||||
* // Listen for messages of any type (Level 1)
|
||||
* bot.on('message', ctx => { ... })
|
||||
* // Listen for audio messages only (Level 2)
|
||||
* bot.on('message:audio', ctx => { ... })
|
||||
* // Listen for text messages that have a URL entity (Level 3)
|
||||
* bot.on('message:entities:url', ctx => { ... })
|
||||
* ```
|
||||
*/
|
||||
export type FilterQuery = AllValidFilterQueries;
|
||||
/**
|
||||
* Any kind of value that appears in the Telegram Bot API. When intersected with
|
||||
* an optional field, it effectively removes `| undefined`.
|
||||
*/
|
||||
type NotUndefined = string | number | boolean | object;
|
||||
/**
|
||||
* Given a FilterQuery, returns an object that, when intersected with an Update,
|
||||
* marks those properties as required that are guaranteed to exist.
|
||||
*/
|
||||
type RunQuery<Q extends string> = L1Discriminator<Q, L1Parts<Q>>;
|
||||
type L1Parts<Q extends string> = Q extends `${infer L1}:${string}` ? L1 : Q;
|
||||
type L2Parts<Q extends string, L1 extends string> = Q extends `${L1}:${infer L2}:${string}` ? L2 : Q extends `${L1}:${infer L2}` ? L2 : never;
|
||||
type L1Discriminator<Q extends string, L1 extends string> = Combine<L1Fragment<Q, L1>, L1>;
|
||||
type L1Fragment<Q extends string, L1 extends string> = L1 extends unknown ? Record<L1, L2Discriminator<L1, L2Parts<Q, L1>>> : never;
|
||||
type L2Discriminator<L1 extends string, L2 extends string> = [L2] extends [
|
||||
never
|
||||
] ? L2ShallowFragment<L1> : Combine<L2Fragment<L1, L2>, L2>;
|
||||
type L2Fragment<L1 extends string, L2 extends string> = L2 extends unknown ? Record<L2 | AddTwins<L1, L2>, NotUndefined> : never;
|
||||
type L2ShallowFragment<L1 extends string> = Record<AddTwins<L1, never>, NotUndefined>;
|
||||
type Combine<U, K extends string> = U extends unknown ? U & Partial<Record<Exclude<K, keyof U>, undefined>> : never;
|
||||
export type FilterCore<Q extends FilterQuery> = PerformQueryCore<RunQuery<ExpandShortcuts<Q>>>;
|
||||
/**
|
||||
* This type infers which properties will be present on the given context object
|
||||
* provided it matches the given filter query. If the filter query is a union
|
||||
* type, the produced context object will be a union of possible combinations,
|
||||
* hence allowing you to narrow down manually which of the properties are
|
||||
* present.
|
||||
*
|
||||
* In some sense, this type computes `matchFilter` on the type level.
|
||||
*/
|
||||
export type Filter<C extends Context, Q extends FilterQuery> = PerformQuery<C, RunQuery<ExpandShortcuts<Q>>>;
|
||||
type PerformQueryCore<U extends object> = U extends unknown ? FilteredContextCore<Update & U> : never;
|
||||
type PerformQuery<C extends Context, U extends object> = U extends unknown ? FilteredContext<C, Update & U> : never;
|
||||
type FilteredContextCore<U extends Update> = Record<"update", U> & AliasProps<Omit<U, "update_id">> & Shortcuts<U>;
|
||||
type FilteredContext<C extends Context, U extends Update> = C & FilteredContextCore<U>;
|
||||
interface Shortcuts<U extends Update> {
|
||||
msg: [U["callback_query"]] extends [object] ? U["callback_query"]["message"] : [U["message"]] extends [object] ? U["message"] : [U["edited_message"]] extends [object] ? U["edited_message"] : [U["channel_post"]] extends [object] ? U["channel_post"] : [U["edited_channel_post"]] extends [object] ? U["edited_channel_post"] : undefined;
|
||||
chat: [U["callback_query"]] extends [object] ? NonNullable<U["callback_query"]["message"]>["chat"] | undefined : [Shortcuts<U>["msg"]] extends [object] ? Shortcuts<U>["msg"]["chat"] : [U["my_chat_member"]] extends [object] ? U["my_chat_member"]["chat"] : [U["chat_member"]] extends [object] ? U["chat_member"]["chat"] : [U["chat_join_request"]] extends [object] ? U["chat_join_request"]["chat"] : undefined;
|
||||
senderChat: [Shortcuts<U>["msg"]] extends [object] ? Shortcuts<U>["msg"]["sender_chat"] : undefined;
|
||||
from: [U["callback_query"]] extends [object] ? U["callback_query"]["from"] : [U["inline_query"]] extends [object] ? U["inline_query"]["from"] : [U["shipping_query"]] extends [object] ? U["shipping_query"]["from"] : [U["pre_checkout_query"]] extends [object] ? U["pre_checkout_query"]["from"] : [U["chosen_inline_result"]] extends [object] ? U["chosen_inline_result"]["from"] : [U["message"]] extends [object] ? NonNullable<U["message"]["from"]> : [U["edited_message"]] extends [object] ? NonNullable<U["edited_message"]["from"]> : [U["my_chat_member"]] extends [object] ? U["my_chat_member"]["from"] : [U["chat_member"]] extends [object] ? U["chat_member"]["from"] : [U["chat_join_request"]] extends [object] ? U["chat_join_request"]["from"] : undefined;
|
||||
}
|
||||
declare const L1_SHORTCUTS: {
|
||||
readonly "": readonly ["message", "channel_post"];
|
||||
readonly msg: readonly ["message", "channel_post"];
|
||||
readonly edit: readonly ["edited_message", "edited_channel_post"];
|
||||
};
|
||||
declare const L2_SHORTCUTS: {
|
||||
readonly "": readonly ["entities", "caption_entities"];
|
||||
readonly media: readonly ["photo", "video"];
|
||||
readonly file: readonly ["photo", "animation", "audio", "document", "video", "video_note", "voice", "sticker"];
|
||||
};
|
||||
type L1Shortcuts = KeyOf<typeof L1_SHORTCUTS>;
|
||||
type L2Shortcuts = KeyOf<typeof L2_SHORTCUTS>;
|
||||
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>;
|
||||
type ExpandL1<S extends string> = S extends L1Shortcuts ? typeof L1_SHORTCUTS[S][number] : S;
|
||||
type ExpandL2<S extends string> = S extends L2Shortcuts ? typeof L2_SHORTCUTS[S][number] : S;
|
||||
type AddTwins<L1 extends string, L2 extends string> = TwinsFromL1<L1, L2> | TwinsFromL2<L1, L2>;
|
||||
type TwinsFromL1<L1 extends string, L2 extends string> = L1 extends KeyOf<L1Equivalents> ? L1Equivalents[L1] : L2;
|
||||
type L1Equivalents = {
|
||||
message: "from";
|
||||
edited_message: "from" | "edit_date";
|
||||
channel_post: "sender_chat";
|
||||
edited_channel_post: "sender_chat" | "edit_date";
|
||||
};
|
||||
type TwinsFromL2<L1 extends string, L2 extends string> = L1 extends KeyOf<L2Equivalents> ? L2 extends KeyOf<L2Equivalents[L1]> ? L2Equivalents[L1][L2] : L2 : L2;
|
||||
type L2Equivalents = {
|
||||
message: MessageEquivalents;
|
||||
edited_message: MessageEquivalents;
|
||||
channel_post: MessageEquivalents;
|
||||
edited_channel_post: MessageEquivalents;
|
||||
};
|
||||
type MessageEquivalents = {
|
||||
animation: "document";
|
||||
entities: "text";
|
||||
caption: CaptionMessages;
|
||||
caption_entities: CaptionMessages;
|
||||
};
|
||||
type CaptionMessages = "animation" | "audio" | "document" | "photo" | "video" | "voice";
|
||||
export {};
|
329
node_modules/grammy/out/filter.js
generated
vendored
Normal file
329
node_modules/grammy/out/filter.js
generated
vendored
Normal file
@ -0,0 +1,329 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.preprocess = exports.parse = exports.matchFilter = void 0;
|
||||
// === Obtain O(1) filter function from query
|
||||
/**
|
||||
* > This is an advanced function of grammY.
|
||||
*
|
||||
* Takes a filter query and turns it into a predicate function that can check in
|
||||
* constant time whether a given context object satisfies the query. The created
|
||||
* predicate can be passed to `bot.filter` and will narrow down the context
|
||||
* accordingly.
|
||||
*
|
||||
* This function is used internally by `bot.on` but exposed for advanced usage
|
||||
* like the following.
|
||||
* ```ts
|
||||
* // Listens for updates except forwards of messages or channel posts
|
||||
* bot.drop(matchFilter(':forward_date'), ctx => { ... })
|
||||
* ```
|
||||
*
|
||||
* Check out the
|
||||
* [documentation](https://doc.deno.land/https://deno.land/x/grammy/mod.ts/~/Composer)
|
||||
* of `bot.on` for examples. In addition, the
|
||||
* [website](https://grammy.dev/guide/filter-queries.html) contains more
|
||||
* information about how filter queries work in grammY.
|
||||
*
|
||||
* @param filter A filter query or an array of filter queries
|
||||
*/
|
||||
function matchFilter(filter) {
|
||||
const parsed = parse(filter);
|
||||
const predicate = compile(parsed);
|
||||
return (ctx) => predicate(ctx);
|
||||
}
|
||||
exports.matchFilter = matchFilter;
|
||||
function parse(filter) {
|
||||
return Array.isArray(filter)
|
||||
? filter.map((q) => q.split(":"))
|
||||
: [filter.split(":")];
|
||||
}
|
||||
exports.parse = parse;
|
||||
function compile(parsed) {
|
||||
const preprocessed = parsed.flatMap((q) => check(q, preprocess(q)));
|
||||
const ltree = treeify(preprocessed);
|
||||
const predicate = arborist(ltree); // arborists check trees
|
||||
return (ctx) => !!predicate(ctx.update, ctx);
|
||||
}
|
||||
function preprocess(filter) {
|
||||
const valid = UPDATE_KEYS;
|
||||
const expanded = [filter]
|
||||
// expand L1
|
||||
.flatMap((q) => {
|
||||
const [l1, l2, l3] = q;
|
||||
// only expand if shortcut is given
|
||||
if (!(l1 in L1_SHORTCUTS))
|
||||
return [q];
|
||||
// only expand for at least one non-empty part
|
||||
if (!l1 && !l2 && !l3)
|
||||
return [q];
|
||||
// perform actual expansion
|
||||
const targets = L1_SHORTCUTS[l1];
|
||||
const expanded = targets.map((s) => [s, l2, l3]);
|
||||
// assume that bare L1 expansions are always correct
|
||||
if (l2 === undefined)
|
||||
return expanded;
|
||||
// only filter out invalid expansions if we don't do this later
|
||||
if (l2 in L2_SHORTCUTS && (l2 || l3))
|
||||
return expanded;
|
||||
// filter out invalid expansions, e.g. `channel_post:new_chat_member` for empty L1
|
||||
return expanded.filter(([s]) => { var _a; return !!((_a = valid[s]) === null || _a === void 0 ? void 0 : _a[l2]); });
|
||||
})
|
||||
// expand L2
|
||||
.flatMap((q) => {
|
||||
const [l1, l2, l3] = q;
|
||||
// only expand if shortcut is given
|
||||
if (!(l2 in L2_SHORTCUTS))
|
||||
return [q];
|
||||
// only expand for at least one non-empty part
|
||||
if (!l2 && !l3)
|
||||
return [q];
|
||||
// perform actual expansion
|
||||
const targets = L2_SHORTCUTS[l2];
|
||||
const expanded = targets.map((s) => [l1, s, l3]);
|
||||
// assume that bare L2 expansions are always correct
|
||||
if (l3 === undefined)
|
||||
return expanded;
|
||||
// filter out invalid expansions
|
||||
return expanded.filter(([, s]) => { var _a, _b; return !!((_b = (_a = valid[l1]) === null || _a === void 0 ? void 0 : _a[s]) === null || _b === void 0 ? void 0 : _b[l3]); });
|
||||
});
|
||||
if (expanded.length === 0) {
|
||||
throw new Error(`Shortcuts in '${filter.join(":")}' do not expand to any valid filter query`);
|
||||
}
|
||||
return expanded;
|
||||
}
|
||||
exports.preprocess = preprocess;
|
||||
function check(original, preprocessed) {
|
||||
if (preprocessed.length === 0)
|
||||
throw new Error("Empty filter query given");
|
||||
const errors = preprocessed
|
||||
.map(checkOne)
|
||||
.filter((r) => r !== true);
|
||||
if (errors.length === 0)
|
||||
return preprocessed;
|
||||
else if (errors.length === 1)
|
||||
throw new Error(errors[0]);
|
||||
else {
|
||||
throw new Error(`Invalid filter query '${original.join(":")}'. There are ${errors.length} errors after expanding the contained shortcuts: ${errors.join("; ")}`);
|
||||
}
|
||||
}
|
||||
function checkOne(filter) {
|
||||
const [l1, l2, l3, ...n] = filter;
|
||||
if (l1 === undefined)
|
||||
return "Empty filter query given";
|
||||
if (!(l1 in UPDATE_KEYS)) {
|
||||
const permitted = Object.keys(UPDATE_KEYS);
|
||||
return `Invalid L1 filter '${l1}' given in '${filter.join(":")}'. \
|
||||
Permitted values are: ${permitted.map((k) => `'${k}'`).join(", ")}.`;
|
||||
}
|
||||
if (l2 === undefined)
|
||||
return true;
|
||||
const l1Obj = UPDATE_KEYS[l1];
|
||||
if (!(l2 in l1Obj)) {
|
||||
const permitted = Object.keys(l1Obj);
|
||||
return `Invalid L2 filter '${l2}' given in '${filter.join(":")}'. \
|
||||
Permitted values are: ${permitted.map((k) => `'${k}'`).join(", ")}.`;
|
||||
}
|
||||
if (l3 === undefined)
|
||||
return true;
|
||||
const l2Obj = l1Obj[l2];
|
||||
if (!(l3 in l2Obj)) {
|
||||
const permitted = Object.keys(l2Obj);
|
||||
return `Invalid L3 filter '${l3}' given in '${filter.join(":")}'. ${permitted.length === 0
|
||||
? `No further filtering is possible after '${l1}:${l2}'.`
|
||||
: `Permitted values are: ${permitted.map((k) => `'${k}'`).join(", ")}.`}`;
|
||||
}
|
||||
if (n.length === 0)
|
||||
return true;
|
||||
return `Cannot filter further than three levels, ':${n.join(":")}' is invalid!`;
|
||||
}
|
||||
function treeify(paths) {
|
||||
var _a, _b;
|
||||
const tree = {};
|
||||
for (const [l1, l2, l3] of paths) {
|
||||
const subtree = ((_a = tree[l1]) !== null && _a !== void 0 ? _a : (tree[l1] = {}));
|
||||
if (l2 !== undefined) {
|
||||
const set = ((_b = subtree[l2]) !== null && _b !== void 0 ? _b : (subtree[l2] = new Set()));
|
||||
if (l3 !== undefined)
|
||||
set.add(l3);
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
function or(left, right) {
|
||||
return (obj, ctx) => left(obj, ctx) || right(obj, ctx);
|
||||
}
|
||||
function concat(get, test) {
|
||||
return (obj, ctx) => {
|
||||
const nextObj = get(obj, ctx);
|
||||
return nextObj && test(nextObj, ctx);
|
||||
};
|
||||
}
|
||||
function leaf(pred) {
|
||||
return (obj, ctx) => pred(obj, ctx) != null;
|
||||
}
|
||||
function arborist(tree) {
|
||||
const l1Predicates = Object.entries(tree).map(([l1, subtree]) => {
|
||||
const l1Pred = (obj) => obj[l1];
|
||||
const l2Predicates = Object.entries(subtree).map(([l2, set]) => {
|
||||
const l2Pred = (obj) => obj[l2];
|
||||
const l3Predicates = Array.from(set).map((l3) => {
|
||||
const l3Pred = l3 === "me" // special handling for `me` shortcut
|
||||
? (obj, ctx) => {
|
||||
const me = ctx.me.id;
|
||||
return testMaybeArray(obj, (u) => u.id === me);
|
||||
}
|
||||
: (obj) => testMaybeArray(obj, (e) => e[l3] || e.type === l3);
|
||||
return l3Pred;
|
||||
});
|
||||
return l3Predicates.length === 0
|
||||
? leaf(l2Pred)
|
||||
: concat(l2Pred, l3Predicates.reduce(or));
|
||||
});
|
||||
return l2Predicates.length === 0
|
||||
? leaf(l1Pred)
|
||||
: concat(l1Pred, l2Predicates.reduce(or));
|
||||
});
|
||||
if (l1Predicates.length === 0) {
|
||||
throw new Error("Cannot create filter function for empty query");
|
||||
}
|
||||
return l1Predicates.reduce(or);
|
||||
}
|
||||
function testMaybeArray(t, pred) {
|
||||
const p = (x) => x != null && pred(x);
|
||||
return Array.isArray(t) ? t.some(p) : p(t);
|
||||
}
|
||||
// === Define a structure to validate the queries
|
||||
// L3
|
||||
const ENTITY_KEYS = {
|
||||
mention: {},
|
||||
hashtag: {},
|
||||
cashtag: {},
|
||||
bot_command: {},
|
||||
url: {},
|
||||
email: {},
|
||||
phone_number: {},
|
||||
bold: {},
|
||||
italic: {},
|
||||
underline: {},
|
||||
strikethrough: {},
|
||||
spoiler: {},
|
||||
code: {},
|
||||
pre: {},
|
||||
text_link: {},
|
||||
text_mention: {},
|
||||
custom_emoji: {},
|
||||
};
|
||||
const USER_KEYS = {
|
||||
me: {},
|
||||
is_bot: {},
|
||||
is_premium: {},
|
||||
added_to_attachment_menu: {},
|
||||
};
|
||||
const STICKER_KEYS = {
|
||||
is_video: {},
|
||||
is_animated: {},
|
||||
premium_animation: {},
|
||||
};
|
||||
// L2
|
||||
const EDITABLE_MESSAGE_KEYS = {
|
||||
text: {},
|
||||
animation: {},
|
||||
audio: {},
|
||||
document: {},
|
||||
photo: {},
|
||||
video: {},
|
||||
game: {},
|
||||
location: {},
|
||||
entities: ENTITY_KEYS,
|
||||
caption_entities: ENTITY_KEYS,
|
||||
has_media_spoiler: {},
|
||||
caption: {},
|
||||
};
|
||||
const COMMON_MESSAGE_KEYS = {
|
||||
...EDITABLE_MESSAGE_KEYS,
|
||||
sticker: STICKER_KEYS,
|
||||
video_note: {},
|
||||
voice: {},
|
||||
contact: {},
|
||||
dice: {},
|
||||
poll: {},
|
||||
venue: {},
|
||||
new_chat_title: {},
|
||||
new_chat_photo: {},
|
||||
delete_chat_photo: {},
|
||||
message_auto_delete_timer_changed: {},
|
||||
pinned_message: {},
|
||||
invoice: {},
|
||||
proximity_alert_triggered: {},
|
||||
video_chat_scheduled: {},
|
||||
video_chat_started: {},
|
||||
video_chat_ended: {},
|
||||
video_chat_participants_invited: {},
|
||||
web_app_data: {},
|
||||
forward_date: {},
|
||||
is_topic_message: {},
|
||||
is_automatic_forward: {},
|
||||
};
|
||||
const MESSAGE_KEYS = {
|
||||
...COMMON_MESSAGE_KEYS,
|
||||
new_chat_members: USER_KEYS,
|
||||
left_chat_member: USER_KEYS,
|
||||
group_chat_created: {},
|
||||
supergroup_chat_created: {},
|
||||
migrate_to_chat_id: {},
|
||||
migrate_from_chat_id: {},
|
||||
successful_payment: {},
|
||||
user_shared: {},
|
||||
chat_shared: {},
|
||||
connected_website: {},
|
||||
write_access_allowed: {},
|
||||
passport_data: {},
|
||||
forum_topic_created: {},
|
||||
forum_topic_edited: { name: {}, icon_custom_emoji_id: {} },
|
||||
forum_topic_closed: {},
|
||||
forum_topic_reopened: {},
|
||||
general_forum_topic_hidden: {},
|
||||
general_forum_topic_unhidden: {},
|
||||
};
|
||||
const CHANNEL_POST_KEYS = {
|
||||
...COMMON_MESSAGE_KEYS,
|
||||
channel_chat_created: {},
|
||||
};
|
||||
const CALLBACK_QUERY_KEYS = { data: {}, game_short_name: {} };
|
||||
const CHAT_MEMBER_UPDATED_KEYS = { from: USER_KEYS };
|
||||
// L1
|
||||
const UPDATE_KEYS = {
|
||||
message: MESSAGE_KEYS,
|
||||
edited_message: MESSAGE_KEYS,
|
||||
channel_post: CHANNEL_POST_KEYS,
|
||||
edited_channel_post: CHANNEL_POST_KEYS,
|
||||
inline_query: {},
|
||||
chosen_inline_result: {},
|
||||
callback_query: CALLBACK_QUERY_KEYS,
|
||||
shipping_query: {},
|
||||
pre_checkout_query: {},
|
||||
poll: {},
|
||||
poll_answer: {},
|
||||
my_chat_member: CHAT_MEMBER_UPDATED_KEYS,
|
||||
chat_member: CHAT_MEMBER_UPDATED_KEYS,
|
||||
chat_join_request: {},
|
||||
};
|
||||
// === Define some helpers for handling shortcuts, e.g. in 'edit:photo'
|
||||
const L1_SHORTCUTS = {
|
||||
"": ["message", "channel_post"],
|
||||
msg: ["message", "channel_post"],
|
||||
edit: ["edited_message", "edited_channel_post"],
|
||||
};
|
||||
const L2_SHORTCUTS = {
|
||||
"": ["entities", "caption_entities"],
|
||||
media: ["photo", "video"],
|
||||
file: [
|
||||
"photo",
|
||||
"animation",
|
||||
"audio",
|
||||
"document",
|
||||
"video",
|
||||
"video_note",
|
||||
"voice",
|
||||
"sticker",
|
||||
],
|
||||
};
|
14
node_modules/grammy/out/mod.d.ts
generated
vendored
Normal file
14
node_modules/grammy/out/mod.d.ts
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
export { Bot, type BotConfig, BotError, type ErrorHandler, type PollingOptions, } from "./bot.js";
|
||||
export { InputFile } from "./types.js";
|
||||
export { type CallbackQueryContext, type ChatTypeContext, type CommandContext, Context, type GameQueryContext, type HearsContext, type InlineQueryContext, } from "./context.js";
|
||||
export * from "./convenience/constants.js";
|
||||
export * from "./convenience/inline_query.js";
|
||||
export * from "./convenience/input_media.js";
|
||||
export * from "./convenience/keyboard.js";
|
||||
export * from "./convenience/session.js";
|
||||
export * from "./convenience/webhook.js";
|
||||
export { type CallbackQueryMiddleware, type ChatTypeMiddleware, type CommandMiddleware, Composer, type GameQueryMiddleware, type HearsMiddleware, type InlineQueryMiddleware, type Middleware, type MiddlewareFn, type MiddlewareObj, type NextFunction, } from "./composer.js";
|
||||
export { type Filter, type FilterQuery, matchFilter } from "./filter.js";
|
||||
export { Api } from "./core/api.js";
|
||||
export { type ApiCallFn, type ApiClientOptions, type RawApi, type TransformableApi, type Transformer, type WebhookReplyEnvelope, } from "./core/client.js";
|
||||
export { GrammyError, HttpError } from "./core/error.js";
|
43
node_modules/grammy/out/mod.js
generated
vendored
Normal file
43
node_modules/grammy/out/mod.js
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HttpError = exports.GrammyError = exports.Api = exports.matchFilter = exports.Composer = exports.Context = exports.InputFile = exports.BotError = exports.Bot = void 0;
|
||||
// Commonly used stuff
|
||||
var bot_js_1 = require("./bot.js");
|
||||
Object.defineProperty(exports, "Bot", { enumerable: true, get: function () { return bot_js_1.Bot; } });
|
||||
Object.defineProperty(exports, "BotError", { enumerable: true, get: function () { return bot_js_1.BotError; } });
|
||||
var types_js_1 = require("./types.js");
|
||||
Object.defineProperty(exports, "InputFile", { enumerable: true, get: function () { return types_js_1.InputFile; } });
|
||||
var context_js_1 = require("./context.js");
|
||||
Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return context_js_1.Context; } });
|
||||
// Convenience stuff, built-in plugins, and helpers
|
||||
__exportStar(require("./convenience/constants.js"), exports);
|
||||
__exportStar(require("./convenience/inline_query.js"), exports);
|
||||
__exportStar(require("./convenience/input_media.js"), exports);
|
||||
__exportStar(require("./convenience/keyboard.js"), exports);
|
||||
__exportStar(require("./convenience/session.js"), exports);
|
||||
__exportStar(require("./convenience/webhook.js"), exports);
|
||||
// A little more advanced stuff
|
||||
var composer_js_1 = require("./composer.js");
|
||||
Object.defineProperty(exports, "Composer", { enumerable: true, get: function () { return composer_js_1.Composer; } });
|
||||
var filter_js_1 = require("./filter.js");
|
||||
Object.defineProperty(exports, "matchFilter", { enumerable: true, get: function () { return filter_js_1.matchFilter; } });
|
||||
// Internal stuff for expert users
|
||||
var api_js_1 = require("./core/api.js");
|
||||
Object.defineProperty(exports, "Api", { enumerable: true, get: function () { return api_js_1.Api; } });
|
||||
var error_js_1 = require("./core/error.js");
|
||||
Object.defineProperty(exports, "GrammyError", { enumerable: true, get: function () { return error_js_1.GrammyError; } });
|
||||
Object.defineProperty(exports, "HttpError", { enumerable: true, get: function () { return error_js_1.HttpError; } });
|
20
node_modules/grammy/out/platform.node.d.ts
generated
vendored
Normal file
20
node_modules/grammy/out/platform.node.d.ts
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference types="node" />
|
||||
/// <reference types="node" />
|
||||
import { Agent as HttpAgent } from "http";
|
||||
import { Agent as HttpsAgent } from "https";
|
||||
import { Readable } from "stream";
|
||||
import { debug as d } from "debug";
|
||||
export { d as debug };
|
||||
export declare const itrToStream: (itr: AsyncIterable<Uint8Array>) => Readable;
|
||||
export declare function baseFetchConfig(apiRoot: string): {
|
||||
compress: boolean;
|
||||
agent: HttpsAgent;
|
||||
} | {
|
||||
agent: HttpAgent;
|
||||
compress?: undefined;
|
||||
} | {
|
||||
compress?: undefined;
|
||||
agent?: undefined;
|
||||
};
|
||||
export declare const defaultAdapter = "express";
|
43
node_modules/grammy/out/platform.node.js
generated
vendored
Normal file
43
node_modules/grammy/out/platform.node.js
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.defaultAdapter = exports.baseFetchConfig = exports.itrToStream = exports.debug = void 0;
|
||||
// === Needed imports
|
||||
const http_1 = require("http");
|
||||
const https_1 = require("https");
|
||||
const stream_1 = require("stream");
|
||||
// === Export debug
|
||||
const debug_1 = require("debug");
|
||||
Object.defineProperty(exports, "debug", { enumerable: true, get: function () { return debug_1.debug; } });
|
||||
// === Export system-specific operations
|
||||
// Turn an AsyncIterable<Uint8Array> into a stream
|
||||
const itrToStream = (itr) => stream_1.Readable.from(itr, { objectMode: false });
|
||||
exports.itrToStream = itrToStream;
|
||||
// === Base configuration for `fetch` calls
|
||||
const httpAgents = new Map();
|
||||
const httpsAgents = new Map();
|
||||
function getCached(map, key, otherwise) {
|
||||
let value = map.get(key);
|
||||
if (value === undefined) {
|
||||
value = otherwise();
|
||||
map.set(key, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function baseFetchConfig(apiRoot) {
|
||||
if (apiRoot.startsWith("https:")) {
|
||||
return {
|
||||
compress: true,
|
||||
agent: getCached(httpsAgents, apiRoot, () => new https_1.Agent({ keepAlive: true })),
|
||||
};
|
||||
}
|
||||
else if (apiRoot.startsWith("http:")) {
|
||||
return {
|
||||
agent: getCached(httpAgents, apiRoot, () => new http_1.Agent({ keepAlive: true })),
|
||||
};
|
||||
}
|
||||
else
|
||||
return {};
|
||||
}
|
||||
exports.baseFetchConfig = baseFetchConfig;
|
||||
// === Default webhook adapter
|
||||
exports.defaultAdapter = "express";
|
2
node_modules/grammy/out/shim.node.d.ts
generated
vendored
Normal file
2
node_modules/grammy/out/shim.node.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export { AbortController, type AbortSignal } from "abort-controller";
|
||||
export { default as fetch } from "node-fetch";
|
7
node_modules/grammy/out/shim.node.js
generated
vendored
Normal file
7
node_modules/grammy/out/shim.node.js
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.fetch = exports.AbortController = void 0;
|
||||
var abort_controller_1 = require("abort-controller");
|
||||
Object.defineProperty(exports, "AbortController", { enumerable: true, get: function () { return abort_controller_1.AbortController; } });
|
||||
var node_fetch_1 = require("node-fetch");
|
||||
Object.defineProperty(exports, "fetch", { enumerable: true, get: function () { return node_fetch_1.default; } });
|
1
node_modules/grammy/out/types.d.ts
generated
vendored
Normal file
1
node_modules/grammy/out/types.d.ts
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
export * from "./types.node.js";
|
17
node_modules/grammy/out/types.js
generated
vendored
Normal file
17
node_modules/grammy/out/types.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./types.node.js"), exports);
|
71
node_modules/grammy/out/types.node.d.ts
generated
vendored
Normal file
71
node_modules/grammy/out/types.node.d.ts
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
/// <reference types="node" />
|
||||
import { type ApiMethods as ApiMethodsF, type InputMedia as InputMediaF, type InputMediaAnimation as InputMediaAnimationF, type InputMediaAudio as InputMediaAudioF, type InputMediaDocument as InputMediaDocumentF, type InputMediaPhoto as InputMediaPhotoF, type InputMediaVideo as InputMediaVideoF, type InputSticker as InputStickerF, type Opts as OptsF } from "@grammyjs/types";
|
||||
import { type ReadStream } from "fs";
|
||||
export * from "@grammyjs/types";
|
||||
/** A value, or a potentially async function supplying that value */
|
||||
type MaybeSupplier<T> = T | (() => T | Promise<T>);
|
||||
/** Something that looks like a URL. */
|
||||
interface URLLike {
|
||||
/**
|
||||
* Identifier of the resource. Must be in a format that can be parsed by the
|
||||
* URL constructor.
|
||||
*/
|
||||
url: string;
|
||||
}
|
||||
/**
|
||||
* An `InputFile` wraps a number of different sources for [sending
|
||||
* files](https://grammy.dev/guide/files.html#uploading-your-own-file).
|
||||
*
|
||||
* It corresponds to the `InputFile` type in the [Telegram Bot API
|
||||
* Reference](https://core.telegram.org/bots/api#inputfile).
|
||||
*/
|
||||
export declare class InputFile {
|
||||
private consumed;
|
||||
private readonly fileData;
|
||||
/**
|
||||
* Optional name of the constructed `InputFile` instance.
|
||||
*
|
||||
* Check out the
|
||||
* [documentation](https://grammy.dev/guide/files.html#uploading-your-own-file)
|
||||
* on sending files with `InputFile`.
|
||||
*/
|
||||
readonly filename?: string;
|
||||
/**
|
||||
* Constructs an `InputFile` that can be used in the API to send files.
|
||||
*
|
||||
* @param file A path to a local file or a `Buffer` or a `fs.ReadStream` that specifies the file data
|
||||
* @param filename Optional name of the file
|
||||
*/
|
||||
constructor(file: MaybeSupplier<string | URL | URLLike | Uint8Array | ReadStream | Iterable<Uint8Array> | AsyncIterable<Uint8Array>>, filename?: string);
|
||||
private guessFilename;
|
||||
/**
|
||||
* Internal method. Do not use.
|
||||
*
|
||||
* Converts this instance into a binary representation that can be sent to
|
||||
* the Bot API server in the request body.
|
||||
*/
|
||||
toRaw(): Promise<Uint8Array | Iterable<Uint8Array> | AsyncIterable<Uint8Array>>;
|
||||
}
|
||||
/** Wrapper type to bundle all methods of the Telegram API */
|
||||
export type ApiMethods = ApiMethodsF<InputFile>;
|
||||
/** Utility type providing the argument type for the given method name or `{}` if the method does not take any parameters */
|
||||
export type Opts<M extends keyof ApiMethods> = OptsF<InputFile>[M];
|
||||
/** This object describes a sticker to be added to a sticker set. */
|
||||
export type InputSticker = InputStickerF<InputFile>;
|
||||
/** This object represents the content of a media message to be sent. It should be one of
|
||||
- InputMediaAnimation
|
||||
- InputMediaDocument
|
||||
- InputMediaAudio
|
||||
- InputMediaPhoto
|
||||
- InputMediaVideo */
|
||||
export type InputMedia = InputMediaF<InputFile>;
|
||||
/** Represents a photo to be sent. */
|
||||
export type InputMediaPhoto = InputMediaPhotoF<InputFile>;
|
||||
/** Represents a video to be sent. */
|
||||
export type InputMediaVideo = InputMediaVideoF<InputFile>;
|
||||
/** Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent. */
|
||||
export type InputMediaAnimation = InputMediaAnimationF<InputFile>;
|
||||
/** Represents an audio file to be treated as music to be sent. */
|
||||
export type InputMediaAudio = InputMediaAudioF<InputFile>;
|
||||
/** Represents a general file to be sent. */
|
||||
export type InputMediaDocument = InputMediaDocumentF<InputFile>;
|
107
node_modules/grammy/out/types.node.js
generated
vendored
Normal file
107
node_modules/grammy/out/types.node.js
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.InputFile = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const node_fetch_1 = require("node-fetch");
|
||||
const path_1 = require("path");
|
||||
const platform_node_1 = require("./platform.node");
|
||||
const debug = (0, platform_node_1.debug)("grammy:warn");
|
||||
// === Export all API types
|
||||
__exportStar(require("@grammyjs/types"), exports);
|
||||
// === InputFile handling and File augmenting
|
||||
/**
|
||||
* An `InputFile` wraps a number of different sources for [sending
|
||||
* files](https://grammy.dev/guide/files.html#uploading-your-own-file).
|
||||
*
|
||||
* It corresponds to the `InputFile` type in the [Telegram Bot API
|
||||
* Reference](https://core.telegram.org/bots/api#inputfile).
|
||||
*/
|
||||
class InputFile {
|
||||
/**
|
||||
* Constructs an `InputFile` that can be used in the API to send files.
|
||||
*
|
||||
* @param file A path to a local file or a `Buffer` or a `fs.ReadStream` that specifies the file data
|
||||
* @param filename Optional name of the file
|
||||
*/
|
||||
constructor(file, filename) {
|
||||
this.consumed = false;
|
||||
this.fileData = file;
|
||||
filename !== null && filename !== void 0 ? filename : (filename = this.guessFilename(file));
|
||||
this.filename = filename;
|
||||
if (typeof file === "string" &&
|
||||
(file.startsWith("http:") || file.startsWith("https:"))) {
|
||||
debug(`InputFile received the local file path '${file}' that looks like a URL. Is this a mistake?`);
|
||||
}
|
||||
}
|
||||
guessFilename(file) {
|
||||
if (typeof file === "string")
|
||||
return (0, path_1.basename)(file);
|
||||
if ("url" in file)
|
||||
return (0, path_1.basename)(file.url);
|
||||
if (!(file instanceof URL))
|
||||
return undefined;
|
||||
if (file.pathname !== "/") {
|
||||
const filename = (0, path_1.basename)(file.pathname);
|
||||
if (filename)
|
||||
return filename;
|
||||
}
|
||||
return (0, path_1.basename)(file.hostname);
|
||||
}
|
||||
/**
|
||||
* Internal method. Do not use.
|
||||
*
|
||||
* Converts this instance into a binary representation that can be sent to
|
||||
* the Bot API server in the request body.
|
||||
*/
|
||||
async toRaw() {
|
||||
if (this.consumed) {
|
||||
throw new Error("Cannot reuse InputFile data source!");
|
||||
}
|
||||
const data = this.fileData;
|
||||
// Handle local files
|
||||
if (typeof data === "string")
|
||||
return (0, fs_1.createReadStream)(data);
|
||||
// Handle URLs and URLLike objects
|
||||
if (data instanceof URL) {
|
||||
return data.protocol === "file" // node-fetch does not support file URLs
|
||||
? (0, fs_1.createReadStream)(data.pathname)
|
||||
: fetchFile(data);
|
||||
}
|
||||
if ("url" in data)
|
||||
return fetchFile(data.url);
|
||||
// Return buffers as-is
|
||||
if (data instanceof Uint8Array)
|
||||
return data;
|
||||
// Unwrap supplier functions
|
||||
if (typeof data === "function") {
|
||||
return new InputFile(await data()).toRaw();
|
||||
}
|
||||
// Mark streams and iterators as consumed and return them as-is
|
||||
this.consumed = true;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
exports.InputFile = InputFile;
|
||||
async function* fetchFile(url) {
|
||||
const { body } = await (0, node_fetch_1.default)(url);
|
||||
for await (const chunk of body) {
|
||||
if (typeof chunk === "string") {
|
||||
throw new Error(`Could not transfer file, received string data instead of bytes from '${url}'`);
|
||||
}
|
||||
yield chunk;
|
||||
}
|
||||
}
|
1
node_modules/grammy/out/web.d.ts
generated
vendored
Normal file
1
node_modules/grammy/out/web.d.ts
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
export * from "./mod";
|
5692
node_modules/grammy/out/web.mjs
generated
vendored
Normal file
5692
node_modules/grammy/out/web.mjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
72
node_modules/grammy/package.json
generated
vendored
Normal file
72
node_modules/grammy/package.json
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "grammy",
|
||||
"description": "The Telegram Bot Framework.",
|
||||
"version": "1.17.2",
|
||||
"author": "KnorpelSenf",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14.13.1"
|
||||
},
|
||||
"homepage": "https://grammy.dev/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/grammyjs/grammY"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "npm run backport",
|
||||
"backport": "deno2node tsconfig.json",
|
||||
"contribs": "all-contributors"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grammyjs/types": "3.1.2",
|
||||
"abort-controller": "^3.0.0",
|
||||
"debug": "^4.3.4",
|
||||
"node-fetch": "^2.6.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/debug": "^4.1.8",
|
||||
"@types/node": "^12.20.55",
|
||||
"@types/node-fetch": "2.6.2",
|
||||
"all-contributors-cli": "6.24.0",
|
||||
"deno2node": "^1.8.1"
|
||||
},
|
||||
"files": [
|
||||
"out/"
|
||||
],
|
||||
"main": "./out/mod.js",
|
||||
"types": "./out/mod.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./out/mod.d.ts",
|
||||
"node": "./out/mod.js",
|
||||
"browser": "./out/web.mjs",
|
||||
"default": "./out/web.mjs"
|
||||
},
|
||||
"./types": {
|
||||
"types": "./out/types.d.ts"
|
||||
},
|
||||
"./web": {
|
||||
"types": "./out/web.d.ts",
|
||||
"default": "./out/web.mjs"
|
||||
}
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"web": [
|
||||
"out/web"
|
||||
],
|
||||
"types": [
|
||||
"out/types"
|
||||
]
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"telegram",
|
||||
"bot",
|
||||
"api",
|
||||
"client",
|
||||
"framework",
|
||||
"library",
|
||||
"grammy"
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user