This commit is contained in:
nik
2025-10-01 22:50:58 +03:00
parent 0b35b5b968
commit 2767145612
296 changed files with 39425 additions and 0 deletions

22
node_modules/telegraf/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2016-2019 Vitaly Domnikov
Copyright (c) 2020-2023 The Telegraf Contributors
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.

393
node_modules/telegraf/README.md generated vendored Normal file
View File

@@ -0,0 +1,393 @@
<header>
<div align="center">
<img src="docs/assets/logo.svg" alt="logo" height="90" align="center">
<h1 align="center">telegraf.js</h1>
<p>Modern Telegram Bot API framework for Node.js</p>
<a href="https://core.telegram.org/bots/api">
<img src="https://img.shields.io/badge/Bot%20API-v7.1-f36caf.svg?style=flat-square" alt="Bot API Version" />
</a>
<a href="https://packagephobia.com/result?p=telegraf,node-telegram-bot-api">
<img src="https://flat.badgen.net/packagephobia/install/telegraf" alt="install size" />
</a>
<a href="https://github.com/telegraf/telegraf">
<img src="https://img.shields.io/github/languages/top/telegraf/telegraf?style=flat-square&logo=github" alt="GitHub top language" />
</a>
<a href="https://telegram.me/TelegrafJSChat">
<img src="https://img.shields.io/badge/English%20chat-grey?style=flat-square&logo=telegram" alt="English chat" />
</a>
</div>
</header>
## For 3.x users
- [3.x docs](https://telegraf.js.org/v3)
- [4.0 release notes](https://github.com/telegraf/telegraf/releases/tag/v4.0.0)
## Introduction
Bots are special [Telegram](https://telegram.org) accounts designed to handle messages automatically.
Users can interact with bots by sending them command messages in private or group chats.
These accounts serve as an interface for code running somewhere on your server.
Telegraf is a library that makes it simple for you to develop your own Telegram bots using JavaScript or [TypeScript](https://www.typescriptlang.org/).
### Features
- Full [Telegram Bot API 7.1](https://core.telegram.org/bots/api) support
- [Excellent TypeScript typings](https://github.com/telegraf/telegraf/releases/tag/v4.0.0)
- [Lightweight](https://packagephobia.com/result?p=telegraf,node-telegram-bot-api)
- [AWS **λ**](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html)
/ [Firebase](https://firebase.google.com/products/functions/)
/ [Glitch](https://glitch.com/edit/#!/dashing-light)
/ [Fly.io](https://fly.io/docs/languages-and-frameworks/node)
/ Whatever ready
- `http/https/fastify/Connect.js/express.js` compatible webhooks
- Extensible
### Example
```js
const { Telegraf } = require('telegraf')
const { message } = require('telegraf/filters')
const bot = new Telegraf(process.env.BOT_TOKEN)
bot.start((ctx) => ctx.reply('Welcome'))
bot.help((ctx) => ctx.reply('Send me a sticker'))
bot.on(message('sticker'), (ctx) => ctx.reply('👍'))
bot.hears('hi', (ctx) => ctx.reply('Hey there'))
bot.launch()
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'))
process.once('SIGTERM', () => bot.stop('SIGTERM'))
```
```js
const { Telegraf } = require('telegraf')
const bot = new Telegraf(process.env.BOT_TOKEN)
bot.command('oldschool', (ctx) => ctx.reply('Hello'))
bot.command('hipster', Telegraf.reply('λ'))
bot.launch()
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'))
process.once('SIGTERM', () => bot.stop('SIGTERM'))
```
For additional bot examples see the new [`docs repo`](https://github.com/feathers-studio/telegraf-docs/).
### Resources
- [Getting started](#getting-started)
- [API reference](https://telegraf.js.org/modules.html)
- Telegram groups (sorted by number of members):
- [English](https://t.me/TelegrafJSChat)
- [Russian](https://t.me/telegrafjs_ru)
- [Uzbek](https://t.me/botjs_uz)
- [Ethiopian](https://t.me/telegraf_et)
- [GitHub Discussions](https://github.com/telegraf/telegraf/discussions)
- [Dependent repositories](https://libraries.io/npm/telegraf/dependent_repositories)
## Getting started
### Telegram token
To use the [Telegram Bot API](https://core.telegram.org/bots/api),
you first have to [get a bot account](https://core.telegram.org/bots)
by [chatting with BotFather](https://core.telegram.org/bots#6-botfather).
BotFather will give you a _token_, something like `123456789:AbCdefGhIJKlmNoPQRsTUVwxyZ`.
### Installation
```shellscript
$ npm install telegraf
```
or
```shellscript
$ yarn add telegraf
```
or
```shellscript
$ pnpm add telegraf
```
### `Telegraf` class
[`Telegraf`] instance represents your bot. It's responsible for obtaining updates and passing them to your handlers.
Start by [listening to commands](https://telegraf.js.org/classes/Telegraf-1.html#command) and [launching](https://telegraf.js.org/classes/Telegraf-1.html#launch) your bot.
### `Context` class
`ctx` you can see in every example is a [`Context`] instance.
[`Telegraf`] creates one for each incoming update and passes it to your middleware.
It contains the `update`, `botInfo`, and `telegram` for making arbitrary Bot API requests,
as well as shorthand methods and getters.
This is probably the class you'll be using the most.
<!--
TODO: Verify and update list
Here is a list of
#### Known middleware
- [Internationalization](https://github.com/telegraf/telegraf-i18n)—simplifies selecting the right translation to use when responding to a user.
- [Redis powered session](https://github.com/telegraf/telegraf-session-redis)—store session data using Redis.
- [Local powered session (via lowdb)](https://github.com/RealSpeaker/telegraf-session-local)—store session data in a local file.
- [Rate-limiting](https://github.com/telegraf/telegraf-ratelimit)—apply rate limitting to chats or users.
- [Bottleneck powered throttling](https://github.com/KnightNiwrem/telegraf-throttler)—apply throttling to both incoming updates and outgoing API calls.
- [Menus via inline keyboards](https://github.com/EdJoPaTo/telegraf-inline-menu)—simplify creating interfaces based on menus.
- [Stateless Questions](https://github.com/EdJoPaTo/telegraf-stateless-question)—create stateless questions to Telegram users working in privacy mode.
- [Natural language processing via wit.ai](https://github.com/telegraf/telegraf-wit)
- [Natural language processing via recast.ai](https://github.com/telegraf/telegraf-recast)
- [Multivariate and A/B testing](https://github.com/telegraf/telegraf-experiments)—add experiments to see how different versions of a feature are used.
- [Powerfull bot stats via Mixpanel](https://github.com/telegraf/telegraf-mixpanel)
- [statsd integration](https://github.com/telegraf/telegraf-statsd)
- [and more...](https://www.npmjs.com/search?q=telegraf-)
-->
#### Shorthand methods
```js
import { Telegraf } from 'telegraf'
import { message } from 'telegraf/filters'
const bot = new Telegraf(process.env.BOT_TOKEN)
bot.command('quit', async (ctx) => {
// Explicit usage
await ctx.telegram.leaveChat(ctx.message.chat.id)
// Using context shortcut
await ctx.leaveChat()
})
bot.on(message('text'), async (ctx) => {
// Explicit usage
await ctx.telegram.sendMessage(ctx.message.chat.id, `Hello ${ctx.state.role}`)
// Using context shortcut
await ctx.reply(`Hello ${ctx.state.role}`)
})
bot.on('callback_query', async (ctx) => {
// Explicit usage
await ctx.telegram.answerCbQuery(ctx.callbackQuery.id)
// Using context shortcut
await ctx.answerCbQuery()
})
bot.on('inline_query', async (ctx) => {
const result = []
// Explicit usage
await ctx.telegram.answerInlineQuery(ctx.inlineQuery.id, result)
// Using context shortcut
await ctx.answerInlineQuery(result)
})
bot.launch()
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'))
process.once('SIGTERM', () => bot.stop('SIGTERM'))
```
## Production
### Webhooks
```TS
import { Telegraf } from "telegraf";
import { message } from 'telegraf/filters';
const bot = new Telegraf(token);
bot.on(message("text"), ctx => ctx.reply("Hello"));
// Start webhook via launch method (preferred)
bot.launch({
webhook: {
// Public domain for webhook; e.g.: example.com
domain: webhookDomain,
// Port to listen on; e.g.: 8080
port: port,
// Optional path to listen for.
// `bot.secretPathComponent()` will be used by default
path: webhookPath,
// Optional secret to be sent back in a header for security.
// e.g.: `crypto.randomBytes(64).toString("hex")`
secretToken: randomAlphaNumericString,
},
});
```
Use `createWebhook()` if you want to attach Telegraf to an existing http server.
<!-- global bot, tlsOptions -->
```TS
import { createServer } from "http";
createServer(await bot.createWebhook({ domain: "example.com" })).listen(3000);
```
```TS
import { createServer } from "https";
createServer(tlsOptions, await bot.createWebhook({ domain: "example.com" })).listen(8443);
```
- [AWS Lambda example integration](https://github.com/feathers-studio/telegraf-docs/tree/master/examples/functions/aws-lambda)
- [Google Cloud Functions example integration](https://github.com/feathers-studio/telegraf-docs/blob/master/examples/functions/google-cloud-function.ts)
- [`express` example integration](https://github.com/feathers-studio/telegraf-docs/blob/master/examples/webhook/express.ts)
- [`fastify` example integration](https://github.com/feathers-studio/telegraf-docs/blob/master/examples/webhook/fastify.ts)
- [`koa` example integration](https://github.com/feathers-studio/telegraf-docs/blob/master/examples/webhook/koa.ts)
- [NestJS framework integration module](https://github.com/bukhalo/nestjs-telegraf)
- [Cloudflare Workers integration module](https://github.com/Tsuk1ko/cfworker-middware-telegraf)
- Use [`bot.handleUpdate`](https://telegraf.js.org/classes/Telegraf-1.html#handleupdate) to write new integrations
### Error handling
If middleware throws an error or times out, Telegraf calls `bot.handleError`. If it rethrows, update source closes, and then the error is printed to console and process terminates. If it does not rethrow, the error is swallowed.
Default `bot.handleError` always rethrows. You can overwrite it using `bot.catch` if you need to.
⚠️ Swallowing unknown errors might leave the process in invalid state!
In production, `systemd` or [`pm2`](https://www.npmjs.com/package/pm2) can restart your bot if it exits for any reason.
## Advanced topics
### Working with files
Supported file sources:
- `Existing file_id`
- `File path`
- `Url`
- `Buffer`
- `ReadStream`
Also, you can provide an optional name of a file as `filename` when you send the file.
<!-- global bot, fs -->
```js
bot.on('message', async (ctx) => {
// resend existing file by file_id
await ctx.replyWithSticker('123123jkbhj6b')
// send file
await ctx.replyWithVideo(Input.fromLocalFile('/path/to/video.mp4'))
// send stream
await ctx.replyWithVideo(
Input.fromReadableStream(fs.createReadStream('/path/to/video.mp4'))
)
// send buffer
await ctx.replyWithVoice(Input.fromBuffer(Buffer.alloc()))
// send url via Telegram server
await ctx.replyWithPhoto(Input.fromURL('https://picsum.photos/200/300/'))
// pipe url content
await ctx.replyWithPhoto(
Input.fromURLStream('https://picsum.photos/200/300/?random', 'kitten.jpg')
)
})
```
### Middleware
In addition to `ctx: Context`, each middleware receives `next: () => Promise<void>`.
As in Koa and some other middleware-based libraries,
`await next()` will call next middleware and wait for it to finish:
```TS
import { Telegraf } from 'telegraf';
import { message } from 'telegraf/filters';
const bot = new Telegraf(process.env.BOT_TOKEN);
bot.use(async (ctx, next) => {
console.time(`Processing update ${ctx.update.update_id}`);
await next() // runs next middleware
// runs after next middleware finishes
console.timeEnd(`Processing update ${ctx.update.update_id}`);
})
bot.on(message('text'), (ctx) => ctx.reply('Hello World'));
bot.launch();
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));
```
With this simple ability, you can:
- extract information from updates and then `await next()` to avoid disrupting other middleware,
- like [`Composer`] and [`Router`], `await next()` for updates you don't wish to handle,
- like [`session`] and [`Scenes`], [extend the context](#extending-context) by mutating `ctx` before `await next()`,
- [intercept API calls](https://github.com/telegraf/telegraf/discussions/1267#discussioncomment-254525),
- reuse [other people's code](https://www.npmjs.com/search?q=telegraf-),
- do whatever **you** come up with!
[`Telegraf`]: https://telegraf.js.org/classes/Telegraf-1.html
[`Composer`]: https://telegraf.js.org/classes/Composer.html
[`Context`]: https://telegraf.js.org/classes/Context.html
[`Router`]: https://telegraf.js.org/classes/Router.html
[`session`]: https://telegraf.js.org/modules.html#session
[`Scenes`]: https://telegraf.js.org/modules/Scenes.html
### Usage with TypeScript
Telegraf is written in TypeScript and therefore ships with declaration files for the entire library.
Moreover, it includes types for the complete Telegram API via the [`typegram`](https://github.com/KnorpelSenf/typegram) package.
While most types of Telegraf's API surface are self-explanatory, there's some notable things to keep in mind.
#### Extending `Context`
The exact shape of `ctx` can vary based on the installed middleware.
Some custom middleware might register properties on the context object that Telegraf is not aware of.
Consequently, you can change the type of `ctx` to fit your needs in order for you to have proper TypeScript types for your data.
This is done through Generics:
```ts
import { Context, Telegraf } from 'telegraf'
// Define your own context type
interface MyContext extends Context {
myProp?: string
myOtherProp?: number
}
// Create your bot and tell it about your context type
const bot = new Telegraf<MyContext>('SECRET TOKEN')
// Register middleware and launch your bot as usual
bot.use((ctx, next) => {
// Yay, `myProp` is now available here as `string | undefined`!
ctx.myProp = ctx.chat?.first_name?.toUpperCase()
return next()
})
// ...
```

1
node_modules/telegraf/filters.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './typings/filters'

1
node_modules/telegraf/filters.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/filters')

1
node_modules/telegraf/format.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './typings/format'

1
node_modules/telegraf/format.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/format')

1
node_modules/telegraf/future.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './typings/future'

1
node_modules/telegraf/future.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/future')

101
node_modules/telegraf/lib/button.js generated vendored Normal file
View File

@@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.webApp = exports.login = exports.pay = exports.game = exports.switchToCurrentChat = exports.switchToChat = exports.callback = exports.url = exports.channelRequest = exports.groupRequest = exports.botRequest = exports.userRequest = exports.pollRequest = exports.locationRequest = exports.contactRequest = exports.text = void 0;
function text(text, hide = false) {
return { text, hide };
}
exports.text = text;
function contactRequest(text, hide = false) {
return { text, request_contact: true, hide };
}
exports.contactRequest = contactRequest;
function locationRequest(text, hide = false) {
return { text, request_location: true, hide };
}
exports.locationRequest = locationRequest;
function pollRequest(text, type, hide = false) {
return { text, request_poll: { type }, hide };
}
exports.pollRequest = pollRequest;
function userRequest(text,
/** Must fit in a signed 32 bit int */
request_id, extra, hide = false) {
return {
text,
request_users: { request_id, ...extra },
hide,
};
}
exports.userRequest = userRequest;
function botRequest(text,
/** Must fit in a signed 32 bit int */
request_id, extra, hide = false) {
return {
text,
request_users: { request_id, user_is_bot: true, ...extra },
hide,
};
}
exports.botRequest = botRequest;
function groupRequest(text,
/** Must fit in a signed 32 bit int */
request_id, extra, hide = false) {
return {
text,
request_chat: { request_id, chat_is_channel: false, ...extra },
hide,
};
}
exports.groupRequest = groupRequest;
function channelRequest(text,
/** Must fit in a signed 32 bit int */
request_id, extra, hide = false) {
return {
text,
request_chat: { request_id, chat_is_channel: true, ...extra },
hide,
};
}
exports.channelRequest = channelRequest;
function url(text, url, hide = false) {
return { text, url, hide };
}
exports.url = url;
function callback(text, data, hide = false) {
return { text, callback_data: data, hide };
}
exports.callback = callback;
function switchToChat(text, value, hide = false) {
return { text, switch_inline_query: value, hide };
}
exports.switchToChat = switchToChat;
function switchToCurrentChat(text, value, hide = false) {
return { text, switch_inline_query_current_chat: value, hide };
}
exports.switchToCurrentChat = switchToCurrentChat;
function game(text, hide = false) {
return { text, callback_game: {}, hide };
}
exports.game = game;
function pay(text, hide = false) {
return { text, pay: true, hide };
}
exports.pay = pay;
function login(text, url, opts = {}, hide = false) {
return {
text,
login_url: { ...opts, url },
hide,
};
}
exports.login = login;
function webApp(text, url, hide = false
// works as both InlineKeyboardButton and KeyboardButton
) {
return {
text,
web_app: { url },
hide,
};
}
exports.webApp = webApp;

105
node_modules/telegraf/lib/cli.mjs generated vendored Executable file
View File

@@ -0,0 +1,105 @@
#!/usr/bin/env node
import d from 'debug';
import parse from 'mri';
import path from 'path';
import { Telegraf } from './index.js';
const debug = d('telegraf:cli');
const helpMsg = `Usage: telegraf [opts] <bot-file>
-t Bot token [$BOT_TOKEN]
-d Webhook domain [$BOT_DOMAIN]
-H Webhook host [0.0.0.0]
-p Webhook port [$PORT or 3000]
-l Enable logs
-h Show this help message
-m Bot API method to run directly
-D Data to pass to the Bot API method`;
const help = () => console.log(helpMsg);
/**
* Runs the cli program and returns exit code
*/
export async function main(argv, env = {}) {
const args = parse(argv, {
alias: {
// string params, all optional
t: 'token',
d: 'domain',
m: 'method',
D: 'data',
// defaults exist
H: 'host',
p: 'port',
// boolean params
l: 'logs',
h: 'help',
},
boolean: ['h', 'l'],
default: {
H: '0.0.0.0',
p: env.PORT || '3000',
},
});
if (args.help) {
help();
return 0;
}
const token = args.token || env.BOT_TOKEN;
const domain = args.domain || env.BOT_DOMAIN;
if (!token) {
console.error('Please supply Bot Token');
help();
return 1;
}
const bot = new Telegraf(token);
if (args.method) {
const method = args.method;
console.log(await bot.telegram.callApi(method, JSON.parse(args.data || '{}')));
return 0;
}
let [, , file] = args._;
if (!file) {
try {
const packageJson = (await import(path.resolve(process.cwd(), 'package.json')));
file = packageJson.main || 'index.js';
// eslint-disable-next-line no-empty
}
catch (err) { }
}
if (!file) {
console.error('Please supply a bot handler file.\n');
help();
return 2;
}
if (file[0] !== '/')
file = path.resolve(process.cwd(), file);
try {
if (args.logs)
d.enable('telegraf:*');
const mod = await import(file);
const botHandler = mod.botHandler || mod.default;
const httpHandler = mod.httpHandler;
const tlsOptions = mod.tlsOptions;
const config = {};
if (domain) {
config.webhook = {
domain,
host: args.host,
port: Number(args.port),
tlsOptions,
cb: httpHandler,
};
}
bot.use(botHandler);
debug(`Starting module ${file}`);
await bot.launch(config);
}
catch (err) {
console.error(`Error launching bot from ${file}`, err === null || err === void 0 ? void 0 : err.stack);
return 3;
}
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));
return 0;
}
process.exitCode = await main(process.argv, process.env);

582
node_modules/telegraf/lib/composer.js generated vendored Normal file
View File

@@ -0,0 +1,582 @@
"use strict";
/** @format */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Composer = void 0;
const context_1 = __importDefault(require("./context"));
const filters_1 = require("./filters");
const args_1 = require("./core/helpers/args");
function always(x) {
return () => x;
}
const anoop = always(Promise.resolve());
class Composer {
constructor(...fns) {
this.handler = Composer.compose(fns);
}
/**
* Registers a middleware.
*/
use(...fns) {
this.handler = Composer.compose([this.handler, ...fns]);
return this;
}
/**
* Registers middleware for handling updates
* matching given type guard function.
* @deprecated use `Composer::on`
*/
guard(guardFn, ...fns) {
return this.use(Composer.guard(guardFn, ...fns));
}
on(filters, ...fns) {
// @ts-expect-error This should get resolved when the overloads are removed in v5
return this.use(Composer.on(filters, ...fns));
}
/**
* Registers middleware for handling matching text messages.
*/
hears(triggers, ...fns) {
return this.use(Composer.hears(triggers, ...fns));
}
/**
* Registers middleware for handling specified commands.
*/
command(command, ...fns) {
return this.use(Composer.command(command, ...fns));
}
/**
* Registers middleware for handling matching callback queries.
*/
action(triggers, ...fns) {
return this.use(Composer.action(triggers, ...fns));
}
/**
* Registers middleware for handling matching inline queries.
*/
inlineQuery(triggers, ...fns) {
return this.use(Composer.inlineQuery(triggers, ...fns));
}
/**
* Registers middleware for handling game queries
*/
gameQuery(...fns) {
return this.use(Composer.gameQuery(...fns));
}
reaction(reaction, ...fns) {
return this.use(Composer.reaction(reaction, ...fns));
}
/**
* Registers middleware for dropping matching updates.
*/
drop(predicate) {
return this.use(Composer.drop(predicate));
}
/** @deprecated use `Composer::drop` */
filter(predicate) {
return this.use(Composer.filter(predicate));
}
entity(predicate, ...fns) {
return this.use(Composer.entity(predicate, ...fns));
}
email(email, ...fns) {
return this.use(Composer.email(email, ...fns));
}
url(url, ...fns) {
return this.use(Composer.url(url, ...fns));
}
textLink(link, ...fns) {
return this.use(Composer.textLink(link, ...fns));
}
textMention(mention, ...fns) {
return this.use(Composer.textMention(mention, ...fns));
}
mention(mention, ...fns) {
return this.use(Composer.mention(mention, ...fns));
}
phone(number, ...fns) {
return this.use(Composer.phone(number, ...fns));
}
hashtag(hashtag, ...fns) {
return this.use(Composer.hashtag(hashtag, ...fns));
}
cashtag(cashtag, ...fns) {
return this.use(Composer.cashtag(cashtag, ...fns));
}
spoiler(text, ...fns) {
return this.use(Composer.spoiler(text, ...fns));
}
/**
* Registers a middleware for handling /start
*/
start(...fns) {
const handler = Composer.compose(fns);
return this.command('start', (ctx, next) => handler(Object.assign(ctx, { startPayload: ctx.payload }), next));
}
/**
* Registers a middleware for handling /help
*/
help(...fns) {
return this.command('help', ...fns);
}
/**
* Registers a middleware for handling /settings
*/
settings(...fns) {
return this.command('settings', ...fns);
}
middleware() {
return this.handler;
}
static reply(...args) {
return (ctx) => ctx.reply(...args);
}
static catch(errorHandler, ...fns) {
const handler = Composer.compose(fns);
// prettier-ignore
return (ctx, next) => Promise.resolve(handler(ctx, next))
.catch((err) => errorHandler(err, ctx));
}
/**
* Generates middleware that runs in the background.
*/
static fork(middleware) {
const handler = Composer.unwrap(middleware);
return async (ctx, next) => {
await Promise.all([handler(ctx, anoop), next()]);
};
}
static tap(middleware) {
const handler = Composer.unwrap(middleware);
return (ctx, next) => Promise.resolve(handler(ctx, anoop)).then(() => next());
}
/**
* Generates middleware that gives up control to the next middleware.
*/
static passThru() {
return (ctx, next) => next();
}
static lazy(factoryFn) {
if (typeof factoryFn !== 'function') {
throw new Error('Argument must be a function');
}
return (ctx, next) => Promise.resolve(factoryFn(ctx)).then((middleware) => Composer.unwrap(middleware)(ctx, next));
}
static log(logFn = console.log) {
return (ctx, next) => {
logFn(JSON.stringify(ctx.update, null, 2));
return next();
};
}
/**
* @param trueMiddleware middleware to run if the predicate returns true
* @param falseMiddleware middleware to run if the predicate returns false
*/
static branch(predicate, trueMiddleware, falseMiddleware) {
if (typeof predicate !== 'function') {
return Composer.unwrap(predicate ? trueMiddleware : falseMiddleware);
}
return Composer.lazy((ctx) => Promise.resolve(predicate(ctx)).then((value) => value ? trueMiddleware : falseMiddleware));
}
/**
* Generates optional middleware.
* @param predicate predicate to decide on a context object whether to run the middleware
* @param fns middleware to run if the predicate returns true
*/
static optional(predicate, ...fns) {
return Composer.branch(predicate, Composer.compose(fns), Composer.passThru());
}
/** @deprecated use `Composer.drop` */
static filter(predicate) {
return Composer.branch(predicate, Composer.passThru(), anoop);
}
/**
* Generates middleware for dropping matching updates.
*/
static drop(predicate) {
return Composer.branch(predicate, anoop, Composer.passThru());
}
static dispatch(routeFn, handlers) {
return Composer.lazy((ctx) => Promise.resolve(routeFn(ctx)).then((value) => handlers[value]));
}
// EXPLANATION FOR THE ts-expect-error ANNOTATIONS
// The annotations around function invocations with `...fns` are there
// whenever we perform validation logic that the flow analysis of TypeScript
// cannot comprehend. We always make sure that the middleware functions are
// only invoked with properly constrained context objects, but this cannot be
// determined automatically.
/**
* Generates optional middleware based on a predicate that only operates on `ctx.update`.
*
* Example:
* ```ts
* import { Composer, Update } from 'telegraf'
*
* const predicate = (u): u is Update.MessageUpdate => 'message' in u
* const middleware = Composer.guard(predicate, (ctx) => {
* const message = ctx.update.message
* })
* ```
*
* Note that `Composer.on('message')` is preferred over this.
*
* @param guardFn predicate to decide whether to run the middleware based on the `ctx.update` object
* @param fns middleware to run if the predicate returns true
* @see `Composer.optional` for a more generic version of this method that allows the predicate to operate on `ctx` itself
* @deprecated use `Composer.on`
*/
static guard(guardFn, ...fns) {
return Composer.optional((ctx) => guardFn(ctx.update),
// @ts-expect-error see explanation above
...fns);
}
static on(updateType, ...fns) {
const filters = Array.isArray(updateType) ? updateType : [updateType];
const predicate = (update) => {
for (const filter of filters) {
if (
// TODO: this should change to === 'function' once TS bug is fixed
// https://github.com/microsoft/TypeScript/pull/51502
typeof filter !== 'string'
? // filter is a type guard
filter(update)
: // check if filter is the update type
filter in update ||
// check if filter is the msg type
// TODO: remove in v5!
('message' in update && filter in update.message)) {
return true;
}
}
return false;
};
return Composer.optional((ctx) => predicate(ctx.update), ...fns);
}
static entity(predicate, ...fns) {
if (typeof predicate !== 'function') {
const entityTypes = normaliseTextArguments(predicate);
return Composer.entity(({ type }) => entityTypes.includes(type), ...fns);
}
return Composer.optional((ctx) => {
var _a;
const msg = (_a = ctx.message) !== null && _a !== void 0 ? _a : ctx.channelPost;
if (msg === undefined) {
return false;
}
const text = getText(msg);
const entities = getEntities(msg);
if (text === undefined)
return false;
return entities.some((entity) => predicate(entity, text.substring(entity.offset, entity.offset + entity.length), ctx));
},
// @ts-expect-error see explanation above
...fns);
}
static entityText(entityType, predicate, ...fns) {
if (fns.length === 0) {
// prettier-ignore
return Array.isArray(predicate)
// @ts-expect-error predicate is really the middleware
? Composer.entity(entityType, ...predicate)
// @ts-expect-error predicate is really the middleware
: Composer.entity(entityType, predicate);
}
const triggers = normaliseTriggers(predicate);
return Composer.entity(({ type }, value, ctx) => {
if (type !== entityType) {
return false;
}
for (const trigger of triggers) {
// @ts-expect-error define so far unknown property `match`
if ((ctx.match = trigger(value, ctx))) {
return true;
}
}
return false;
},
// @ts-expect-error see explanation above
...fns);
}
static email(email, ...fns) {
return Composer.entityText('email', email, ...fns);
}
static phone(number, ...fns) {
return Composer.entityText('phone_number', number, ...fns);
}
static url(url, ...fns) {
return Composer.entityText('url', url, ...fns);
}
static textLink(link, ...fns) {
return Composer.entityText('text_link', link, ...fns);
}
static textMention(mention, ...fns) {
return Composer.entityText('text_mention', mention, ...fns);
}
static mention(mention, ...fns) {
return Composer.entityText('mention', normaliseTextArguments(mention, '@'), ...fns);
}
static hashtag(hashtag, ...fns) {
return Composer.entityText('hashtag', normaliseTextArguments(hashtag, '#'), ...fns);
}
static cashtag(cashtag, ...fns) {
return Composer.entityText('cashtag', normaliseTextArguments(cashtag, '$'), ...fns);
}
static spoiler(text, ...fns) {
return Composer.entityText('spoiler', text, ...fns);
}
static match(triggers, ...fns) {
const handler = Composer.compose(fns);
return (ctx, next) => {
var _a, _b, _c, _d;
const text = (_c = (_b = (_a = getText(ctx.message)) !== null && _a !== void 0 ? _a : getText(ctx.channelPost)) !== null && _b !== void 0 ? _b : getText(ctx.callbackQuery)) !== null && _c !== void 0 ? _c : (_d = ctx.inlineQuery) === null || _d === void 0 ? void 0 : _d.query;
if (text === undefined)
return next();
for (const trigger of triggers) {
const match = trigger(text, ctx);
if (match)
return handler(Object.assign(ctx, { match }), next);
}
return next();
};
}
/**
* Generates middleware for handling matching text messages.
*/
static hears(triggers, ...fns) {
return Composer.on('text', Composer.match(normaliseTriggers(triggers), ...fns));
}
/**
* Generates middleware for handling specified commands.
*/
static command(command, ...fns) {
if (fns.length === 0)
// @ts-expect-error command is really the middleware
return Composer.entity('bot_command', command);
const triggers = normaliseTriggers(command);
const filter = (0, filters_1.message)('text');
const handler = Composer.compose(fns);
return Composer.on(filter, (ctx, next) => {
const { entities } = ctx.message;
const cmdEntity = entities === null || entities === void 0 ? void 0 : entities[0];
if ((cmdEntity === null || cmdEntity === void 0 ? void 0 : cmdEntity.type) !== 'bot_command')
return next();
if (cmdEntity.offset > 0)
return next();
const len = cmdEntity.length;
const text = ctx.message.text;
const [cmdPart, to] = text.slice(0, len).split('@');
if (!cmdPart)
return next();
// always check for bot's own username case-insensitively
if (to && to.toLowerCase() !== ctx.me.toLowerCase())
return next();
const command = cmdPart.slice(1);
for (const trigger of triggers) {
const match = trigger(command, ctx);
if (match) {
const payloadOffset = len + 1;
const payload = text.slice(payloadOffset);
const c = Object.assign(ctx, { match, command, payload, args: [] });
let _args = undefined;
// using defineProperty only to make parsing lazy on access
Object.defineProperty(c, 'args', {
enumerable: true,
configurable: true,
get() {
if (_args != null)
return _args;
// once parsed, cache and don't parse again on every access
return (_args = (0, args_1.argsParser)(payload, entities, payloadOffset));
},
set(args) {
_args = args;
},
});
return handler(c, next);
}
}
return next();
});
}
/**
* Generates middleware for handling matching callback queries.
*/
static action(triggers, ...fns) {
return Composer.on('callback_query', Composer.match(normaliseTriggers(triggers), ...fns));
}
/**
* Generates middleware for handling matching inline queries.
*/
static inlineQuery(triggers, ...fns) {
return Composer.on('inline_query', Composer.match(normaliseTriggers(triggers), ...fns));
}
static reaction(reaction, ...fns) {
const reactions = Array.isArray(reaction) ? reaction : [reaction];
const handler = Composer.compose(fns);
return Composer.on('message_reaction', (ctx, next) => {
const match = reactions.find((r) => typeof r === 'string' && r.startsWith('-')
? ctx.reactions.removed.has(r.slice(1))
: ctx.reactions.added.has(r));
if (match)
return handler(Object.assign(ctx, { match }), next);
return next();
});
}
/**
* Generates middleware responding only to specified users.
*/
static acl(userId, ...fns) {
if (typeof userId === 'function') {
return Composer.optional(userId, ...fns);
}
const allowed = Array.isArray(userId) ? userId : [userId];
// prettier-ignore
return Composer.optional((ctx) => !ctx.from || allowed.includes(ctx.from.id), ...fns);
}
static memberStatus(status, ...fns) {
const statuses = Array.isArray(status) ? status : [status];
return Composer.optional(async (ctx) => {
if (ctx.message === undefined)
return false;
const member = await ctx.getChatMember(ctx.message.from.id);
return statuses.includes(member.status);
}, ...fns);
}
/**
* Generates middleware responding only to chat admins and chat creator.
*/
static admin(...fns) {
return Composer.memberStatus(['administrator', 'creator'], ...fns);
}
/**
* Generates middleware responding only to chat creator.
*/
static creator(...fns) {
return Composer.memberStatus('creator', ...fns);
}
/**
* Generates middleware running only in specified chat types.
*/
static chatType(type, ...fns) {
const types = Array.isArray(type) ? type : [type];
return Composer.optional((ctx) => {
const chat = ctx.chat;
return chat !== undefined && types.includes(chat.type);
}, ...fns);
}
/**
* Generates middleware running only in private chats.
*/
static privateChat(...fns) {
return Composer.chatType('private', ...fns);
}
/**
* Generates middleware running only in groups and supergroups.
*/
static groupChat(...fns) {
return Composer.chatType(['group', 'supergroup'], ...fns);
}
/**
* Generates middleware for handling game queries.
*/
static gameQuery(...fns) {
return Composer.guard((0, filters_1.callbackQuery)('game_short_name'), ...fns);
}
static unwrap(handler) {
if (!handler) {
throw new Error('Handler is undefined');
}
return 'middleware' in handler ? handler.middleware() : handler;
}
static compose(middlewares) {
if (!Array.isArray(middlewares)) {
throw new Error('Middlewares must be an array');
}
if (middlewares.length === 0) {
return Composer.passThru();
}
if (middlewares.length === 1) {
// Quite literally asserted in the above condition
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return Composer.unwrap(middlewares[0]);
}
return (ctx, next) => {
let index = -1;
return execute(0, ctx);
async function execute(i, context) {
var _a;
if (!(context instanceof context_1.default)) {
throw new Error('next(ctx) called with invalid context');
}
if (i <= index) {
throw new Error('next() called multiple times');
}
index = i;
const handler = Composer.unwrap((_a = middlewares[i]) !== null && _a !== void 0 ? _a : next);
await handler(context, async (ctx = context) => {
await execute(i + 1, ctx);
});
}
};
}
}
exports.Composer = Composer;
/**
* Generates middleware for handling provided update types.
* @deprecated use `Composer.on` instead
*/
Composer.mount = Composer.on;
function escapeRegExp(s) {
// $& means the whole matched string
return s.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
}
function normaliseTriggers(triggers) {
if (!Array.isArray(triggers))
triggers = [triggers];
return triggers.map((trigger) => {
if (!trigger)
throw new Error('Invalid trigger');
if (typeof trigger === 'function')
return trigger;
if (trigger instanceof RegExp)
return (value = '') => {
trigger.lastIndex = 0;
return trigger.exec(value);
};
const regex = new RegExp(`^${escapeRegExp(trigger)}$`);
return (value) => regex.exec(value);
});
}
function getEntities(msg) {
var _a, _b;
if (msg == null)
return [];
if ('caption_entities' in msg)
return (_a = msg.caption_entities) !== null && _a !== void 0 ? _a : [];
if ('entities' in msg)
return (_b = msg.entities) !== null && _b !== void 0 ? _b : [];
return [];
}
function getText(msg) {
if (msg == null)
return undefined;
if ('caption' in msg)
return msg.caption;
if ('text' in msg)
return msg.text;
if ('data' in msg)
return msg.data;
if ('game_short_name' in msg)
return msg.game_short_name;
return undefined;
}
function normaliseTextArguments(argument, prefix = '') {
const args = Array.isArray(argument) ? argument : [argument];
// prettier-ignore
return args
.filter(Boolean)
.map((arg) => prefix && typeof arg === 'string' && !arg.startsWith(prefix) ? `${prefix}${arg}` : arg);
}
exports.default = Composer;

1219
node_modules/telegraf/lib/context.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

58
node_modules/telegraf/lib/core/helpers/args.js generated vendored Normal file
View File

@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.argsParser = void 0;
const SINGLE_QUOTE = "'";
const DOUBLE_QUOTE = '"';
function argsParser(str, entities = [], entityOffset = 0) {
const mentions = {};
for (const entity of entities) // extract all text_mentions into an { offset: length } map
if (entity.type === 'text_mention' || entity.type === 'text_link')
mentions[entity.offset - entityOffset] = entity.length;
const args = [];
let done = 0;
let inside = undefined;
let buf = '';
function flush(to) {
if (done !== to)
args.push(buf + str.slice(done, to)), (inside = undefined);
buf = '';
done = to + 1;
}
for (let i = 0; i < str.length; i++) {
const char = str[i];
// quick lookup length of mention starting at i
const mention = mentions[i];
if (mention) {
// if we're inside a quote, eagerly flush existing state
flush(i);
// this also consumes current index, so decrement
done--;
// fast forward to end of mention
i += mention;
flush(i);
}
else if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE)
if (inside)
if (inside === char)
flush(i);
else
continue;
else
flush(i), (inside = char);
else if (char === ' ')
if (inside)
continue;
else
flush(i);
else if (char === '\n')
flush(i);
else if (char === '\\')
(buf += str.slice(done, i)), (done = ++i); // skip parsing the next char
else
continue;
}
if (done < str.length)
flush(str.length);
return args;
}
exports.argsParser = argsParser;

56
node_modules/telegraf/lib/core/helpers/check.js generated vendored Normal file
View File

@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.is2D = exports.hasPropType = exports.hasProp = void 0;
/**
* Checks if a given object has a property with a given name.
*
* Example invocation:
* ```js
* let obj = { 'foo': 'bar', 'baz': () => {} }
* hasProp(obj, 'foo') // true
* hasProp(obj, 'baz') // true
* hasProp(obj, 'abc') // false
* ```
*
* @param obj An object to test
* @param prop The name of the property
*/
function hasProp(obj, prop) {
return obj !== undefined && prop in obj;
}
exports.hasProp = hasProp;
/**
* Checks if a given object has a property with a given name.
* Furthermore performs a `typeof` check on the property if it exists.
*
* Example invocation:
* ```js
* let obj = { 'foo': 'bar', 'baz': () => {} }
* hasPropType(obj, 'foo', 'string') // true
* hasPropType(obj, 'baz', 'function') // true
* hasPropType(obj, 'abc', 'number') // false
* ```
*
* @param obj An object to test
* @param prop The name of the property
* @param type The type the property is expected to have
*/
function hasPropType(obj, prop, type) {
return hasProp(obj, prop) && type === typeof obj[prop];
}
exports.hasPropType = hasPropType;
/**
* Checks if the supplied array has two dimensions or not.
*
* Example invocations:
* is2D([]) // false
* is2D([[]]) // true
* is2D([[], []]) // true
* is2D([42]) // false
*
* @param arr an array with one or two dimensions
*/
function is2D(arr) {
return Array.isArray(arr[0]);
}
exports.is2D = is2D;

17
node_modules/telegraf/lib/core/helpers/compact.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compactOptions = void 0;
function compactOptions(options) {
if (!options) {
return options;
}
const compacted = {};
for (const key in options)
if (
// todo(mkr): replace with Object.hasOwn in v5 (Node 16+)
Object.prototype.hasOwnProperty.call(options, key) &&
options[key] !== undefined)
compacted[key] = options[key];
return compacted;
}
exports.compactOptions = compactOptions;

13
node_modules/telegraf/lib/core/helpers/deunionize.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.deunionize = void 0;
/**
* Expose properties from all union variants.
* @deprectated
* @see https://github.com/telegraf/telegraf/issues/1388#issuecomment-791573609
* @see https://millsp.github.io/ts-toolbelt/modules/union_strict.html
*/
function deunionize(t) {
return t;
}
exports.deunionize = deunionize;

91
node_modules/telegraf/lib/core/helpers/formatting.js generated vendored Normal file
View File

@@ -0,0 +1,91 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.linkOrMention = exports.createFmt = exports.join = exports.FmtString = void 0;
const util_1 = require("./util");
class FmtString {
constructor(text, entities) {
this.text = text;
if (entities) {
this.entities = entities;
// force parse_mode to undefined if entities are present
this.parse_mode = undefined;
}
}
static normalise(content) {
if (content instanceof FmtString)
return content;
return new FmtString(String(content));
}
}
exports.FmtString = FmtString;
const isArray = Array.isArray;
/** Given a base FmtString and something to append to it, mutates the base */
const _add = (base, next) => {
var _a;
const len = base.text.length;
if (next instanceof FmtString) {
base.text = `${base.text}${next.text}`;
// next.entities could be undefined and condition will fail
for (let i = 0; i < (((_a = next.entities) === null || _a === void 0 ? void 0 : _a.length) || 0); i++) {
// because of the above condition, next.entities[i] cannot be undefined
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const entity = next.entities[i];
// base.entities is ensured by caller
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
base.entities.push({ ...entity, offset: entity.offset + len });
}
}
else
base.text = `${base.text}${next}`;
};
/**
* Given an `Iterable<FmtString | string | Any>` and a separator, flattens the list into a single FmtString.
* Analogous to Array#join -> string, but for FmtString
*/
const join = (fragments, separator) => {
const result = new FmtString('');
// ensure entities array so loop doesn't need to check
result.entities = [];
const iter = fragments[Symbol.iterator]();
let curr = iter.next();
while (!curr.done) {
_add(result, curr.value);
curr = iter.next();
if (separator && !curr.done)
_add(result, separator);
}
// set parse_mode: undefined if entities are present
if (result.entities.length)
result.parse_mode = undefined;
// remove entities array if not relevant
else
delete result.entities;
return result;
};
exports.join = join;
/** Internal constructor for all fmt helpers */
function createFmt(kind, opts) {
return function fmt(parts, ...items) {
var _a;
parts = isArray(parts) ? parts : [parts];
const result = (0, exports.join)((0, util_1.zip)(parts, items));
if (kind) {
(_a = result.entities) !== null && _a !== void 0 ? _a : (result.entities = []);
result.entities.unshift({
type: kind,
offset: 0,
length: result.text.length,
...opts,
});
result.parse_mode = undefined;
}
return result;
};
}
exports.createFmt = createFmt;
const linkOrMention = (content, data) => {
const { text, entities = [] } = FmtString.normalise(content);
entities.unshift(Object.assign(data, { offset: 0, length: text.length }));
return new FmtString(text, entities);
};
exports.linkOrMention = linkOrMention;

50
node_modules/telegraf/lib/core/helpers/util.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.indexed = exports.zip = exports.fmtCaption = exports.env = void 0;
exports.env = process.env;
function fmtCaption(extra) {
if (!extra)
return;
const caption = extra.caption;
if (!caption || typeof caption === 'string')
return extra;
const { text, entities } = caption;
return {
...extra,
caption: text,
...(entities && {
caption_entities: entities,
parse_mode: undefined,
}),
};
}
exports.fmtCaption = fmtCaption;
function* zip(xs, ys) {
const x = xs[Symbol.iterator]();
const y = ys[Symbol.iterator]();
let x1 = x.next();
let y1 = y.next();
while (!x1.done) {
yield x1.value;
if (!y1.done)
yield y1.value;
x1 = x.next();
y1 = y.next();
}
while (!y1.done) {
yield y1.value;
y1 = y.next();
}
}
exports.zip = zip;
function indexed(target, indexer) {
return new Proxy(target, {
get: function (target, prop, receiver) {
if ((typeof prop === 'string' || typeof prop === 'number') &&
!isNaN(+prop))
return indexer.call(target, +prop);
return Reflect.get(target, prop, receiver);
},
});
}
exports.indexed = indexed;

320
node_modules/telegraf/lib/core/network/client.js generated vendored Normal file
View File

@@ -0,0 +1,320 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint @typescript-eslint/restrict-template-expressions: [ "error", { "allowNumber": true, "allowBoolean": true } ] */
const crypto = __importStar(require("crypto"));
const fs = __importStar(require("fs"));
const promises_1 = require("fs/promises");
const https = __importStar(require("https"));
const path = __importStar(require("path"));
const node_fetch_1 = __importDefault(require("node-fetch"));
const check_1 = require("../helpers/check");
const compact_1 = require("../helpers/compact");
const multipart_stream_1 = __importDefault(require("./multipart-stream"));
const error_1 = __importDefault(require("./error"));
const url_1 = require("url");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const debug = require('debug')('telegraf:client');
const { isStream } = multipart_stream_1.default;
const WEBHOOK_REPLY_METHOD_ALLOWLIST = new Set([
'answerCallbackQuery',
'answerInlineQuery',
'deleteMessage',
'leaveChat',
'sendChatAction',
]);
const DEFAULT_EXTENSIONS = {
audio: 'mp3',
photo: 'jpg',
sticker: 'webp',
video: 'mp4',
animation: 'mp4',
video_note: 'mp4',
voice: 'ogg',
};
const DEFAULT_OPTIONS = {
apiRoot: 'https://api.telegram.org',
apiMode: 'bot',
webhookReply: true,
agent: new https.Agent({
keepAlive: true,
keepAliveMsecs: 10000,
}),
attachmentAgent: undefined,
testEnv: false,
};
function includesMedia(payload) {
return Object.entries(payload).some(([key, value]) => {
if (key === 'link_preview_options')
return false;
if (Array.isArray(value)) {
return value.some(({ media }) => media && typeof media === 'object' && (media.source || media.url));
}
return (value &&
typeof value === 'object' &&
(((0, check_1.hasProp)(value, 'source') && value.source) ||
((0, check_1.hasProp)(value, 'url') && value.url) ||
((0, check_1.hasPropType)(value, 'media', 'object') &&
(((0, check_1.hasProp)(value.media, 'source') && value.media.source) ||
((0, check_1.hasProp)(value.media, 'url') && value.media.url)))));
});
}
function replacer(_, value) {
if (value == null)
return undefined;
return value;
}
function buildJSONConfig(payload) {
return Promise.resolve({
method: 'POST',
compress: true,
headers: { 'content-type': 'application/json', connection: 'keep-alive' },
body: JSON.stringify(payload, replacer),
});
}
const FORM_DATA_JSON_FIELDS = [
'results',
'reply_markup',
'mask_position',
'shipping_options',
'errors',
];
async function buildFormDataConfig(payload, agent) {
for (const field of FORM_DATA_JSON_FIELDS) {
if ((0, check_1.hasProp)(payload, field) && typeof payload[field] !== 'string') {
payload[field] = JSON.stringify(payload[field]);
}
}
const boundary = crypto.randomBytes(32).toString('hex');
const formData = new multipart_stream_1.default(boundary);
await Promise.all(Object.keys(payload).map((key) =>
// @ts-expect-error payload[key] can obviously index payload, but TS doesn't trust us
attachFormValue(formData, key, payload[key], agent)));
return {
method: 'POST',
compress: true,
headers: {
'content-type': `multipart/form-data; boundary=${boundary}`,
connection: 'keep-alive',
},
body: formData,
};
}
async function attachFormValue(form, id, value, agent) {
if (value == null) {
return;
}
if (typeof value === 'string' ||
typeof value === 'boolean' ||
typeof value === 'number') {
form.addPart({
headers: { 'content-disposition': `form-data; name="${id}"` },
body: `${value}`,
});
return;
}
if (id === 'thumb' || id === 'thumbnail') {
const attachmentId = crypto.randomBytes(16).toString('hex');
await attachFormMedia(form, value, attachmentId, agent);
return form.addPart({
headers: { 'content-disposition': `form-data; name="${id}"` },
body: `attach://${attachmentId}`,
});
}
if (Array.isArray(value)) {
const items = await Promise.all(value.map(async (item) => {
var _a;
if (typeof item.media !== 'object') {
return await Promise.resolve(item);
}
const attachmentId = crypto.randomBytes(16).toString('hex');
await attachFormMedia(form, item.media, attachmentId, agent);
const thumb = (_a = item.thumb) !== null && _a !== void 0 ? _a : item.thumbnail;
if (typeof thumb === 'object') {
const thumbAttachmentId = crypto.randomBytes(16).toString('hex');
await attachFormMedia(form, thumb, thumbAttachmentId, agent);
return {
...item,
media: `attach://${attachmentId}`,
thumbnail: `attach://${thumbAttachmentId}`,
};
}
return { ...item, media: `attach://${attachmentId}` };
}));
return form.addPart({
headers: { 'content-disposition': `form-data; name="${id}"` },
body: JSON.stringify(items),
});
}
if (value &&
typeof value === 'object' &&
(0, check_1.hasProp)(value, 'media') &&
(0, check_1.hasProp)(value, 'type') &&
typeof value.media !== 'undefined' &&
typeof value.type !== 'undefined') {
const attachmentId = crypto.randomBytes(16).toString('hex');
await attachFormMedia(form, value.media, attachmentId, agent);
return form.addPart({
headers: { 'content-disposition': `form-data; name="${id}"` },
body: JSON.stringify({
...value,
media: `attach://${attachmentId}`,
}),
});
}
return await attachFormMedia(form, value, id, agent);
}
async function attachFormMedia(form, media, id, agent) {
var _a, _b, _c;
let fileName = (_a = media.filename) !== null && _a !== void 0 ? _a : `${id}.${(_b = DEFAULT_EXTENSIONS[id]) !== null && _b !== void 0 ? _b : 'dat'}`;
if ('url' in media && media.url !== undefined) {
const timeout = 500000; // ms
const res = await (0, node_fetch_1.default)(media.url, { agent, timeout });
return form.addPart({
headers: {
'content-disposition': `form-data; name="${id}"; filename="${fileName}"`,
},
body: res.body,
});
}
if ('source' in media && media.source) {
let mediaSource = media.source;
if (typeof media.source === 'string') {
const source = await (0, promises_1.realpath)(media.source);
if ((await (0, promises_1.stat)(source)).isFile()) {
fileName = (_c = media.filename) !== null && _c !== void 0 ? _c : path.basename(media.source);
mediaSource = await fs.createReadStream(media.source);
}
else {
throw new TypeError(`Unable to upload '${media.source}', not a file`);
}
}
if (isStream(mediaSource) || Buffer.isBuffer(mediaSource)) {
form.addPart({
headers: {
'content-disposition': `form-data; name="${id}"; filename="${fileName}"`,
},
body: mediaSource,
});
}
}
}
async function answerToWebhook(response, payload, options) {
if (!includesMedia(payload)) {
if (!response.headersSent) {
response.setHeader('content-type', 'application/json');
}
response.end(JSON.stringify(payload), 'utf-8');
return true;
}
const { headers, body } = await buildFormDataConfig(payload, options.attachmentAgent);
if (!response.headersSent) {
for (const [key, value] of Object.entries(headers)) {
response.setHeader(key, value);
}
}
await new Promise((resolve) => {
response.on('finish', resolve);
body.pipe(response);
});
return true;
}
function redactToken(error) {
error.message = error.message.replace(/\/(bot|user)(\d+):[^/]+\//, '/$1$2:[REDACTED]/');
throw error;
}
class ApiClient {
constructor(token, options, response) {
this.token = token;
this.response = response;
this.options = {
...DEFAULT_OPTIONS,
...(0, compact_1.compactOptions)(options),
};
if (this.options.apiRoot.startsWith('http://')) {
this.options.agent = undefined;
}
}
/**
* If set to `true`, first _eligible_ call will avoid performing a POST request.
* Note that such a call:
* 1. cannot report errors or return meaningful values,
* 2. resolves before bot API has a chance to process it,
* 3. prematurely confirms the update as processed.
*
* https://core.telegram.org/bots/faq#how-can-i-make-requests-in-response-to-updates
* https://github.com/telegraf/telegraf/pull/1250
*/
set webhookReply(enable) {
this.options.webhookReply = enable;
}
get webhookReply() {
return this.options.webhookReply;
}
async callApi(method, payload, { signal } = {}) {
const { token, options, response } = this;
if (options.webhookReply &&
(response === null || response === void 0 ? void 0 : response.writableEnded) === false &&
WEBHOOK_REPLY_METHOD_ALLOWLIST.has(method)) {
debug('Call via webhook', method, payload);
// @ts-expect-error using webhookReply is an optimisation that doesn't respond with normal result
// up to the user to deal with this
return await answerToWebhook(response, { method, ...payload }, options);
}
if (!token) {
throw new error_1.default({
error_code: 401,
description: 'Bot Token is required',
});
}
debug('HTTP call', method, payload);
const config = includesMedia(payload)
? await buildFormDataConfig({ method, ...payload }, options.attachmentAgent)
: await buildJSONConfig(payload);
const apiUrl = new url_1.URL(`./${options.apiMode}${token}${options.testEnv ? '/test' : ''}/${method}`, options.apiRoot);
config.agent = options.agent;
// @ts-expect-error AbortSignal shim is missing some props from Request.AbortSignal
config.signal = signal;
config.timeout = 500000; // ms
const res = await (0, node_fetch_1.default)(apiUrl, config).catch(redactToken);
if (res.status >= 500) {
const errorPayload = {
error_code: res.status,
description: res.statusText,
};
throw new error_1.default(errorPayload, { method, payload });
}
const data = await res.json();
if (!data.ok) {
debug('API call failed', data);
throw new error_1.default(data, { method, payload });
}
return data.result;
}
}
exports.default = ApiClient;

21
node_modules/telegraf/lib/core/network/error.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TelegramError = void 0;
class TelegramError extends Error {
constructor(response, on = {}) {
super(`${response.error_code}: ${response.description}`);
this.response = response;
this.on = on;
}
get code() {
return this.response.error_code;
}
get description() {
return this.response.description;
}
get parameters() {
return this.response.parameters;
}
}
exports.TelegramError = TelegramError;
exports.default = TelegramError;

View File

@@ -0,0 +1,61 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const stream = __importStar(require("stream"));
const check_1 = require("../helpers/check");
const sandwich_stream_1 = __importDefault(require("sandwich-stream"));
const CRNL = '\r\n';
class MultipartStream extends sandwich_stream_1.default {
constructor(boundary) {
super({
head: `--${boundary}${CRNL}`,
tail: `${CRNL}--${boundary}--`,
separator: `${CRNL}--${boundary}${CRNL}`,
});
}
addPart(part) {
const partStream = new stream.PassThrough();
for (const [key, header] of Object.entries(part.headers)) {
partStream.write(`${key}:${header}${CRNL}`);
}
partStream.write(CRNL);
if (MultipartStream.isStream(part.body)) {
part.body.pipe(partStream);
}
else {
partStream.end(part.body);
}
this.add(partStream);
}
static isStream(stream) {
return (typeof stream === 'object' &&
stream !== null &&
(0, check_1.hasPropType)(stream, 'pipe', 'function'));
}
}
exports.default = MultipartStream;

87
node_modules/telegraf/lib/core/network/polling.js generated vendored Normal file
View File

@@ -0,0 +1,87 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Polling = void 0;
const abort_controller_1 = __importDefault(require("abort-controller"));
const debug_1 = __importDefault(require("debug"));
const util_1 = require("util");
const error_1 = require("./error");
const debug = (0, debug_1.default)('telegraf:polling');
const wait = (0, util_1.promisify)(setTimeout);
function always(x) {
return () => x;
}
const noop = always(Promise.resolve());
class Polling {
constructor(telegram, allowedUpdates) {
this.telegram = telegram;
this.allowedUpdates = allowedUpdates;
this.abortController = new abort_controller_1.default();
this.skipOffsetSync = false;
this.offset = 0;
}
async *[Symbol.asyncIterator]() {
var _a, _b;
debug('Starting long polling');
do {
try {
const updates = await this.telegram.callApi('getUpdates', {
timeout: 50,
offset: this.offset,
allowed_updates: this.allowedUpdates,
}, this.abortController);
const last = updates[updates.length - 1];
if (last !== undefined) {
this.offset = last.update_id + 1;
}
yield updates;
}
catch (error) {
const err = error;
if (err.name === 'AbortError')
return;
if (err.name === 'FetchError' ||
(err instanceof error_1.TelegramError && err.code === 429) ||
(err instanceof error_1.TelegramError && err.code >= 500)) {
const retryAfter = (_b = (_a = err.parameters) === null || _a === void 0 ? void 0 : _a.retry_after) !== null && _b !== void 0 ? _b : 5;
debug('Failed to fetch updates, retrying after %ds.', retryAfter, err);
await wait(retryAfter * 1000);
continue;
}
if (err instanceof error_1.TelegramError &&
// Unauthorized Conflict
(err.code === 401 || err.code === 409)) {
this.skipOffsetSync = true;
throw err;
}
throw err;
}
} while (!this.abortController.signal.aborted);
}
async syncUpdateOffset() {
if (this.skipOffsetSync)
return;
debug('Syncing update offset...');
await this.telegram.callApi('getUpdates', { offset: this.offset, limit: 1 });
}
async loop(handleUpdate) {
if (this.abortController.signal.aborted)
throw new Error('Polling instances must not be reused!');
try {
for await (const updates of this)
await Promise.all(updates.map(handleUpdate));
}
finally {
debug('Long polling stopped');
// prevent instance reuse
this.stop();
await this.syncUpdateOffset().catch(noop);
}
}
stop() {
this.abortController.abort();
}
}
exports.Polling = Polling;

54
node_modules/telegraf/lib/core/network/webhook.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)('telegraf:webhook');
function generateWebhook(filter, updateHandler) {
return async (req, res, next = () => {
res.statusCode = 403;
debug('Replying with status code', res.statusCode);
res.end();
}) => {
debug('Incoming request', req.method, req.url);
if (!filter(req)) {
debug('Webhook filter failed', req.method, req.url);
return next();
}
let update;
try {
if (req.body != null) {
/* If req.body is already set, we expect it to be the parsed
request body (update object) received from Telegram
However, some libraries such as `serverless-http` set req.body to the
raw buffer, so we'll handle that additionally */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let body = req.body;
// if body is Buffer, parse it into string
if (body instanceof Buffer)
body = String(req.body);
// if body is string, parse it into object
if (typeof body === 'string')
body = JSON.parse(body);
update = body;
}
else {
let body = '';
// parse each buffer to string and append to body
for await (const chunk of req)
body += String(chunk);
// parse body to object
update = JSON.parse(body);
}
}
catch (error) {
// if any of the parsing steps fails, give up and respond with error
res.writeHead(415).end();
debug('Failed to parse request body:', error);
return;
}
return await updateHandler(update, res);
};
}
exports.default = generateWebhook;

27
node_modules/telegraf/lib/core/types/typegram.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
"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 });
// internal type provisions
__exportStar(require("@telegraf/types/api"), exports);
__exportStar(require("@telegraf/types/inline"), exports);
__exportStar(require("@telegraf/types/manage"), exports);
__exportStar(require("@telegraf/types/markup"), exports);
__exportStar(require("@telegraf/types/message"), exports);
__exportStar(require("@telegraf/types/methods"), exports);
__exportStar(require("@telegraf/types/passport"), exports);
__exportStar(require("@telegraf/types/payment"), exports);
__exportStar(require("@telegraf/types/settings"), exports);
__exportStar(require("@telegraf/types/update"), exports);

69
node_modules/telegraf/lib/filters.js generated vendored Normal file
View File

@@ -0,0 +1,69 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.allOf = exports.anyOf = exports.callbackQuery = exports.editedChannelPost = exports.channelPost = exports.editedMessage = exports.message = void 0;
const message = (...keys) => (update) => {
if (!('message' in update))
return false;
for (const key of keys) {
if (!(key in update.message))
return false;
}
return true;
};
exports.message = message;
const editedMessage = (...keys) => (update) => {
if (!('edited_message' in update))
return false;
for (const key of keys) {
if (!(key in update.edited_message))
return false;
}
return true;
};
exports.editedMessage = editedMessage;
const channelPost = (...keys) => (update) => {
if (!('channel_post' in update))
return false;
for (const key of keys) {
if (!(key in update.channel_post))
return false;
}
return true;
};
exports.channelPost = channelPost;
const editedChannelPost = (...keys) => (update) => {
if (!('edited_channel_post' in update))
return false;
for (const key of keys) {
if (!(key in update.edited_channel_post))
return false;
}
return true;
};
exports.editedChannelPost = editedChannelPost;
const callbackQuery = (...keys) => (update) => {
if (!('callback_query' in update))
return false;
for (const key of keys) {
if (!(key in update.callback_query))
return false;
}
return true;
};
exports.callbackQuery = callbackQuery;
/** Any of the provided filters must match */
const anyOf = (...filters) => (update) => {
for (const filter of filters)
if (filter(update))
return true;
return false;
};
exports.anyOf = anyOf;
/** All of the provided filters must match */
const allOf = (...filters) => (update) => {
for (const filter of filters)
if (!filter(update))
return false;
return true;
};
exports.allOf = allOf;

38
node_modules/telegraf/lib/format.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mention = exports.link = exports.pre = exports.code = exports.quote = exports.underline = exports.strikethrough = exports.spoiler = exports.italic = exports.bold = exports.fmt = exports.join = exports.FmtString = void 0;
const formatting_1 = require("./core/helpers/formatting");
Object.defineProperty(exports, "FmtString", { enumerable: true, get: function () { return formatting_1.FmtString; } });
// Nests<A, B> means the function will return A, and it can nest B
// Nests<'fmt', string> means it will nest anything
// Nests<'code', never> means it will not nest anything
// Allowing everything to nest 'fmt' is a necessary evil; it allows to indirectly nest illegal entities
// Except for 'code' and 'pre', which don't nest anything anyway, so they only deal with strings
exports.join = formatting_1.join;
exports.fmt = (0, formatting_1.createFmt)();
exports.bold = (0, formatting_1.createFmt)('bold');
exports.italic = (0, formatting_1.createFmt)('italic');
exports.spoiler = (0, formatting_1.createFmt)('spoiler');
exports.strikethrough =
//
(0, formatting_1.createFmt)('strikethrough');
exports.underline =
//
(0, formatting_1.createFmt)('underline');
exports.quote =
//
(0, formatting_1.createFmt)('blockquote');
exports.code = (0, formatting_1.createFmt)('code');
const pre = (language) => (0, formatting_1.createFmt)('pre', { language });
exports.pre = pre;
const link = (content, url) =>
//
(0, formatting_1.linkOrMention)(content, { type: 'text_link', url });
exports.link = link;
const mention = (name, user) => typeof user === 'number'
? (0, exports.link)(name, 'tg://user?id=' + user)
: (0, formatting_1.linkOrMention)(name, {
type: 'text_mention',
user,
});
exports.mention = mention;

150
node_modules/telegraf/lib/future.js generated vendored Normal file
View File

@@ -0,0 +1,150 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useNewReplies = void 0;
function makeReply(ctx, extra) {
if (ctx.msgId)
return {
// overrides in this order so user can override all properties
reply_parameters: {
message_id: ctx.msgId,
...extra === null || extra === void 0 ? void 0 : extra.reply_parameters,
},
...extra,
};
else
return extra;
}
const replyContext = {
replyWithChatAction: function () {
throw new TypeError('ctx.replyWithChatAction has been removed, use ctx.sendChatAction instead');
},
reply(text, extra) {
this.assert(this.chat, 'reply');
return this.telegram.sendMessage(this.chat.id, text, makeReply(this, extra));
},
replyWithAnimation(animation, extra) {
this.assert(this.chat, 'replyWithAnimation');
return this.telegram.sendAnimation(this.chat.id, animation, makeReply(this, extra));
},
replyWithAudio(audio, extra) {
this.assert(this.chat, 'replyWithAudio');
return this.telegram.sendAudio(this.chat.id, audio, makeReply(this, extra));
},
replyWithContact(phoneNumber, firstName, extra) {
this.assert(this.chat, 'replyWithContact');
return this.telegram.sendContact(this.chat.id, phoneNumber, firstName, makeReply(this, extra));
},
replyWithDice(extra) {
this.assert(this.chat, 'replyWithDice');
return this.telegram.sendDice(this.chat.id, makeReply(this, extra));
},
replyWithDocument(document, extra) {
this.assert(this.chat, 'replyWithDocument');
return this.telegram.sendDocument(this.chat.id, document, makeReply(this, extra));
},
replyWithGame(gameName, extra) {
this.assert(this.chat, 'replyWithGame');
return this.telegram.sendGame(this.chat.id, gameName, makeReply(this, extra));
},
replyWithHTML(html, extra) {
this.assert(this.chat, 'replyWithHTML');
return this.telegram.sendMessage(this.chat.id, html, {
parse_mode: 'HTML',
...makeReply(this, extra),
});
},
replyWithInvoice(invoice, extra) {
this.assert(this.chat, 'replyWithInvoice');
return this.telegram.sendInvoice(this.chat.id, invoice, makeReply(this, extra));
},
replyWithLocation(latitude, longitude, extra) {
this.assert(this.chat, 'replyWithLocation');
return this.telegram.sendLocation(this.chat.id, latitude, longitude, makeReply(this, extra));
},
replyWithMarkdown(markdown, extra) {
this.assert(this.chat, 'replyWithMarkdown');
return this.telegram.sendMessage(this.chat.id, markdown, {
parse_mode: 'Markdown',
...makeReply(this, extra),
});
},
replyWithMarkdownV2(markdown, extra) {
this.assert(this.chat, 'replyWithMarkdownV2');
return this.telegram.sendMessage(this.chat.id, markdown, {
parse_mode: 'MarkdownV2',
...makeReply(this, extra),
});
},
replyWithMediaGroup(media, extra) {
this.assert(this.chat, 'replyWithMediaGroup');
return this.telegram.sendMediaGroup(this.chat.id, media, makeReply(this, extra));
},
replyWithPhoto(photo, extra) {
this.assert(this.chat, 'replyWithPhoto');
return this.telegram.sendPhoto(this.chat.id, photo, makeReply(this, extra));
},
replyWithPoll(question, options, extra) {
this.assert(this.chat, 'replyWithPoll');
return this.telegram.sendPoll(this.chat.id, question, options, makeReply(this, extra));
},
replyWithQuiz(question, options, extra) {
this.assert(this.chat, 'replyWithQuiz');
return this.telegram.sendQuiz(this.chat.id, question, options, makeReply(this, extra));
},
replyWithSticker(sticker, extra) {
this.assert(this.chat, 'replyWithSticker');
return this.telegram.sendSticker(this.chat.id, sticker, makeReply(this, extra));
},
replyWithVenue(latitude, longitude, title, address, extra) {
this.assert(this.chat, 'replyWithVenue');
return this.telegram.sendVenue(this.chat.id, latitude, longitude, title, address, makeReply(this, extra));
},
replyWithVideo(video, extra) {
this.assert(this.chat, 'replyWithVideo');
return this.telegram.sendVideo(this.chat.id, video, makeReply(this, extra));
},
replyWithVideoNote(videoNote, extra) {
this.assert(this.chat, 'replyWithVideoNote');
return this.telegram.sendVideoNote(this.chat.id, videoNote, makeReply(this, extra));
},
replyWithVoice(voice, extra) {
this.assert(this.chat, 'replyWithVoice');
return this.telegram.sendVoice(this.chat.id, voice, makeReply(this, extra));
},
};
/**
* Sets up Context to use the new reply methods.
* This middleware makes `ctx.reply()` and `ctx.replyWith*()` methods will actually reply to the message they are replying to.
* Use `ctx.sendMessage()` to send a message in chat without replying to it.
*
* If the message to reply is deleted, `reply()` will send a normal message.
* If the update is not a message and we are unable to reply, `reply()` will send a normal message.
*/
function useNewReplies() {
return (ctx, next) => {
ctx.reply = replyContext.reply;
ctx.replyWithPhoto = replyContext.replyWithPhoto;
ctx.replyWithMediaGroup = replyContext.replyWithMediaGroup;
ctx.replyWithAudio = replyContext.replyWithAudio;
ctx.replyWithDice = replyContext.replyWithDice;
ctx.replyWithDocument = replyContext.replyWithDocument;
ctx.replyWithSticker = replyContext.replyWithSticker;
ctx.replyWithVideo = replyContext.replyWithVideo;
ctx.replyWithAnimation = replyContext.replyWithAnimation;
ctx.replyWithVideoNote = replyContext.replyWithVideoNote;
ctx.replyWithInvoice = replyContext.replyWithInvoice;
ctx.replyWithGame = replyContext.replyWithGame;
ctx.replyWithVoice = replyContext.replyWithVoice;
ctx.replyWithPoll = replyContext.replyWithPoll;
ctx.replyWithQuiz = replyContext.replyWithQuiz;
ctx.replyWithChatAction = replyContext.replyWithChatAction;
ctx.replyWithLocation = replyContext.replyWithLocation;
ctx.replyWithVenue = replyContext.replyWithVenue;
ctx.replyWithContact = replyContext.replyWithContact;
ctx.replyWithMarkdown = replyContext.replyWithMarkdown;
ctx.replyWithMarkdownV2 = replyContext.replyWithMarkdownV2;
ctx.replyWithHTML = replyContext.replyWithHTML;
return next();
};
}
exports.useNewReplies = useNewReplies;

48
node_modules/telegraf/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,48 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Scenes = exports.MemorySessionStore = exports.session = exports.deunionize = exports.Format = exports.Input = exports.Markup = exports.Types = exports.Telegram = exports.TelegramError = exports.Router = exports.Composer = exports.Context = exports.Telegraf = void 0;
var telegraf_1 = require("./telegraf");
Object.defineProperty(exports, "Telegraf", { enumerable: true, get: function () { return telegraf_1.Telegraf; } });
var context_1 = require("./context");
Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return context_1.Context; } });
var composer_1 = require("./composer");
Object.defineProperty(exports, "Composer", { enumerable: true, get: function () { return composer_1.Composer; } });
var router_1 = require("./router");
Object.defineProperty(exports, "Router", { enumerable: true, get: function () { return router_1.Router; } });
var error_1 = require("./core/network/error");
Object.defineProperty(exports, "TelegramError", { enumerable: true, get: function () { return error_1.TelegramError; } });
var telegram_1 = require("./telegram");
Object.defineProperty(exports, "Telegram", { enumerable: true, get: function () { return telegram_1.Telegram; } });
exports.Types = __importStar(require("./telegram-types"));
exports.Markup = __importStar(require("./markup"));
exports.Input = __importStar(require("./input"));
exports.Format = __importStar(require("./format"));
var deunionize_1 = require("./core/helpers/deunionize");
Object.defineProperty(exports, "deunionize", { enumerable: true, get: function () { return deunionize_1.deunionize; } });
var session_1 = require("./session");
Object.defineProperty(exports, "session", { enumerable: true, get: function () { return session_1.session; } });
Object.defineProperty(exports, "MemorySessionStore", { enumerable: true, get: function () { return session_1.MemorySessionStore; } });
exports.Scenes = __importStar(require("./scenes"));

61
node_modules/telegraf/lib/input.js generated vendored Normal file
View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.fromFileId = exports.fromURL = exports.fromURLStream = exports.fromReadableStream = exports.fromBuffer = exports.fromLocalFile = void 0;
/**
* The local file specified by path will be uploaded to Telegram using multipart/form-data.
*
* 10 MB max size for photos, 50 MB for other files.
*/
// prettier-ignore
const fromLocalFile = (path, filename) => ({ source: path, filename });
exports.fromLocalFile = fromLocalFile;
/**
* The buffer will be uploaded as file to Telegram using multipart/form-data.
*
* 10 MB max size for photos, 50 MB for other files.
*/
// prettier-ignore
const fromBuffer = (buffer, filename) => ({ source: buffer, filename });
exports.fromBuffer = fromBuffer;
/**
* Contents of the stream will be uploaded as file to Telegram using multipart/form-data.
*
* 10 MB max size for photos, 50 MB for other files.
*/
// prettier-ignore
const fromReadableStream = (stream, filename) => ({ source: stream, filename });
exports.fromReadableStream = fromReadableStream;
/**
* Contents of the URL will be streamed to Telegram.
*
* 10 MB max size for photos, 50 MB for other files.
*/
// prettier-ignore
const fromURLStream = (url, filename) => ({ url: url.toString(), filename });
exports.fromURLStream = fromURLStream;
/**
* Provide Telegram with an HTTP URL for the file to be sent.
* Telegram will download and send the file.
*
* * The target file must have the correct MIME type (e.g., audio/mpeg for `sendAudio`, etc.).
* * `sendDocument` with URL will currently only work for GIF, PDF and ZIP files.
* * To use `sendVoice`, the file must have the type audio/ogg and be no more than 1MB in size.
* 1-20MB voice notes will be sent as files.
*
* 5 MB max size for photos and 20 MB max for other types of content.
*/
const fromURL = (url) => url.toString();
exports.fromURL = fromURL;
/**
* If the file is already stored somewhere on the Telegram servers, you don't need to reupload it:
* each file object has a file_id field, simply pass this file_id as a parameter instead of uploading.
*
* It is not possible to change the file type when resending by file_id.
*
* It is not possible to resend thumbnails using file_id.
* They have to be uploaded using one of the other Input methods.
*
* There are no limits for files sent this way.
*/
const fromFileId = (fileId) => fileId;
exports.fromFileId = fromFileId;

111
node_modules/telegraf/lib/markup.js generated vendored Normal file
View File

@@ -0,0 +1,111 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.inlineKeyboard = exports.keyboard = exports.forceReply = exports.removeKeyboard = exports.button = exports.Markup = void 0;
const check_1 = require("./core/helpers/check");
class Markup {
constructor(reply_markup) {
this.reply_markup = reply_markup;
}
selective(value = true) {
return new Markup({ ...this.reply_markup, selective: value });
}
placeholder(placeholder) {
return new Markup({
...this.reply_markup,
input_field_placeholder: placeholder,
});
}
resize(value = true) {
return new Markup({
...this.reply_markup,
resize_keyboard: value,
});
}
oneTime(value = true) {
return new Markup({
...this.reply_markup,
one_time_keyboard: value,
});
}
persistent(value = true) {
return new Markup({
...this.reply_markup,
is_persistent: value,
});
}
}
exports.Markup = Markup;
exports.button = __importStar(require("./button"));
function removeKeyboard() {
return new Markup({ remove_keyboard: true });
}
exports.removeKeyboard = removeKeyboard;
function forceReply() {
return new Markup({ force_reply: true });
}
exports.forceReply = forceReply;
function keyboard(buttons, options) {
const keyboard = buildKeyboard(buttons, {
columns: 1,
...options,
});
return new Markup({ keyboard });
}
exports.keyboard = keyboard;
function inlineKeyboard(buttons, options) {
const inlineKeyboard = buildKeyboard(buttons, {
columns: buttons.length,
...options,
});
return new Markup({ inline_keyboard: inlineKeyboard });
}
exports.inlineKeyboard = inlineKeyboard;
function buildKeyboard(buttons, options) {
const result = [];
if (!Array.isArray(buttons)) {
return result;
}
if ((0, check_1.is2D)(buttons)) {
return buttons.map((row) => row.filter((button) => !button.hide));
}
const wrapFn = options.wrap !== undefined
? options.wrap
: (_btn, _index, currentRow) => currentRow.length >= options.columns;
let currentRow = [];
let index = 0;
for (const btn of buttons.filter((button) => !button.hide)) {
if (wrapFn(btn, index, currentRow) && currentRow.length > 0) {
result.push(currentRow);
currentRow = [];
}
currentRow.push(btn);
index++;
}
if (currentRow.length > 0) {
result.push(currentRow);
}
return result;
}

2
node_modules/telegraf/lib/middleware.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

84
node_modules/telegraf/lib/reactions.js generated vendored Normal file
View File

@@ -0,0 +1,84 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageReactions = exports.ReactionList = exports.Digit = void 0;
const util_1 = require("./core/helpers/util");
exports.Digit = new Set(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']);
const inspectReaction = (reaction) => {
if (reaction.type === 'custom_emoji')
return `Custom(${reaction.custom_emoji_id})`;
else
return reaction.emoji;
};
class ReactionList {
constructor(list) {
this.list = list;
}
static fromArray(list = []) {
return (0, util_1.indexed)(new ReactionList(list), function (index) {
return this.list[index];
});
}
static has(reactions, reaction) {
if (typeof reaction === 'string')
if (exports.Digit.has(reaction[0]))
return reactions.some((r) => r.custom_emoji_id === reaction);
else
return reactions.some((r) => r.emoji === reaction);
return reactions.some((r) => {
if (r.type === 'custom_emoji')
return r.custom_emoji_id === reaction.custom_emoji_id;
else if (r.type === 'emoji')
return r.emoji === reaction.emoji;
});
}
toArray() {
return [...this.list];
}
filter(filterFn) {
return ReactionList.fromArray(this.list.filter(filterFn));
}
has(reaction) {
return ReactionList.has(this.list, reaction);
}
get count() {
return this.list.length;
}
[Symbol.iterator]() {
return this.list[Symbol.iterator]();
}
[Symbol.for('nodejs.util.inspect.custom')]() {
const flattened = this.list.map(inspectReaction).join(', ');
return ['ReactionList {', flattened, '}'].join(' ');
}
}
exports.ReactionList = ReactionList;
class MessageReactions extends ReactionList {
constructor(ctx) {
var _a, _b;
super((_b = (_a = ctx.update.message_reaction) === null || _a === void 0 ? void 0 : _a.new_reaction) !== null && _b !== void 0 ? _b : []);
this.ctx = ctx;
}
static from(ctx) {
return (0, util_1.indexed)(new MessageReactions(ctx), function (index) {
return this.list[index];
});
}
get old() {
var _a;
return ReactionList.fromArray((_a = this.ctx.update.message_reaction) === null || _a === void 0 ? void 0 : _a.old_reaction);
}
get new() {
var _a;
return ReactionList.fromArray((_a = this.ctx.update.message_reaction) === null || _a === void 0 ? void 0 : _a.new_reaction);
}
get added() {
return this.new.filter((reaction) => !this.old.has(reaction));
}
get removed() {
return this.old.filter((reaction) => !this.new.has(reaction));
}
get kept() {
return this.new.filter((reaction) => this.old.has(reaction));
}
}
exports.MessageReactions = MessageReactions;

46
node_modules/telegraf/lib/router.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
"use strict";
/** @format */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Router = void 0;
const composer_1 = __importDefault(require("./composer"));
/** @deprecated in favor of {@link Composer.dispatch} */
class Router {
constructor(routeFn, handlers = new Map()) {
this.routeFn = routeFn;
this.handlers = handlers;
this.otherwiseHandler = composer_1.default.passThru();
if (typeof routeFn !== 'function') {
throw new Error('Missing routing function');
}
}
on(route, ...fns) {
if (fns.length === 0) {
throw new TypeError('At least one handler must be provided');
}
this.handlers.set(route, composer_1.default.compose(fns));
return this;
}
otherwise(...fns) {
if (fns.length === 0) {
throw new TypeError('At least one otherwise handler must be provided');
}
this.otherwiseHandler = composer_1.default.compose(fns);
return this;
}
middleware() {
return composer_1.default.lazy((ctx) => {
var _a;
const result = this.routeFn(ctx);
if (result == null) {
return this.otherwiseHandler;
}
Object.assign(ctx, result.context);
Object.assign(ctx.state, result.state);
return (_a = this.handlers.get(result.route)) !== null && _a !== void 0 ? _a : this.otherwiseHandler;
});
}
}
exports.Router = Router;

17
node_modules/telegraf/lib/scenes.js generated vendored Normal file
View 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("./scenes/index.js"), exports);

39
node_modules/telegraf/lib/scenes/base.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseScene = void 0;
const composer_1 = __importDefault(require("../composer"));
const { compose } = composer_1.default;
class BaseScene extends composer_1.default {
constructor(id, options) {
const opts = {
handlers: [],
enterHandlers: [],
leaveHandlers: [],
...options,
};
super(...opts.handlers);
this.id = id;
this.ttl = opts.ttl;
this.enterHandler = compose(opts.enterHandlers);
this.leaveHandler = compose(opts.leaveHandlers);
}
enter(...fns) {
this.enterHandler = compose([this.enterHandler, ...fns]);
return this;
}
leave(...fns) {
this.leaveHandler = compose([this.leaveHandler, ...fns]);
return this;
}
enterMiddleware() {
return this.enterHandler;
}
leaveMiddleware() {
return this.leaveHandler;
}
}
exports.BaseScene = BaseScene;
exports.default = BaseScene;

104
node_modules/telegraf/lib/scenes/context.js generated vendored Normal file
View File

@@ -0,0 +1,104 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const composer_1 = __importDefault(require("../composer"));
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)('telegraf:scenes:context');
const noop = () => Promise.resolve();
const now = () => Math.floor(Date.now() / 1000);
class SceneContextScene {
constructor(ctx, scenes, options) {
this.ctx = ctx;
this.scenes = scenes;
this.leaving = false;
// @ts-expect-error {} might not be assignable to D
const fallbackSessionDefault = {};
this.options = { defaultSession: fallbackSessionDefault, ...options };
}
get session() {
var _a, _b;
const defaultSession = Object.assign({}, this.options.defaultSession);
let session = (_b = (_a = this.ctx.session) === null || _a === void 0 ? void 0 : _a.__scenes) !== null && _b !== void 0 ? _b : defaultSession;
if (session.expires !== undefined && session.expires < now()) {
session = defaultSession;
}
if (this.ctx.session === undefined) {
this.ctx.session = { __scenes: session };
}
else {
this.ctx.session.__scenes = session;
}
return session;
}
get state() {
var _a;
var _b;
return ((_a = (_b = this.session).state) !== null && _a !== void 0 ? _a : (_b.state = {}));
}
set state(value) {
this.session.state = { ...value };
}
get current() {
var _a;
const sceneId = (_a = this.session.current) !== null && _a !== void 0 ? _a : this.options.default;
return sceneId === undefined || !this.scenes.has(sceneId)
? undefined
: this.scenes.get(sceneId);
}
reset() {
if (this.ctx.session !== undefined)
this.ctx.session.__scenes = Object.assign({}, this.options.defaultSession);
}
async enter(sceneId, initialState = {}, silent = false) {
var _a, _b;
if (!this.scenes.has(sceneId)) {
throw new Error(`Can't find scene: ${sceneId}`);
}
if (!silent) {
await this.leave();
}
debug('Entering scene', sceneId, initialState, silent);
this.session.current = sceneId;
this.state = initialState;
const ttl = (_b = (_a = this.current) === null || _a === void 0 ? void 0 : _a.ttl) !== null && _b !== void 0 ? _b : this.options.ttl;
if (ttl !== undefined) {
this.session.expires = now() + ttl;
}
if (this.current === undefined || silent) {
return;
}
const handler = 'enterMiddleware' in this.current &&
typeof this.current.enterMiddleware === 'function'
? this.current.enterMiddleware()
: this.current.middleware();
return await handler(this.ctx, noop);
}
reenter() {
return this.session.current === undefined
? undefined
: this.enter(this.session.current, this.state);
}
async leave() {
if (this.leaving)
return;
debug('Leaving scene');
try {
this.leaving = true;
if (this.current === undefined) {
return;
}
const handler = 'leaveMiddleware' in this.current &&
typeof this.current.leaveMiddleware === 'function'
? this.current.leaveMiddleware()
: composer_1.default.passThru();
await handler(this.ctx, noop);
return this.reset();
}
finally {
this.leaving = false;
}
}
}
exports.default = SceneContextScene;

21
node_modules/telegraf/lib/scenes/index.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
"use strict";
/**
* @see https://github.com/telegraf/telegraf/issues/705#issuecomment-549056045
* @see https://www.npmjs.com/package/telegraf-stateless-question
* @packageDocumentation
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WizardContextWizard = exports.WizardScene = exports.BaseScene = exports.SceneContextScene = exports.Stage = void 0;
var stage_1 = require("./stage");
Object.defineProperty(exports, "Stage", { enumerable: true, get: function () { return stage_1.Stage; } });
var context_1 = require("./context");
Object.defineProperty(exports, "SceneContextScene", { enumerable: true, get: function () { return __importDefault(context_1).default; } });
var base_1 = require("./base");
Object.defineProperty(exports, "BaseScene", { enumerable: true, get: function () { return base_1.BaseScene; } });
var wizard_1 = require("./wizard");
Object.defineProperty(exports, "WizardScene", { enumerable: true, get: function () { return wizard_1.WizardScene; } });
var context_2 = require("./wizard/context");
Object.defineProperty(exports, "WizardContextWizard", { enumerable: true, get: function () { return __importDefault(context_2).default; } });

49
node_modules/telegraf/lib/scenes/stage.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Stage = void 0;
const session_1 = require("../session");
const context_1 = __importDefault(require("./context"));
const composer_1 = require("../composer");
class Stage extends composer_1.Composer {
constructor(scenes = [], options) {
super();
this.options = { ...options };
this.scenes = new Map();
scenes.forEach((scene) => this.register(scene));
}
register(...scenes) {
scenes.forEach((scene) => {
if ((scene === null || scene === void 0 ? void 0 : scene.id) == null || typeof scene.middleware !== 'function') {
throw new Error('telegraf: Unsupported scene');
}
this.scenes.set(scene.id, scene);
});
return this;
}
middleware() {
const handler = composer_1.Composer.compose([
(ctx, next) => {
const scenes = this.scenes;
const scene = new context_1.default(ctx, scenes, this.options);
ctx.scene = scene;
return next();
},
super.middleware(),
composer_1.Composer.lazy((ctx) => { var _a; return (_a = ctx.scene.current) !== null && _a !== void 0 ? _a : composer_1.Composer.passThru(); }),
]);
return composer_1.Composer.optional(session_1.isSessionContext, handler);
}
static enter(...args) {
return (ctx) => ctx.scene.enter(...args);
}
static reenter(...args) {
return (ctx) => ctx.scene.reenter(...args);
}
static leave(...args) {
return (ctx) => ctx.scene.leave(...args);
}
}
exports.Stage = Stage;

31
node_modules/telegraf/lib/scenes/wizard/context.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class WizardContextWizard {
constructor(ctx, steps) {
var _a;
this.ctx = ctx;
this.steps = steps;
this.state = ctx.scene.state;
this.cursor = (_a = ctx.scene.session.cursor) !== null && _a !== void 0 ? _a : 0;
}
get step() {
return this.steps[this.cursor];
}
get cursor() {
return this.ctx.scene.session.cursor;
}
set cursor(cursor) {
this.ctx.scene.session.cursor = cursor;
}
selectStep(index) {
this.cursor = index;
return this;
}
next() {
return this.selectStep(this.cursor + 1);
}
back() {
return this.selectStep(this.cursor - 1);
}
}
exports.default = WizardContextWizard;

45
node_modules/telegraf/lib/scenes/wizard/index.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WizardScene = void 0;
const base_1 = __importDefault(require("../base"));
const context_1 = __importDefault(require("./context"));
const composer_1 = __importDefault(require("../../composer"));
class WizardScene extends base_1.default {
constructor(id, options, ...steps) {
let opts;
let s;
if (typeof options === 'function' || 'middleware' in options) {
opts = undefined;
s = [options, ...steps];
}
else {
opts = options;
s = steps;
}
super(id, opts);
this.steps = s;
}
middleware() {
return composer_1.default.compose([
(ctx, next) => {
ctx.wizard = new context_1.default(ctx, this.steps);
return next();
},
super.middleware(),
(ctx, next) => {
if (ctx.wizard.step === undefined) {
ctx.wizard.selectStep(0);
return ctx.scene.leave();
}
return composer_1.default.unwrap(ctx.wizard.step)(ctx, next);
},
]);
}
enterMiddleware() {
return composer_1.default.compose([this.enterHandler, this.middleware()]);
}
}
exports.WizardScene = WizardScene;

166
node_modules/telegraf/lib/session.js generated vendored Normal file
View File

@@ -0,0 +1,166 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isSessionContext = exports.MemorySessionStore = exports.session = void 0;
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)('telegraf:session');
/**
* Returns middleware that adds `ctx.session` for storing arbitrary state per session key.
*
* The default `getSessionKey` is `${ctx.from.id}:${ctx.chat.id}`.
* If either `ctx.from` or `ctx.chat` is `undefined`, default session key and thus `ctx.session` are also `undefined`.
*
* > ⚠️ Session data is kept only in memory by default, which means that all data will be lost when the process is terminated.
* >
* > If you want to persist data across process restarts, or share it among multiple instances, you should use
* [@telegraf/session](https://www.npmjs.com/package/@telegraf/session), or pass custom `storage`.
*
* @see {@link https://github.com/feathers-studio/telegraf-docs/blob/b694bcc36b4f71fb1cd650a345c2009ab4d2a2a5/guide/session.md Telegraf Docs | Session}
* @see {@link https://github.com/feathers-studio/telegraf-docs/blob/master/examples/session-bot.ts Example}
*/
function session(options) {
var _a, _b, _c;
const prop = (_a = options === null || options === void 0 ? void 0 : options.property) !== null && _a !== void 0 ? _a : 'session';
const getSessionKey = (_b = options === null || options === void 0 ? void 0 : options.getSessionKey) !== null && _b !== void 0 ? _b : defaultGetSessionKey;
const store = (_c = options === null || options === void 0 ? void 0 : options.store) !== null && _c !== void 0 ? _c : new MemorySessionStore();
// caches value from store in-memory while simultaneous updates share it
// when counter reaches 0, the cached ref will be freed from memory
const cache = new Map();
// temporarily stores concurrent requests
const concurrents = new Map();
// this function must be handled with care
// read full description on the original PR: https://github.com/telegraf/telegraf/pull/1713
// make sure to update the tests in test/session.js if you make any changes or fix bugs here
return async (ctx, next) => {
var _a;
const updId = ctx.update.update_id;
let released = false;
function releaseChecks() {
if (released && process.env.EXPERIMENTAL_SESSION_CHECKS)
throw new Error("Session was accessed or assigned to after the middleware chain exhausted. This is a bug in your code. You're probably accessing session asynchronously and missing awaits.");
}
// because this is async, requests may still race here, but it will get autocorrected at (1)
// v5 getSessionKey should probably be synchronous to avoid that
const key = await getSessionKey(ctx);
if (!key) {
// Leaving this here could be useful to check for `prop in ctx` in future middleware
ctx[prop] = undefined;
return await next();
}
let cached = cache.get(key);
if (cached) {
debug(`(${updId}) found cached session, reusing from cache`);
++cached.counter;
}
else {
debug(`(${updId}) did not find cached session`);
// if another concurrent request has already sent a store request, fetch that instead
let promise = concurrents.get(key);
if (promise)
debug(`(${updId}) found a concurrent request, reusing promise`);
else {
debug(`(${updId}) fetching from upstream store`);
promise = store.get(key);
}
// synchronously store promise so concurrent requests can share response
concurrents.set(key, promise);
const upstream = await promise;
// all concurrent awaits will have promise in their closure, safe to remove now
concurrents.delete(key);
debug(`(${updId}) updating cache`);
// another request may have beaten us to the punch
const c = cache.get(key);
if (c) {
// another request did beat us to the punch
c.counter++;
// (1) preserve cached reference; in-memory reference is always newer than from store
cached = c;
}
else {
// we're the first, so we must cache the reference
cached = { ref: upstream !== null && upstream !== void 0 ? upstream : (_a = options === null || options === void 0 ? void 0 : options.defaultSession) === null || _a === void 0 ? void 0 : _a.call(options, ctx), counter: 1 };
cache.set(key, cached);
}
}
// TS already knows cached is always defined by this point, but does not guard cached.
// It will, however, guard `c` here.
const c = cached;
let touched = false;
Object.defineProperty(ctx, prop, {
get() {
releaseChecks();
touched = true;
return c.ref;
},
set(value) {
releaseChecks();
touched = true;
c.ref = value;
},
});
try {
await next();
released = true;
}
finally {
if (--c.counter === 0) {
// decrement to avoid memory leak
debug(`(${updId}) refcounter reached 0, removing cached`);
cache.delete(key);
}
debug(`(${updId}) middlewares completed, checking session`);
// only update store if ctx.session was touched
if (touched)
if (c.ref == null) {
debug(`(${updId}) ctx.${prop} missing, removing from store`);
await store.delete(key);
}
else {
debug(`(${updId}) ctx.${prop} found, updating store`);
await store.set(key, c.ref);
}
}
};
}
exports.session = session;
function defaultGetSessionKey(ctx) {
var _a, _b;
const fromId = (_a = ctx.from) === null || _a === void 0 ? void 0 : _a.id;
const chatId = (_b = ctx.chat) === null || _b === void 0 ? void 0 : _b.id;
if (fromId == null || chatId == null)
return undefined;
return `${fromId}:${chatId}`;
}
/** @deprecated Use `Map` */
class MemorySessionStore {
constructor(ttl = Infinity) {
this.ttl = ttl;
this.store = new Map();
}
get(name) {
const entry = this.store.get(name);
if (entry == null) {
return undefined;
}
else if (entry.expires < Date.now()) {
this.delete(name);
return undefined;
}
return entry.session;
}
set(name, value) {
const now = Date.now();
this.store.set(name, { session: value, expires: now + this.ttl });
}
delete(name) {
this.store.delete(name);
}
}
exports.MemorySessionStore = MemorySessionStore;
/** @deprecated session can use custom properties now. Directly use `'session' in ctx` instead */
function isSessionContext(ctx) {
return 'session' in ctx;
}
exports.isSessionContext = isSessionContext;

246
node_modules/telegraf/lib/telegraf.js generated vendored Normal file
View File

@@ -0,0 +1,246 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Telegraf = void 0;
const crypto = __importStar(require("crypto"));
const http = __importStar(require("http"));
const https = __importStar(require("https"));
const composer_1 = require("./composer");
const compact_1 = require("./core/helpers/compact");
const context_1 = __importDefault(require("./context"));
const debug_1 = __importDefault(require("debug"));
const webhook_1 = __importDefault(require("./core/network/webhook"));
const polling_1 = require("./core/network/polling");
const p_timeout_1 = __importDefault(require("p-timeout"));
const telegram_1 = __importDefault(require("./telegram"));
const url_1 = require("url");
const safeCompare = require("safe-compare");
const debug = (0, debug_1.default)('telegraf:main');
const DEFAULT_OPTIONS = {
telegram: {},
handlerTimeout: 90000,
contextType: context_1.default,
};
function always(x) {
return () => x;
}
const anoop = always(Promise.resolve());
const TOKEN_HEADER = 'x-telegram-bot-api-secret-token';
class Telegraf extends composer_1.Composer {
constructor(token, options) {
super();
this.context = {};
/** Assign to this to customise the webhook filter middleware.
* `{ path, secretToken }` will be bound to this rather than the Telegraf instance.
* Remember to assign a regular function and not an arrow function so it's bindable.
*/
this.webhookFilter = function (req) {
const debug = (0, debug_1.default)('telegraf:webhook');
if (req.method === 'POST') {
if (safeCompare(this.path, req.url)) {
// no need to check if secret_token was not set
if (!this.secretToken)
return true;
else {
const token = req.headers[TOKEN_HEADER];
if (safeCompare(this.secretToken, token))
return true;
else
debug('Secret token does not match:', token, this.secretToken);
}
}
else
debug('Path does not match:', req.url, this.path);
}
else
debug('Unexpected request method, not POST. Received:', req.method);
return false;
};
this.handleError = (err, ctx) => {
// set exit code to emulate `warn-with-error-code` behavior of
// https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode
// to prevent a clean exit despite an error being thrown
process.exitCode = 1;
console.error('Unhandled error while processing', ctx.update);
throw err;
};
// @ts-expect-error Trust me, TS
this.options = {
...DEFAULT_OPTIONS,
...(0, compact_1.compactOptions)(options),
};
this.telegram = new telegram_1.default(token, this.options.telegram);
debug('Created a `Telegraf` instance');
}
get token() {
return this.telegram.token;
}
/** @deprecated use `ctx.telegram.webhookReply` */
set webhookReply(webhookReply) {
this.telegram.webhookReply = webhookReply;
}
/** @deprecated use `ctx.telegram.webhookReply` */
get webhookReply() {
return this.telegram.webhookReply;
}
/**
* _Override_ error handling
*/
catch(handler) {
this.handleError = handler;
return this;
}
/**
* You must call `bot.telegram.setWebhook` for this to work.
* You should probably use {@link Telegraf.createWebhook} instead.
*/
webhookCallback(path = '/', opts = {}) {
const { secretToken } = opts;
return (0, webhook_1.default)(this.webhookFilter.bind({ hookPath: path, path, secretToken }), (update, res) => this.handleUpdate(update, res));
}
getDomainOpts(opts) {
var _a;
const protocol = opts.domain.startsWith('https://') || opts.domain.startsWith('http://');
if (protocol)
debug('Unexpected protocol in domain, telegraf will use https:', opts.domain);
const domain = protocol ? new url_1.URL(opts.domain).host : opts.domain;
const path = (_a = opts.path) !== null && _a !== void 0 ? _a : `/telegraf/${this.secretPathComponent()}`;
const url = `https://${domain}${path}`;
return { domain, path, url };
}
/**
* Specify a url to receive incoming updates via webhook.
* Returns an Express-style middleware you can pass to app.use()
*/
async createWebhook(opts) {
const { domain, path, ...extra } = opts;
const domainOpts = this.getDomainOpts({ domain, path });
await this.telegram.setWebhook(domainOpts.url, extra);
debug(`Webhook set to ${domainOpts.url}`);
return this.webhookCallback(domainOpts.path, {
secretToken: extra.secret_token,
});
}
startPolling(allowedUpdates = []) {
this.polling = new polling_1.Polling(this.telegram, allowedUpdates);
return this.polling.loop(async (update) => {
await this.handleUpdate(update);
});
}
startWebhook(path, tlsOptions, port, host, cb, secretToken) {
const webhookCb = this.webhookCallback(path, { secretToken });
const callback = typeof cb === 'function'
? (req, res) => webhookCb(req, res, () => cb(req, res))
: webhookCb;
this.webhookServer =
tlsOptions != null
? https.createServer(tlsOptions, callback)
: http.createServer(callback);
this.webhookServer.listen(port, host, () => {
debug('Webhook listening on port: %s', port);
});
return this;
}
secretPathComponent() {
return crypto
.createHash('sha3-256')
.update(this.token)
.update(process.version) // salt
.digest('hex');
}
/**
* @see https://github.com/telegraf/telegraf/discussions/1344#discussioncomment-335700
*/
async launch(config = {},
/** @experimental */
onLaunch) {
var _a, _b;
const [cfg, onMe] = typeof config === 'function' ? [{}, config] : [config, onLaunch];
const drop_pending_updates = cfg.dropPendingUpdates;
const allowed_updates = cfg.allowedUpdates;
const webhook = cfg.webhook;
debug('Connecting to Telegram');
(_a = this.botInfo) !== null && _a !== void 0 ? _a : (this.botInfo = await this.telegram.getMe());
onMe === null || onMe === void 0 ? void 0 : onMe();
debug(`Launching @${this.botInfo.username}`);
if (webhook === undefined) {
await this.telegram.deleteWebhook({ drop_pending_updates });
debug('Bot started with long polling');
await this.startPolling(allowed_updates);
return;
}
const domainOpts = this.getDomainOpts({
domain: webhook.domain,
path: (_b = webhook.path) !== null && _b !== void 0 ? _b : webhook.hookPath,
});
const { tlsOptions, port, host, cb, secretToken } = webhook;
this.startWebhook(domainOpts.path, tlsOptions, port, host, cb, secretToken);
await this.telegram.setWebhook(domainOpts.url, {
drop_pending_updates: drop_pending_updates,
allowed_updates: allowed_updates,
ip_address: webhook.ipAddress,
max_connections: webhook.maxConnections,
secret_token: webhook.secretToken,
certificate: webhook.certificate,
});
debug(`Bot started with webhook @ ${domainOpts.url}`);
}
stop(reason = 'unspecified') {
var _a, _b;
debug('Stopping bot... Reason:', reason);
// https://github.com/telegraf/telegraf/pull/1224#issuecomment-742693770
if (this.polling === undefined && this.webhookServer === undefined) {
throw new Error('Bot is not running!');
}
(_a = this.webhookServer) === null || _a === void 0 ? void 0 : _a.close();
(_b = this.polling) === null || _b === void 0 ? void 0 : _b.stop();
}
async handleUpdate(update, webhookResponse) {
var _a, _b;
(_a = this.botInfo) !== null && _a !== void 0 ? _a : (this.botInfo = (debug('Update %d is waiting for `botInfo` to be initialized', update.update_id),
await ((_b = this.botInfoCall) !== null && _b !== void 0 ? _b : (this.botInfoCall = this.telegram.getMe()))));
debug('Processing update', update.update_id);
const tg = new telegram_1.default(this.token, this.telegram.options, webhookResponse);
const TelegrafContext = this.options.contextType;
const ctx = new TelegrafContext(update, tg, this.botInfo);
Object.assign(ctx, this.context);
try {
await (0, p_timeout_1.default)(Promise.resolve(this.middleware()(ctx, anoop)), this.options.handlerTimeout);
}
catch (err) {
return await this.handleError(err, ctx);
}
finally {
if ((webhookResponse === null || webhookResponse === void 0 ? void 0 : webhookResponse.writableEnded) === false) {
webhookResponse.end();
}
debug('Finished processing update', update.update_id);
}
}
}
exports.Telegraf = Telegraf;

6
node_modules/telegraf/lib/telegram-types.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
"use strict";
/** @format */
Object.defineProperty(exports, "__esModule", { value: true });
exports.Markup = void 0;
var markup_1 = require("./markup");
Object.defineProperty(exports, "Markup", { enumerable: true, get: function () { return markup_1.Markup; } });

1240
node_modules/telegraf/lib/telegram.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

2
node_modules/telegraf/lib/types.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

5
node_modules/telegraf/lib/utils.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.argsParser = void 0;
var args_1 = require("./core/helpers/args");
Object.defineProperty(exports, "argsParser", { enumerable: true, get: function () { return args_1.argsParser; } });

1
node_modules/telegraf/markup.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './typings/markup'

1
node_modules/telegraf/markup.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/markup')

134
node_modules/telegraf/package.json generated vendored Normal file
View File

@@ -0,0 +1,134 @@
{
"name": "telegraf",
"version": "4.16.3",
"description": "Modern Telegram Bot Framework",
"license": "MIT",
"author": "The Telegraf Contributors",
"homepage": "https://telegraf.js.org",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/telegraf/telegraf.git"
},
"bugs": {
"url": "https://github.com/telegraf/telegraf/issues"
},
"main": "lib/index.js",
"exports": {
".": {
"types": "./typings/index.d.ts",
"default": "./lib/index.js"
},
"./filters": {
"types": "./filters.d.ts",
"default": "./filters.js"
},
"./future": {
"types": "./future.d.ts",
"default": "./future.js"
},
"./scenes": {
"types": "./scenes.d.ts",
"default": "./scenes.js"
},
"./types": {
"types": "./types.d.ts",
"default": "./types.js"
},
"./format": {
"types": "./format.d.ts",
"default": "./format.js"
},
"./utils": {
"types": "./utils.d.ts",
"default": "./utils.js"
},
"./markup": {
"types": "./markup.d.ts",
"default": "./markup.js"
},
"./session": {
"types": "./session.d.ts",
"default": "./session.js"
}
},
"files": [
"bin/*",
"src/**/*.ts",
"lib/**/*.js",
"typings/**/*.d.ts",
"typings/**/*.d.ts.map",
"types.*",
"format.*",
"filters.*",
"future.*",
"scenes.*",
"utils.*",
"markup.*",
"session.*"
],
"bin": {
"telegraf": "lib/cli.mjs"
},
"scripts": {
"prepare": "npm run --silent build",
"build": "tsc && npm run expose",
"expose": "tsx build/expose.ts types scenes filters format future utils markup session",
"build:docs": "typedoc src/index.ts",
"pretest": "npm run build",
"test": "ava",
"lint": "eslint .",
"checks": "npm test && npm run lint",
"refresh": "npm run clean && npm ci",
"clean": "git clean -fX .eslintcache docs/build/ lib/ typings/"
},
"ava": {
"files": [
"test/*",
"!test/_*"
]
},
"type": "commonjs",
"engines": {
"node": "^12.20.0 || >=14.13.1"
},
"types": "./typings/index.d.ts",
"dependencies": {
"@telegraf/types": "^7.1.0",
"abort-controller": "^3.0.0",
"debug": "^4.3.4",
"mri": "^1.2.0",
"node-fetch": "^2.7.0",
"p-timeout": "^4.1.0",
"safe-compare": "^1.1.4",
"sandwich-stream": "^2.0.2"
},
"devDependencies": {
"@types/debug": "^4.1.8",
"@types/node": "^20.4.2",
"@types/node-fetch": "^2.6.2",
"@types/safe-compare": "^1.1.0",
"@typescript-eslint/eslint-plugin": "^6.1.0",
"@typescript-eslint/parser": "^6.1.0",
"ava": "^5.3.1",
"eslint": "^8.45.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-ava": "^14.0.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-promise": "^6.1.1",
"fast-check": "^3.12.0",
"prettier": "^3.0.3",
"tsx": "^4.7.1",
"typedoc": "^0.25.0",
"typescript": "^5.2.2"
},
"keywords": [
"telegraf",
"telegram",
"telegram bot api",
"bot",
"botapi",
"bot framework"
]
}

1
node_modules/telegraf/scenes.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './typings/scenes'

1
node_modules/telegraf/scenes.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/scenes')

1
node_modules/telegraf/session.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './typings/session'

1
node_modules/telegraf/session.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/session')

182
node_modules/telegraf/src/button.ts generated vendored Normal file
View File

@@ -0,0 +1,182 @@
import {
InlineKeyboardButton,
KeyboardButton,
KeyboardButtonRequestChat,
KeyboardButtonRequestUsers,
} from './core/types/typegram'
type Hideable<B> = B & { hide: boolean }
export function text(
text: string,
hide = false
): Hideable<KeyboardButton.CommonButton> {
return { text, hide }
}
export function contactRequest(
text: string,
hide = false
): Hideable<KeyboardButton.RequestContactButton> {
return { text, request_contact: true, hide }
}
export function locationRequest(
text: string,
hide = false
): Hideable<KeyboardButton.RequestLocationButton> {
return { text, request_location: true, hide }
}
export function pollRequest(
text: string,
type?: 'quiz' | 'regular',
hide = false
): Hideable<KeyboardButton.RequestPollButton> {
return { text, request_poll: { type }, hide }
}
export function userRequest(
text: string,
/** Must fit in a signed 32 bit int */
request_id: number,
extra?: Omit<KeyboardButtonRequestUsers, 'request_id' | 'text'>,
hide = false
): Hideable<KeyboardButton.RequestUsersButton> {
return {
text,
request_users: { request_id, ...extra },
hide,
}
}
export function botRequest(
text: string,
/** Must fit in a signed 32 bit int */
request_id: number,
extra?: Omit<
KeyboardButtonRequestUsers,
'request_id' | 'user_is_bot' | 'text'
>,
hide = false
): Hideable<KeyboardButton.RequestUsersButton> {
return {
text,
request_users: { request_id, user_is_bot: true, ...extra },
hide,
}
}
type KeyboardButtonRequestGroup = Omit<
KeyboardButtonRequestChat,
'request_id' | 'chat_is_channel'
>
export function groupRequest(
text: string,
/** Must fit in a signed 32 bit int */
request_id: number,
extra?: KeyboardButtonRequestGroup,
hide = false
): Hideable<KeyboardButton.RequestChatButton> {
return {
text,
request_chat: { request_id, chat_is_channel: false, ...extra },
hide,
}
}
type KeyboardButtonRequestChannel = Omit<
KeyboardButtonRequestChat,
'request_id' | 'chat_is_channel' | 'chat_is_forum'
>
export function channelRequest(
text: string,
/** Must fit in a signed 32 bit int */
request_id: number,
extra?: KeyboardButtonRequestChannel,
hide = false
): Hideable<KeyboardButton.RequestChatButton> {
return {
text,
request_chat: { request_id, chat_is_channel: true, ...extra },
hide,
}
}
export function url(
text: string,
url: string,
hide = false
): Hideable<InlineKeyboardButton.UrlButton> {
return { text, url, hide }
}
export function callback(
text: string,
data: string,
hide = false
): Hideable<InlineKeyboardButton.CallbackButton> {
return { text, callback_data: data, hide }
}
export function switchToChat(
text: string,
value: string,
hide = false
): Hideable<InlineKeyboardButton.SwitchInlineButton> {
return { text, switch_inline_query: value, hide }
}
export function switchToCurrentChat(
text: string,
value: string,
hide = false
): Hideable<InlineKeyboardButton.SwitchInlineCurrentChatButton> {
return { text, switch_inline_query_current_chat: value, hide }
}
export function game(
text: string,
hide = false
): Hideable<InlineKeyboardButton.GameButton> {
return { text, callback_game: {}, hide }
}
export function pay(
text: string,
hide = false
): Hideable<InlineKeyboardButton.PayButton> {
return { text, pay: true, hide }
}
export function login(
text: string,
url: string,
opts: {
forward_text?: string
bot_username?: string
request_write_access?: boolean
} = {},
hide = false
): Hideable<InlineKeyboardButton.LoginButton> {
return {
text,
login_url: { ...opts, url },
hide,
}
}
export function webApp(
text: string,
url: string,
hide = false
// works as both InlineKeyboardButton and KeyboardButton
): Hideable<InlineKeyboardButton.WebAppButton> {
return {
text,
web_app: { url },
hide,
}
}

1008
node_modules/telegraf/src/composer.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

1663
node_modules/telegraf/src/context.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

63
node_modules/telegraf/src/core/helpers/args.ts generated vendored Normal file
View File

@@ -0,0 +1,63 @@
interface Entity {
/** Type of the entity. Currently, can be “mention” (@username), “hashtag” (#hashtag), “cashtag” ($USD), “bot_command” (/start@jobs_bot), “url” (https://telegram.org), “email” (do-not-reply@telegram.org), “phone_number” (+1-212-555-0123), “bold” (bold text), “italic” (italic text), “underline” (underlined text), “strikethrough” (strikethrough text), “spoiler” (spoiler message), “code” (monowidth string), “pre” (monowidth block), “text_link” (for clickable text URLs), “text_mention” (for users without usernames), “custom_emoji” (for inline custom emoji stickers) */
type: string
/** Offset in UTF-16 code units to the start of the entity */
offset: number
/** Length of the entity in UTF-16 code units */
length: number
}
const SINGLE_QUOTE = "'"
const DOUBLE_QUOTE = '"'
export function argsParser(
str: string,
entities: Entity[] = [],
entityOffset = 0
) {
const mentions: { [offset: string]: number } = {}
for (const entity of entities) // extract all text_mentions into an { offset: length } map
if (entity.type === 'text_mention' || entity.type === 'text_link')
mentions[entity.offset - entityOffset] = entity.length
const args: string[] = []
let done = 0
let inside: `'` | `"` | undefined = undefined
let buf = ''
function flush(to: number) {
if (done !== to) args.push(buf + str.slice(done, to)), (inside = undefined)
buf = ''
done = to + 1
}
for (let i = 0; i < str.length; i++) {
const char = str[i]
// quick lookup length of mention starting at i
const mention = mentions[i]
if (mention) {
// if we're inside a quote, eagerly flush existing state
flush(i)
// this also consumes current index, so decrement
done--
// fast forward to end of mention
i += mention
flush(i)
} else if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE)
if (inside)
if (inside === char) flush(i)
else continue
else flush(i), (inside = char)
else if (char === ' ')
if (inside) continue
else flush(i)
else if (char === '\n') flush(i)
else if (char === '\\')
(buf += str.slice(done, i)), (done = ++i) // skip parsing the next char
else continue
}
if (done < str.length) flush(str.length)
return args
}

71
node_modules/telegraf/src/core/helpers/check.ts generated vendored Normal file
View File

@@ -0,0 +1,71 @@
interface Mapping {
string: string
number: number
bigint: bigint
boolean: boolean
symbol: symbol
undefined: undefined
object: Record<string, unknown>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function: (...props: any[]) => any
}
/**
* Checks if a given object has a property with a given name.
*
* Example invocation:
* ```js
* let obj = { 'foo': 'bar', 'baz': () => {} }
* hasProp(obj, 'foo') // true
* hasProp(obj, 'baz') // true
* hasProp(obj, 'abc') // false
* ```
*
* @param obj An object to test
* @param prop The name of the property
*/
export function hasProp<O extends object, K extends PropertyKey>(
obj: O | undefined,
prop: K
): obj is O & Record<K, unknown> {
return obj !== undefined && prop in obj
}
/**
* Checks if a given object has a property with a given name.
* Furthermore performs a `typeof` check on the property if it exists.
*
* Example invocation:
* ```js
* let obj = { 'foo': 'bar', 'baz': () => {} }
* hasPropType(obj, 'foo', 'string') // true
* hasPropType(obj, 'baz', 'function') // true
* hasPropType(obj, 'abc', 'number') // false
* ```
*
* @param obj An object to test
* @param prop The name of the property
* @param type The type the property is expected to have
*/
export function hasPropType<
O extends object,
K extends PropertyKey,
T extends keyof Mapping,
V extends Mapping[T],
>(obj: O | undefined, prop: K, type: T): obj is O & Record<K, V> {
return hasProp(obj, prop) && type === typeof obj[prop]
}
/**
* Checks if the supplied array has two dimensions or not.
*
* Example invocations:
* is2D([]) // false
* is2D([[]]) // true
* is2D([[], []]) // true
* is2D([42]) // false
*
* @param arr an array with one or two dimensions
*/
export function is2D<E>(arr: E[] | E[][]): arr is E[][] {
return Array.isArray(arr[0])
}

18
node_modules/telegraf/src/core/helpers/compact.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
export function compactOptions<T extends { [key: string]: unknown }>(
options?: T
): T | undefined {
if (!options) {
return options
}
const compacted: Partial<T> = {}
for (const key in options)
if (
// todo(mkr): replace with Object.hasOwn in v5 (Node 16+)
Object.prototype.hasOwnProperty.call(options, key) &&
options[key] !== undefined
)
compacted[key] = options[key]
return compacted as T | undefined
}

26
node_modules/telegraf/src/core/helpers/deunionize.ts generated vendored Normal file
View File

@@ -0,0 +1,26 @@
export type PropOr<
T extends object | undefined,
P extends string | symbol | number,
D = undefined,
> = T extends Partial<Record<P, unknown>> ? T[P] : D
export type UnionKeys<T> = T extends unknown ? keyof T : never
type AddOptionalKeys<K extends PropertyKey> = { readonly [P in K]?: never }
/**
* @see https://millsp.github.io/ts-toolbelt/modules/union_strict.html
*/
export type Deunionize<B extends object | undefined, T = B> = T extends object
? T & AddOptionalKeys<Exclude<UnionKeys<B>, keyof T>>
: T
/**
* Expose properties from all union variants.
* @deprectated
* @see https://github.com/telegraf/telegraf/issues/1388#issuecomment-791573609
* @see https://millsp.github.io/ts-toolbelt/modules/union_strict.html
*/
export function deunionize<T extends object | undefined>(t: T) {
return t as Deunionize<T>
}

119
node_modules/telegraf/src/core/helpers/formatting.ts generated vendored Normal file
View File

@@ -0,0 +1,119 @@
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
import { MessageEntity, User } from '@telegraf/types'
import { Any, zip } from './util'
export type Nestable<Kind extends string> =
| string
| number
| boolean
| FmtString<Kind>
export type MaybeNestableList<Kind extends string> =
| Nestable<Kind>
| readonly Nestable<Kind>[]
export interface FmtString<Brand extends string> {
text: string
entities?: MessageEntity[]
parse_mode?: undefined
__to_nest: Brand
}
export class FmtString<Brand extends string = string>
implements FmtString<Brand>
{
constructor(
public text: string,
entities?: MessageEntity[]
) {
if (entities) {
this.entities = entities
// force parse_mode to undefined if entities are present
this.parse_mode = undefined
}
}
static normalise(content: Nestable<string>) {
if (content instanceof FmtString) return content
return new FmtString(String(content))
}
}
const isArray: <T>(xs: T | readonly T[]) => xs is readonly T[] = Array.isArray
/** Given a base FmtString and something to append to it, mutates the base */
const _add = (base: FmtString, next: FmtString | Any) => {
const len = base.text.length
if (next instanceof FmtString) {
base.text = `${base.text}${next.text}`
// next.entities could be undefined and condition will fail
for (let i = 0; i < (next.entities?.length || 0); i++) {
// because of the above condition, next.entities[i] cannot be undefined
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const entity = next.entities![i]!
// base.entities is ensured by caller
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
base.entities!.push({ ...entity, offset: entity.offset + len })
}
} else base.text = `${base.text}${next}`
}
/**
* Given an `Iterable<FmtString | string | Any>` and a separator, flattens the list into a single FmtString.
* Analogous to Array#join -> string, but for FmtString
*/
export const join = (
fragments: Iterable<FmtString | string | Any>,
separator?: string | FmtString
) => {
const result = new FmtString('')
// ensure entities array so loop doesn't need to check
result.entities = []
const iter = fragments[Symbol.iterator]()
let curr = iter.next()
while (!curr.done) {
_add(result, curr.value)
curr = iter.next()
if (separator && !curr.done) _add(result, separator)
}
// set parse_mode: undefined if entities are present
if (result.entities.length) result.parse_mode = undefined
// remove entities array if not relevant
else delete result.entities
return result
}
/** Internal constructor for all fmt helpers */
export function createFmt(kind?: MessageEntity['type'], opts?: object) {
return function fmt(
parts: MaybeNestableList<string>,
...items: Nestable<string>[]
) {
parts = isArray(parts) ? parts : [parts]
const result = join(zip(parts, items))
if (kind) {
result.entities ??= []
result.entities.unshift({
type: kind,
offset: 0,
length: result.text.length,
...opts,
} as MessageEntity)
result.parse_mode = undefined
}
return result
}
}
export const linkOrMention = (
content: Nestable<string>,
data:
| { type: 'text_link'; url: string }
| { type: 'text_mention'; user: User }
) => {
const { text, entities = [] } = FmtString.normalise(content)
entities.unshift(Object.assign(data, { offset: 0, length: text.length }))
return new FmtString(text, entities)
}

96
node_modules/telegraf/src/core/helpers/util.ts generated vendored Normal file
View File

@@ -0,0 +1,96 @@
import { FmtString } from './formatting'
import { Deunionize, UnionKeys } from './deunionize'
export const env = process.env
// eslint-disable-next-line @typescript-eslint/ban-types
export type Any = {} | undefined | null
export type Expand<T> = T extends object
? T extends infer O
? { [K in keyof O]: O[K] }
: never
: T
export type MaybeArray<T> = T | T[]
export type MaybePromise<T> = T | Promise<T>
export type NonemptyReadonlyArray<T> = readonly [T, ...T[]]
// prettier-ignore
export type ExclusiveKeys<A extends object, B extends object> = keyof Omit<A, keyof B>
export function fmtCaption<
Extra extends { caption?: string | FmtString } | undefined,
>(
extra?: Extra
): Extra extends undefined
? undefined
: Omit<Extra, 'caption'> & { caption?: string }
export function fmtCaption(extra?: { caption?: string | FmtString }) {
if (!extra) return
const caption = extra.caption
if (!caption || typeof caption === 'string') return extra
const { text, entities } = caption
return {
...extra,
caption: text,
...(entities && {
caption_entities: entities,
parse_mode: undefined,
}),
}
}
export type DistinctKeys<T extends object> = Exclude<UnionKeys<T>, keyof T>
// prettier-ignore
/* eslint-disable-next-line @typescript-eslint/ban-types */
export type KeyedDistinct<T extends object, K extends DistinctKeys<T>> = Record<K, {}> & Deunionize<Record<K, {}>, T>
// prettier-ignore
/* eslint-disable-next-line @typescript-eslint/ban-types */
export type Keyed<T extends object, K extends UnionKeys<T>> = Record<K, {}> & Deunionize<Record<K, {}>, T>
/** Construct a generic type guard */
export type Guard<X = unknown, Y extends X = X> = (x: X) => x is Y
/** Extract the guarded type from a type guard, defaults to never. */
export type Guarded<F> =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
F extends (x: any) => x is infer T ? T : never
export function* zip<X, Y>(xs: Iterable<X>, ys: Iterable<Y>): Iterable<X | Y> {
const x = xs[Symbol.iterator]()
const y = ys[Symbol.iterator]()
let x1 = x.next()
let y1 = y.next()
while (!x1.done) {
yield x1.value
if (!y1.done) yield y1.value
x1 = x.next()
y1 = y.next()
}
while (!y1.done) {
yield y1.value
y1 = y.next()
}
}
export function indexed<T extends object, U>(
target: T,
indexer: (index: number) => U
) {
return new Proxy(target, {
get: function (target, prop, receiver) {
if (
(typeof prop === 'string' || typeof prop === 'number') &&
!isNaN(+prop)
)
return indexer.call(target, +prop)
return Reflect.get(target, prop, receiver)
},
})
}

396
node_modules/telegraf/src/core/network/client.ts generated vendored Normal file
View File

@@ -0,0 +1,396 @@
/* eslint @typescript-eslint/restrict-template-expressions: [ "error", { "allowNumber": true, "allowBoolean": true } ] */
import * as crypto from 'crypto'
import * as fs from 'fs'
import { stat, realpath } from 'fs/promises'
import * as http from 'http'
import * as https from 'https'
import * as path from 'path'
import fetch, { RequestInit } from 'node-fetch'
import { hasProp, hasPropType } from '../helpers/check'
import { InputFile, Opts, Telegram } from '../types/typegram'
import { AbortSignal } from 'abort-controller'
import { compactOptions } from '../helpers/compact'
import MultipartStream from './multipart-stream'
import TelegramError from './error'
import { URL } from 'url'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const debug = require('debug')('telegraf:client')
const { isStream } = MultipartStream
const WEBHOOK_REPLY_METHOD_ALLOWLIST = new Set<keyof Telegram>([
'answerCallbackQuery',
'answerInlineQuery',
'deleteMessage',
'leaveChat',
'sendChatAction',
])
namespace ApiClient {
export type Agent = http.Agent | ((parsedUrl: URL) => http.Agent) | undefined
export interface Options {
/**
* Agent for communicating with the bot API.
*/
agent?: http.Agent
/**
* Agent for attaching files via URL.
* 1. Not all agents support both `http:` and `https:`.
* 2. When passing a function, create the agents once, outside of the function.
* Creating new agent every request probably breaks `keepAlive`.
*/
attachmentAgent?: Agent
apiRoot: string
/**
* @default 'bot'
* @see https://github.com/tdlight-team/tdlight-telegram-bot-api#user-mode
*/
apiMode: 'bot' | 'user'
webhookReply: boolean
testEnv: boolean
}
export interface CallApiOptions {
signal?: AbortSignal
}
}
const DEFAULT_EXTENSIONS: Record<string, string | undefined> = {
audio: 'mp3',
photo: 'jpg',
sticker: 'webp',
video: 'mp4',
animation: 'mp4',
video_note: 'mp4',
voice: 'ogg',
}
const DEFAULT_OPTIONS: ApiClient.Options = {
apiRoot: 'https://api.telegram.org',
apiMode: 'bot',
webhookReply: true,
agent: new https.Agent({
keepAlive: true,
keepAliveMsecs: 10000,
}),
attachmentAgent: undefined,
testEnv: false,
}
function includesMedia(payload: Record<string, unknown>) {
return Object.entries(payload).some(([key, value]) => {
if (key === 'link_preview_options') return false
if (Array.isArray(value)) {
return value.some(
({ media }) =>
media && typeof media === 'object' && (media.source || media.url)
)
}
return (
value &&
typeof value === 'object' &&
((hasProp(value, 'source') && value.source) ||
(hasProp(value, 'url') && value.url) ||
(hasPropType(value, 'media', 'object') &&
((hasProp(value.media, 'source') && value.media.source) ||
(hasProp(value.media, 'url') && value.media.url))))
)
})
}
function replacer(_: unknown, value: unknown) {
if (value == null) return undefined
return value
}
function buildJSONConfig(payload: unknown): Promise<RequestInit> {
return Promise.resolve({
method: 'POST',
compress: true,
headers: { 'content-type': 'application/json', connection: 'keep-alive' },
body: JSON.stringify(payload, replacer),
})
}
const FORM_DATA_JSON_FIELDS = [
'results',
'reply_markup',
'mask_position',
'shipping_options',
'errors',
] as const
async function buildFormDataConfig(
payload: Opts<keyof Telegram>,
agent: ApiClient.Agent
) {
for (const field of FORM_DATA_JSON_FIELDS) {
if (hasProp(payload, field) && typeof payload[field] !== 'string') {
payload[field] = JSON.stringify(payload[field])
}
}
const boundary = crypto.randomBytes(32).toString('hex')
const formData = new MultipartStream(boundary)
await Promise.all(
Object.keys(payload).map((key) =>
// @ts-expect-error payload[key] can obviously index payload, but TS doesn't trust us
attachFormValue(formData, key, payload[key], agent)
)
)
return {
method: 'POST',
compress: true,
headers: {
'content-type': `multipart/form-data; boundary=${boundary}`,
connection: 'keep-alive',
},
body: formData,
}
}
async function attachFormValue(
form: MultipartStream,
id: string,
value: unknown,
agent: ApiClient.Agent
) {
if (value == null) {
return
}
if (
typeof value === 'string' ||
typeof value === 'boolean' ||
typeof value === 'number'
) {
form.addPart({
headers: { 'content-disposition': `form-data; name="${id}"` },
body: `${value}`,
})
return
}
if (id === 'thumb' || id === 'thumbnail') {
const attachmentId = crypto.randomBytes(16).toString('hex')
await attachFormMedia(form, value as InputFile, attachmentId, agent)
return form.addPart({
headers: { 'content-disposition': `form-data; name="${id}"` },
body: `attach://${attachmentId}`,
})
}
if (Array.isArray(value)) {
const items = await Promise.all(
value.map(async (item) => {
if (typeof item.media !== 'object') {
return await Promise.resolve(item)
}
const attachmentId = crypto.randomBytes(16).toString('hex')
await attachFormMedia(form, item.media, attachmentId, agent)
const thumb = item.thumb ?? item.thumbnail
if (typeof thumb === 'object') {
const thumbAttachmentId = crypto.randomBytes(16).toString('hex')
await attachFormMedia(form, thumb, thumbAttachmentId, agent)
return {
...item,
media: `attach://${attachmentId}`,
thumbnail: `attach://${thumbAttachmentId}`,
}
}
return { ...item, media: `attach://${attachmentId}` }
})
)
return form.addPart({
headers: { 'content-disposition': `form-data; name="${id}"` },
body: JSON.stringify(items),
})
}
if (
value &&
typeof value === 'object' &&
hasProp(value, 'media') &&
hasProp(value, 'type') &&
typeof value.media !== 'undefined' &&
typeof value.type !== 'undefined'
) {
const attachmentId = crypto.randomBytes(16).toString('hex')
await attachFormMedia(form, value.media as InputFile, attachmentId, agent)
return form.addPart({
headers: { 'content-disposition': `form-data; name="${id}"` },
body: JSON.stringify({
...value,
media: `attach://${attachmentId}`,
}),
})
}
return await attachFormMedia(form, value as InputFile, id, agent)
}
async function attachFormMedia(
form: MultipartStream,
media: InputFile,
id: string,
agent: ApiClient.Agent
) {
let fileName = media.filename ?? `${id}.${DEFAULT_EXTENSIONS[id] ?? 'dat'}`
if ('url' in media && media.url !== undefined) {
const timeout = 500_000 // ms
const res = await fetch(media.url, { agent, timeout })
return form.addPart({
headers: {
'content-disposition': `form-data; name="${id}"; filename="${fileName}"`,
},
body: res.body,
})
}
if ('source' in media && media.source) {
let mediaSource = media.source
if (typeof media.source === 'string') {
const source = await realpath(media.source)
if ((await stat(source)).isFile()) {
fileName = media.filename ?? path.basename(media.source)
mediaSource = await fs.createReadStream(media.source)
} else {
throw new TypeError(`Unable to upload '${media.source}', not a file`)
}
}
if (isStream(mediaSource) || Buffer.isBuffer(mediaSource)) {
form.addPart({
headers: {
'content-disposition': `form-data; name="${id}"; filename="${fileName}"`,
},
body: mediaSource,
})
}
}
}
async function answerToWebhook(
response: Response,
payload: Opts<keyof Telegram>,
options: ApiClient.Options
): Promise<true> {
if (!includesMedia(payload)) {
if (!response.headersSent) {
response.setHeader('content-type', 'application/json')
}
response.end(JSON.stringify(payload), 'utf-8')
return true
}
const { headers, body } = await buildFormDataConfig(
payload,
options.attachmentAgent
)
if (!response.headersSent) {
for (const [key, value] of Object.entries(headers)) {
response.setHeader(key, value)
}
}
await new Promise((resolve) => {
response.on('finish', resolve)
body.pipe(response)
})
return true
}
function redactToken(error: Error): never {
error.message = error.message.replace(
/\/(bot|user)(\d+):[^/]+\//,
'/$1$2:[REDACTED]/'
)
throw error
}
type Response = http.ServerResponse
class ApiClient {
readonly options: ApiClient.Options
constructor(
readonly token: string,
options?: Partial<ApiClient.Options>,
private readonly response?: Response
) {
this.options = {
...DEFAULT_OPTIONS,
...compactOptions(options),
}
if (this.options.apiRoot.startsWith('http://')) {
this.options.agent = undefined
}
}
/**
* If set to `true`, first _eligible_ call will avoid performing a POST request.
* Note that such a call:
* 1. cannot report errors or return meaningful values,
* 2. resolves before bot API has a chance to process it,
* 3. prematurely confirms the update as processed.
*
* https://core.telegram.org/bots/faq#how-can-i-make-requests-in-response-to-updates
* https://github.com/telegraf/telegraf/pull/1250
*/
set webhookReply(enable: boolean) {
this.options.webhookReply = enable
}
get webhookReply() {
return this.options.webhookReply
}
async callApi<M extends keyof Telegram>(
method: M,
payload: Opts<M>,
{ signal }: ApiClient.CallApiOptions = {}
): Promise<ReturnType<Telegram[M]>> {
const { token, options, response } = this
if (
options.webhookReply &&
response?.writableEnded === false &&
WEBHOOK_REPLY_METHOD_ALLOWLIST.has(method)
) {
debug('Call via webhook', method, payload)
// @ts-expect-error using webhookReply is an optimisation that doesn't respond with normal result
// up to the user to deal with this
return await answerToWebhook(response, { method, ...payload }, options)
}
if (!token) {
throw new TelegramError({
error_code: 401,
description: 'Bot Token is required',
})
}
debug('HTTP call', method, payload)
const config: RequestInit = includesMedia(payload)
? await buildFormDataConfig(
{ method, ...payload },
options.attachmentAgent
)
: await buildJSONConfig(payload)
const apiUrl = new URL(
`./${options.apiMode}${token}${options.testEnv ? '/test' : ''}/${method}`,
options.apiRoot
)
config.agent = options.agent
// @ts-expect-error AbortSignal shim is missing some props from Request.AbortSignal
config.signal = signal
config.timeout = 500_000 // ms
const res = await fetch(apiUrl, config).catch(redactToken)
if (res.status >= 500) {
const errorPayload = {
error_code: res.status,
description: res.statusText,
}
throw new TelegramError(errorPayload, { method, payload })
}
const data = await res.json()
if (!data.ok) {
debug('API call failed', data)
throw new TelegramError(data, { method, payload })
}
return data.result
}
}
export default ApiClient

29
node_modules/telegraf/src/core/network/error.ts generated vendored Normal file
View File

@@ -0,0 +1,29 @@
import { ResponseParameters } from '../types/typegram'
interface ErrorPayload {
error_code: number
description: string
parameters?: ResponseParameters
}
export class TelegramError extends Error {
constructor(
readonly response: ErrorPayload,
readonly on = {}
) {
super(`${response.error_code}: ${response.description}`)
}
get code() {
return this.response.error_code
}
get description() {
return this.response.description
}
get parameters() {
return this.response.parameters
}
}
export default TelegramError

View File

@@ -0,0 +1,45 @@
import * as stream from 'stream'
import { hasPropType } from '../helpers/check'
import SandwichStream from 'sandwich-stream'
const CRNL = '\r\n'
interface Part {
headers: { [key: string]: string }
body: NodeJS.ReadStream | NodeJS.ReadableStream | Buffer | string
}
class MultipartStream extends SandwichStream {
constructor(boundary: string) {
super({
head: `--${boundary}${CRNL}`,
tail: `${CRNL}--${boundary}--`,
separator: `${CRNL}--${boundary}${CRNL}`,
})
}
addPart(part: Part) {
const partStream = new stream.PassThrough()
for (const [key, header] of Object.entries(part.headers)) {
partStream.write(`${key}:${header}${CRNL}`)
}
partStream.write(CRNL)
if (MultipartStream.isStream(part.body)) {
part.body.pipe(partStream)
} else {
partStream.end(part.body)
}
this.add(partStream)
}
static isStream(
stream: unknown
): stream is { pipe: MultipartStream['pipe'] } {
return (
typeof stream === 'object' &&
stream !== null &&
hasPropType(stream, 'pipe', 'function')
)
}
}
export default MultipartStream

94
node_modules/telegraf/src/core/network/polling.ts generated vendored Normal file
View File

@@ -0,0 +1,94 @@
import * as tg from '../types/typegram'
import * as tt from '../../telegram-types'
import AbortController from 'abort-controller'
import ApiClient from './client'
import d from 'debug'
import { promisify } from 'util'
import { TelegramError } from './error'
const debug = d('telegraf:polling')
const wait = promisify(setTimeout)
function always<T>(x: T) {
return () => x
}
const noop = always(Promise.resolve())
export class Polling {
private readonly abortController = new AbortController()
private skipOffsetSync = false
private offset = 0
constructor(
private readonly telegram: ApiClient,
private readonly allowedUpdates: readonly tt.UpdateType[]
) {}
private async *[Symbol.asyncIterator]() {
debug('Starting long polling')
do {
try {
const updates = await this.telegram.callApi(
'getUpdates',
{
timeout: 50,
offset: this.offset,
allowed_updates: this.allowedUpdates,
},
this.abortController
)
const last = updates[updates.length - 1]
if (last !== undefined) {
this.offset = last.update_id + 1
}
yield updates
} catch (error) {
const err = error as Error & {
parameters?: { retry_after: number }
}
if (err.name === 'AbortError') return
if (
err.name === 'FetchError' ||
(err instanceof TelegramError && err.code === 429) ||
(err instanceof TelegramError && err.code >= 500)
) {
const retryAfter: number = err.parameters?.retry_after ?? 5
debug('Failed to fetch updates, retrying after %ds.', retryAfter, err)
await wait(retryAfter * 1000)
continue
}
if (
err instanceof TelegramError &&
// Unauthorized Conflict
(err.code === 401 || err.code === 409)
) {
this.skipOffsetSync = true
throw err
}
throw err
}
} while (!this.abortController.signal.aborted)
}
private async syncUpdateOffset() {
if (this.skipOffsetSync) return
debug('Syncing update offset...')
await this.telegram.callApi('getUpdates', { offset: this.offset, limit: 1 })
}
async loop(handleUpdate: (updates: tg.Update) => Promise<void>) {
if (this.abortController.signal.aborted)
throw new Error('Polling instances must not be reused!')
try {
for await (const updates of this)
await Promise.all(updates.map(handleUpdate))
} finally {
debug('Long polling stopped')
// prevent instance reuse
this.stop()
await this.syncUpdateOffset().catch(noop)
}
}
stop() {
this.abortController.abort()
}
}

58
node_modules/telegraf/src/core/network/webhook.ts generated vendored Normal file
View File

@@ -0,0 +1,58 @@
import * as http from 'http'
import d from 'debug'
import { type Update } from '../types/typegram'
const debug = d('telegraf:webhook')
export default function generateWebhook(
filter: (req: http.IncomingMessage) => boolean,
updateHandler: (update: Update, res: http.ServerResponse) => Promise<void>
) {
return async (
req: http.IncomingMessage & { body?: Update },
res: http.ServerResponse,
next = (): void => {
res.statusCode = 403
debug('Replying with status code', res.statusCode)
res.end()
}
): Promise<void> => {
debug('Incoming request', req.method, req.url)
if (!filter(req)) {
debug('Webhook filter failed', req.method, req.url)
return next()
}
let update: Update
try {
if (req.body != null) {
/* If req.body is already set, we expect it to be the parsed
request body (update object) received from Telegram
However, some libraries such as `serverless-http` set req.body to the
raw buffer, so we'll handle that additionally */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let body: any = req.body
// if body is Buffer, parse it into string
if (body instanceof Buffer) body = String(req.body)
// if body is string, parse it into object
if (typeof body === 'string') body = JSON.parse(body)
update = body
} else {
let body = ''
// parse each buffer to string and append to body
for await (const chunk of req) body += String(chunk)
// parse body to object
update = JSON.parse(body)
}
} catch (error: unknown) {
// if any of the parsing steps fails, give up and respond with error
res.writeHead(415).end()
debug('Failed to parse request body:', error)
return
}
return await updateHandler(update, res)
}
}

54
node_modules/telegraf/src/core/types/typegram.ts generated vendored Normal file
View File

@@ -0,0 +1,54 @@
import * as Typegram from '@telegraf/types'
// internal type provisions
export * from '@telegraf/types/api'
export * from '@telegraf/types/inline'
export * from '@telegraf/types/manage'
export * from '@telegraf/types/markup'
export * from '@telegraf/types/message'
export * from '@telegraf/types/methods'
export * from '@telegraf/types/passport'
export * from '@telegraf/types/payment'
export * from '@telegraf/types/settings'
export * from '@telegraf/types/update'
// telegraf input file definition
interface InputFileByPath {
source: string
filename?: string
}
interface InputFileByReadableStream {
source: NodeJS.ReadableStream
filename?: string
}
interface InputFileByBuffer {
source: Buffer
filename?: string
}
interface InputFileByURL {
url: string
filename?: string
}
export type InputFile =
| InputFileByPath
| InputFileByReadableStream
| InputFileByBuffer
| InputFileByURL
export type Telegram = Typegram.ApiMethods<InputFile>
export type Opts<M extends keyof Telegram> = Typegram.Opts<InputFile>[M]
export type InputMedia = Typegram.InputMedia<InputFile>
export type InputMediaPhoto = Typegram.InputMediaPhoto<InputFile>
export type InputMediaVideo = Typegram.InputMediaVideo<InputFile>
export type InputMediaAnimation = Typegram.InputMediaAnimation<InputFile>
export type InputMediaAudio = Typegram.InputMediaAudio<InputFile>
export type InputMediaDocument = Typegram.InputMediaDocument<InputFile>
// tiny helper types
export type ChatAction = Opts<'sendChatAction'>['action']
/**
* Sending video notes by a URL is currently unsupported
*/
export type InputFileVideoNote = Exclude<InputFile, InputFileByURL>

109
node_modules/telegraf/src/filters.ts generated vendored Normal file
View File

@@ -0,0 +1,109 @@
import type {
CallbackQuery,
CommonMessageBundle,
Message,
Update,
} from '@telegraf/types'
import { DistinctKeys, KeyedDistinct, Guarded } from './core/helpers/util'
export type Filter<U extends Update> = (update: Update) => update is U
export { Guarded }
export type AllGuarded<Fs extends Filter<Update>[]> = Fs extends [
infer A,
...infer B,
]
? B extends []
? Guarded<A>
: // TS doesn't know otherwise that B is Filter[]
B extends Filter<Update>[]
? Guarded<A> & AllGuarded<B>
: never
: never
export const message =
<Ks extends DistinctKeys<Message>[]>(...keys: Ks) =>
(
update: Update
): update is Update.MessageUpdate<KeyedDistinct<Message, Ks[number]>> => {
if (!('message' in update)) return false
for (const key of keys) {
if (!(key in update.message)) return false
}
return true
}
export const editedMessage =
<Ks extends DistinctKeys<CommonMessageBundle>[]>(...keys: Ks) =>
(
update: Update
): update is Update.EditedMessageUpdate<
KeyedDistinct<CommonMessageBundle, Ks[number]>
> => {
if (!('edited_message' in update)) return false
for (const key of keys) {
if (!(key in update.edited_message)) return false
}
return true
}
export const channelPost =
<Ks extends DistinctKeys<Message>[]>(...keys: Ks) =>
(
update: Update
): update is Update.ChannelPostUpdate<KeyedDistinct<Message, Ks[number]>> => {
if (!('channel_post' in update)) return false
for (const key of keys) {
if (!(key in update.channel_post)) return false
}
return true
}
export const editedChannelPost =
<Ks extends DistinctKeys<CommonMessageBundle>[]>(...keys: Ks) =>
(
update: Update
): update is Update.EditedChannelPostUpdate<
KeyedDistinct<CommonMessageBundle, Ks[number]>
> => {
if (!('edited_channel_post' in update)) return false
for (const key of keys) {
if (!(key in update.edited_channel_post)) return false
}
return true
}
export const callbackQuery =
<Ks extends DistinctKeys<CallbackQuery>[]>(...keys: Ks) =>
(
update: Update
): update is Update.CallbackQueryUpdate<
KeyedDistinct<CallbackQuery, Ks[number]>
> => {
if (!('callback_query' in update)) return false
for (const key of keys) {
if (!(key in update.callback_query)) return false
}
return true
}
/** Any of the provided filters must match */
export const anyOf =
<Us extends Update[]>(
...filters: {
[UIdx in keyof Us]: Filter<Us[UIdx]>
}
) =>
(update: Update): update is Us[number] => {
for (const filter of filters) if (filter(update)) return true
return false
}
/** All of the provided filters must match */
export const allOf =
<U extends Update, Fs extends Filter<U>[]>(...filters: Fs) =>
(update: Update): update is AllGuarded<Fs> => {
for (const filter of filters) if (!filter(update)) return false
return true
}

110
node_modules/telegraf/src/format.ts generated vendored Normal file
View File

@@ -0,0 +1,110 @@
import { User } from '@telegraf/types'
import {
FmtString,
createFmt,
linkOrMention,
join as _join,
} from './core/helpers/formatting'
export { FmtString }
type Nestable<Kind extends string> = string | number | boolean | FmtString<Kind>
type Nesting<Kind extends string> = [
parts: Nestable<Kind> | readonly Nestable<Kind>[],
...items: Nestable<Kind>[],
]
type Nests<Is extends string, Kind extends string> = (
...args: Nesting<Kind>
) => FmtString<Is>
// Nests<A, B> means the function will return A, and it can nest B
// Nests<'fmt', string> means it will nest anything
// Nests<'code', never> means it will not nest anything
// Allowing everything to nest 'fmt' is a necessary evil; it allows to indirectly nest illegal entities
// Except for 'code' and 'pre', which don't nest anything anyway, so they only deal with strings
export const join = _join as Nests<'fmt', string>
export const fmt = createFmt() as Nests<'fmt', string>
export const bold = createFmt('bold') as Nests<
'bold',
'fmt' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'spoiler'
>
export const italic = createFmt('italic') as Nests<
'italic',
'fmt' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'spoiler'
>
export const spoiler = createFmt('spoiler') as Nests<
'spoiler',
'fmt' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'spoiler'
>
export const strikethrough =
//
createFmt('strikethrough') as Nests<
'strikethrough',
'fmt' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'spoiler'
>
export const underline =
//
createFmt('underline') as Nests<
'underline',
'fmt' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'spoiler'
>
export const quote =
//
createFmt('blockquote') as Nests<
'blockquote',
| 'fmt'
| 'bold'
| 'italic'
| 'underline'
| 'strikethrough'
| 'spoiler'
| 'code'
>
export const code = createFmt('code') as Nests<'code', never>
export const pre = (language: string) =>
createFmt('pre', { language }) as Nests<'pre', never>
export const link = (
content: Nestable<
| 'fmt'
| 'bold'
| 'italic'
| 'underline'
| 'strikethrough'
| 'spoiler'
| 'code'
>,
url: string
) =>
//
linkOrMention(content, { type: 'text_link', url }) as FmtString<'text_link'>
export const mention = (
name: Nestable<
| 'fmt'
| 'bold'
| 'italic'
| 'underline'
| 'strikethrough'
| 'spoiler'
| 'code'
>,
user: number | User
) =>
typeof user === 'number'
? link(name, 'tg://user?id=' + user)
: (linkOrMention(name, {
type: 'text_mention',
user,
}) as FmtString<'text_mention'>)

213
node_modules/telegraf/src/future.ts generated vendored Normal file
View File

@@ -0,0 +1,213 @@
import { ReplyParameters } from '@telegraf/types'
import Context from './context'
import { Middleware } from './middleware'
type ReplyContext = { [key in keyof Context & `reply${string}`]: Context[key] }
function makeReply<
C extends Context,
E extends { reply_parameters?: ReplyParameters },
>(ctx: C, extra?: E) {
if (ctx.msgId)
return {
// overrides in this order so user can override all properties
reply_parameters: {
message_id: ctx.msgId,
...extra?.reply_parameters,
},
...extra,
}
else return extra
}
const replyContext: ReplyContext = {
replyWithChatAction: function () {
throw new TypeError(
'ctx.replyWithChatAction has been removed, use ctx.sendChatAction instead'
)
},
reply(this: Context, text, extra) {
this.assert(this.chat, 'reply')
return this.telegram.sendMessage(this.chat.id, text, makeReply(this, extra))
},
replyWithAnimation(this: Context, animation, extra) {
this.assert(this.chat, 'replyWithAnimation')
return this.telegram.sendAnimation(
this.chat.id,
animation,
makeReply(this, extra)
)
},
replyWithAudio(this: Context, audio, extra) {
this.assert(this.chat, 'replyWithAudio')
return this.telegram.sendAudio(this.chat.id, audio, makeReply(this, extra))
},
replyWithContact(this: Context, phoneNumber, firstName, extra) {
this.assert(this.chat, 'replyWithContact')
return this.telegram.sendContact(
this.chat.id,
phoneNumber,
firstName,
makeReply(this, extra)
)
},
replyWithDice(this: Context, extra) {
this.assert(this.chat, 'replyWithDice')
return this.telegram.sendDice(this.chat.id, makeReply(this, extra))
},
replyWithDocument(this: Context, document, extra) {
this.assert(this.chat, 'replyWithDocument')
return this.telegram.sendDocument(
this.chat.id,
document,
makeReply(this, extra)
)
},
replyWithGame(this: Context, gameName, extra) {
this.assert(this.chat, 'replyWithGame')
return this.telegram.sendGame(
this.chat.id,
gameName,
makeReply(this, extra)
)
},
replyWithHTML(this: Context, html, extra) {
this.assert(this.chat, 'replyWithHTML')
return this.telegram.sendMessage(this.chat.id, html, {
parse_mode: 'HTML',
...makeReply(this, extra),
})
},
replyWithInvoice(this: Context, invoice, extra) {
this.assert(this.chat, 'replyWithInvoice')
return this.telegram.sendInvoice(
this.chat.id,
invoice,
makeReply(this, extra)
)
},
replyWithLocation(this: Context, latitude, longitude, extra) {
this.assert(this.chat, 'replyWithLocation')
return this.telegram.sendLocation(
this.chat.id,
latitude,
longitude,
makeReply(this, extra)
)
},
replyWithMarkdown(this: Context, markdown, extra) {
this.assert(this.chat, 'replyWithMarkdown')
return this.telegram.sendMessage(this.chat.id, markdown, {
parse_mode: 'Markdown',
...makeReply(this, extra),
})
},
replyWithMarkdownV2(this: Context, markdown, extra) {
this.assert(this.chat, 'replyWithMarkdownV2')
return this.telegram.sendMessage(this.chat.id, markdown, {
parse_mode: 'MarkdownV2',
...makeReply(this, extra),
})
},
replyWithMediaGroup(this: Context, media, extra) {
this.assert(this.chat, 'replyWithMediaGroup')
return this.telegram.sendMediaGroup(
this.chat.id,
media,
makeReply(this, extra)
)
},
replyWithPhoto(this: Context, photo, extra) {
this.assert(this.chat, 'replyWithPhoto')
return this.telegram.sendPhoto(this.chat.id, photo, makeReply(this, extra))
},
replyWithPoll(this: Context, question, options, extra) {
this.assert(this.chat, 'replyWithPoll')
return this.telegram.sendPoll(
this.chat.id,
question,
options,
makeReply(this, extra)
)
},
replyWithQuiz(this: Context, question, options, extra) {
this.assert(this.chat, 'replyWithQuiz')
return this.telegram.sendQuiz(
this.chat.id,
question,
options,
makeReply(this, extra)
)
},
replyWithSticker(this: Context, sticker, extra) {
this.assert(this.chat, 'replyWithSticker')
return this.telegram.sendSticker(
this.chat.id,
sticker,
makeReply(this, extra)
)
},
replyWithVenue(this: Context, latitude, longitude, title, address, extra) {
this.assert(this.chat, 'replyWithVenue')
return this.telegram.sendVenue(
this.chat.id,
latitude,
longitude,
title,
address,
makeReply(this, extra)
)
},
replyWithVideo(this: Context, video, extra) {
this.assert(this.chat, 'replyWithVideo')
return this.telegram.sendVideo(this.chat.id, video, makeReply(this, extra))
},
replyWithVideoNote(this: Context, videoNote, extra) {
this.assert(this.chat, 'replyWithVideoNote')
return this.telegram.sendVideoNote(
this.chat.id,
videoNote,
makeReply(this, extra)
)
},
replyWithVoice(this: Context, voice, extra) {
this.assert(this.chat, 'replyWithVoice')
return this.telegram.sendVoice(this.chat.id, voice, makeReply(this, extra))
},
}
/**
* Sets up Context to use the new reply methods.
* This middleware makes `ctx.reply()` and `ctx.replyWith*()` methods will actually reply to the message they are replying to.
* Use `ctx.sendMessage()` to send a message in chat without replying to it.
*
* If the message to reply is deleted, `reply()` will send a normal message.
* If the update is not a message and we are unable to reply, `reply()` will send a normal message.
*/
export function useNewReplies<C extends Context>(): Middleware<C> {
return (ctx, next) => {
ctx.reply = replyContext.reply
ctx.replyWithPhoto = replyContext.replyWithPhoto
ctx.replyWithMediaGroup = replyContext.replyWithMediaGroup
ctx.replyWithAudio = replyContext.replyWithAudio
ctx.replyWithDice = replyContext.replyWithDice
ctx.replyWithDocument = replyContext.replyWithDocument
ctx.replyWithSticker = replyContext.replyWithSticker
ctx.replyWithVideo = replyContext.replyWithVideo
ctx.replyWithAnimation = replyContext.replyWithAnimation
ctx.replyWithVideoNote = replyContext.replyWithVideoNote
ctx.replyWithInvoice = replyContext.replyWithInvoice
ctx.replyWithGame = replyContext.replyWithGame
ctx.replyWithVoice = replyContext.replyWithVoice
ctx.replyWithPoll = replyContext.replyWithPoll
ctx.replyWithQuiz = replyContext.replyWithQuiz
ctx.replyWithChatAction = replyContext.replyWithChatAction
ctx.replyWithLocation = replyContext.replyWithLocation
ctx.replyWithVenue = replyContext.replyWithVenue
ctx.replyWithContact = replyContext.replyWithContact
ctx.replyWithMarkdown = replyContext.replyWithMarkdown
ctx.replyWithMarkdownV2 = replyContext.replyWithMarkdownV2
ctx.replyWithHTML = replyContext.replyWithHTML
return next()
}
}

17
node_modules/telegraf/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
export { Telegraf } from './telegraf'
export { Context, NarrowedContext } from './context'
export { Composer } from './composer'
export { Middleware, MiddlewareFn, MiddlewareObj } from './middleware'
export { Router } from './router'
export { TelegramError } from './core/network/error'
export { Telegram } from './telegram'
export * as Types from './telegram-types'
export * as Markup from './markup'
export * as Input from './input'
export * as Format from './format'
export { deunionize } from './core/helpers/deunionize'
export { session, MemorySessionStore, SessionStore } from './session'
export * as Scenes from './scenes'

59
node_modules/telegraf/src/input.ts generated vendored Normal file
View File

@@ -0,0 +1,59 @@
import { InputFile } from './core/types/typegram'
/**
* The local file specified by path will be uploaded to Telegram using multipart/form-data.
*
* 10 MB max size for photos, 50 MB for other files.
*/
// prettier-ignore
export const fromLocalFile = (path: string, filename?: string): InputFile => ({ source: path, filename })
/**
* The buffer will be uploaded as file to Telegram using multipart/form-data.
*
* 10 MB max size for photos, 50 MB for other files.
*/
// prettier-ignore
export const fromBuffer = (buffer: Buffer, filename?: string): InputFile => ({ source: buffer, filename })
/**
* Contents of the stream will be uploaded as file to Telegram using multipart/form-data.
*
* 10 MB max size for photos, 50 MB for other files.
*/
// prettier-ignore
export const fromReadableStream = (stream: NodeJS.ReadableStream, filename?: string): InputFile => ({ source: stream, filename })
/**
* Contents of the URL will be streamed to Telegram.
*
* 10 MB max size for photos, 50 MB for other files.
*/
// prettier-ignore
export const fromURLStream = (url: string | URL, filename?: string): InputFile => ({ url: url.toString(), filename })
/**
* Provide Telegram with an HTTP URL for the file to be sent.
* Telegram will download and send the file.
*
* * The target file must have the correct MIME type (e.g., audio/mpeg for `sendAudio`, etc.).
* * `sendDocument` with URL will currently only work for GIF, PDF and ZIP files.
* * To use `sendVoice`, the file must have the type audio/ogg and be no more than 1MB in size.
* 1-20MB voice notes will be sent as files.
*
* 5 MB max size for photos and 20 MB max for other types of content.
*/
export const fromURL = (url: string | URL): string => url.toString()
/**
* If the file is already stored somewhere on the Telegram servers, you don't need to reupload it:
* each file object has a file_id field, simply pass this file_id as a parameter instead of uploading.
*
* It is not possible to change the file type when resending by file_id.
*
* It is not possible to resend thumbnails using file_id.
* They have to be uploaded using one of the other Input methods.
*
* There are no limits for files sent this way.
*/
export const fromFileId = (fileId: string): string => fileId

142
node_modules/telegraf/src/markup.ts generated vendored Normal file
View File

@@ -0,0 +1,142 @@
import {
ForceReply,
InlineKeyboardButton,
InlineKeyboardMarkup,
KeyboardButton,
ReplyKeyboardMarkup,
ReplyKeyboardRemove,
} from './core/types/typegram'
import { is2D } from './core/helpers/check'
type Hideable<B> = B & { hide?: boolean }
type HideableKBtn = Hideable<KeyboardButton>
type HideableIKBtn = Hideable<InlineKeyboardButton>
export class Markup<
T extends
| InlineKeyboardMarkup
| ReplyKeyboardMarkup
| ReplyKeyboardRemove
| ForceReply,
> {
constructor(readonly reply_markup: T) {}
selective<T extends ForceReply | ReplyKeyboardMarkup>(
this: Markup<T>,
value = true
) {
return new Markup<T>({ ...this.reply_markup, selective: value })
}
placeholder<T extends ForceReply | ReplyKeyboardMarkup>(
this: Markup<T>,
placeholder: string
) {
return new Markup<T>({
...this.reply_markup,
input_field_placeholder: placeholder,
})
}
resize(this: Markup<ReplyKeyboardMarkup>, value = true) {
return new Markup<ReplyKeyboardMarkup>({
...this.reply_markup,
resize_keyboard: value,
})
}
oneTime(this: Markup<ReplyKeyboardMarkup>, value = true) {
return new Markup<ReplyKeyboardMarkup>({
...this.reply_markup,
one_time_keyboard: value,
})
}
persistent(this: Markup<ReplyKeyboardMarkup>, value = true) {
return new Markup<ReplyKeyboardMarkup>({
...this.reply_markup,
is_persistent: value,
})
}
}
export * as button from './button'
export function removeKeyboard(): Markup<ReplyKeyboardRemove> {
return new Markup<ReplyKeyboardRemove>({ remove_keyboard: true })
}
export function forceReply(): Markup<ForceReply> {
return new Markup<ForceReply>({ force_reply: true })
}
export function keyboard(buttons: HideableKBtn[][]): Markup<ReplyKeyboardMarkup>
export function keyboard(
buttons: HideableKBtn[],
options?: Partial<KeyboardBuildingOptions<HideableKBtn>>
): Markup<ReplyKeyboardMarkup>
export function keyboard(
buttons: HideableKBtn[] | HideableKBtn[][],
options?: Partial<KeyboardBuildingOptions<HideableKBtn>>
): Markup<ReplyKeyboardMarkup> {
const keyboard = buildKeyboard(buttons, {
columns: 1,
...options,
})
return new Markup<ReplyKeyboardMarkup>({ keyboard })
}
export function inlineKeyboard(
buttons: HideableIKBtn[][]
): Markup<InlineKeyboardMarkup>
export function inlineKeyboard(
buttons: HideableIKBtn[],
options?: Partial<KeyboardBuildingOptions<HideableIKBtn>>
): Markup<InlineKeyboardMarkup>
export function inlineKeyboard(
buttons: HideableIKBtn[] | HideableIKBtn[][],
options?: Partial<KeyboardBuildingOptions<HideableIKBtn>>
): Markup<InlineKeyboardMarkup> {
const inlineKeyboard = buildKeyboard(buttons, {
columns: buttons.length,
...options,
})
return new Markup<InlineKeyboardMarkup>({ inline_keyboard: inlineKeyboard })
}
interface KeyboardBuildingOptions<B extends HideableKBtn | HideableIKBtn> {
wrap?: (btn: B, index: number, currentRow: B[]) => boolean
columns: number
}
function buildKeyboard<B extends HideableKBtn | HideableIKBtn>(
buttons: B[] | B[][],
options: KeyboardBuildingOptions<B>
): B[][] {
const result: B[][] = []
if (!Array.isArray(buttons)) {
return result
}
if (is2D(buttons)) {
return buttons.map((row) => row.filter((button) => !button.hide))
}
const wrapFn =
options.wrap !== undefined
? options.wrap
: (_btn: B, _index: number, currentRow: B[]) =>
currentRow.length >= options.columns
let currentRow: B[] = []
let index = 0
for (const btn of buttons.filter((button) => !button.hide)) {
if (wrapFn(btn, index, currentRow) && currentRow.length > 0) {
result.push(currentRow)
currentRow = []
}
currentRow.push(btn)
index++
}
if (currentRow.length > 0) {
result.push(currentRow)
}
return result
}

24
node_modules/telegraf/src/middleware.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { Context } from './context'
import { Update } from './core/types/typegram'
/*
next's parameter is in a contravariant position, and thus, trying to type it
prevents assigning `MiddlewareFn<ContextMessageUpdate>`
to `MiddlewareFn<CustomContext>`.
Middleware passing the parameter should be a separate type instead.
*/
export type MiddlewareFn<C extends Context<U>, U extends Update = Update> = (
ctx: C,
next: () => Promise<void>
) => Promise<unknown> | void
export interface MiddlewareObj<
C extends Context<U>,
U extends Update = Update,
> {
middleware: () => MiddlewareFn<C, U>
}
export type Middleware<C extends Context<U>, U extends Update = Update> =
| MiddlewareFn<C, U>
| MiddlewareObj<C, U>

118
node_modules/telegraf/src/reactions.ts generated vendored Normal file
View File

@@ -0,0 +1,118 @@
import { Deunionize } from './core/helpers/deunionize'
import { indexed } from './core/helpers/util'
import * as tg from './core/types/typegram'
export type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
export const Digit = new Set(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])
export type Reaction =
| tg.TelegramEmoji
| `${Digit}${string}`
| Deunionize<tg.ReactionType>
type ReactionCtx = { update: Partial<tg.Update.MessageReactionUpdate> }
const inspectReaction = (reaction: tg.ReactionType) => {
if (reaction.type === 'custom_emoji')
return `Custom(${reaction.custom_emoji_id})`
else return reaction.emoji
}
export class ReactionList {
// this is a lie, proxy will be used to access the properties
[index: number]: Deunionize<tg.ReactionType>
protected constructor(protected list: tg.ReactionType[]) {}
static fromArray(list: tg.ReactionType[] = []): ReactionList {
return indexed(
new ReactionList(list),
function (this: ReactionList, index) {
return this.list[index]
}
)
}
static has(reactions: tg.ReactionType[], reaction: Reaction): boolean {
if (typeof reaction === 'string')
if (Digit.has(reaction[0] as string))
return reactions.some(
(r: Deunionize<tg.ReactionType>) => r.custom_emoji_id === reaction
)
else
return reactions.some(
(r: Deunionize<tg.ReactionType>) => r.emoji === reaction
)
return reactions.some((r: Deunionize<tg.ReactionType>) => {
if (r.type === 'custom_emoji')
return r.custom_emoji_id === reaction.custom_emoji_id
else if (r.type === 'emoji') return r.emoji === reaction.emoji
})
}
toArray(): tg.ReactionType[] {
return [...this.list]
}
filter(
filterFn: (value: tg.ReactionType, index: number) => boolean
): ReactionList {
return ReactionList.fromArray(this.list.filter(filterFn))
}
has(reaction: Reaction): boolean {
return ReactionList.has(this.list, reaction)
}
get count(): number {
return this.list.length
}
[Symbol.iterator]() {
return this.list[Symbol.iterator]()
}
[Symbol.for('nodejs.util.inspect.custom')]() {
const flattened = this.list.map(inspectReaction).join(', ')
return ['ReactionList {', flattened, '}'].join(' ')
}
}
export class MessageReactions extends ReactionList {
private constructor(public ctx: ReactionCtx) {
super(ctx.update.message_reaction?.new_reaction ?? [])
}
static from(ctx: ReactionCtx) {
return indexed(
new MessageReactions(ctx),
function (this: MessageReactions, index) {
return this.list[index]
}
)
}
get old() {
return ReactionList.fromArray(
this.ctx.update.message_reaction?.old_reaction
)
}
get new() {
return ReactionList.fromArray(
this.ctx.update.message_reaction?.new_reaction
)
}
get added(): ReactionList {
return this.new.filter((reaction) => !this.old.has(reaction))
}
get removed(): ReactionList {
return this.old.filter((reaction) => !this.new.has(reaction))
}
get kept(): ReactionList {
return this.new.filter((reaction) => this.old.has(reaction))
}
}

55
node_modules/telegraf/src/router.ts generated vendored Normal file
View File

@@ -0,0 +1,55 @@
/** @format */
import { Middleware, MiddlewareObj } from './middleware'
import Composer from './composer'
import Context from './context'
type NonemptyReadonlyArray<T> = readonly [T, ...T[]]
type RouteFn<TContext extends Context> = (ctx: TContext) => {
route: string
context?: Partial<TContext>
state?: Partial<TContext['state']>
} | null
/** @deprecated in favor of {@link Composer.dispatch} */
export class Router<C extends Context> implements MiddlewareObj<C> {
private otherwiseHandler: Middleware<C> = Composer.passThru()
constructor(
private readonly routeFn: RouteFn<C>,
public handlers = new Map<string, Middleware<C>>()
) {
if (typeof routeFn !== 'function') {
throw new Error('Missing routing function')
}
}
on(route: string, ...fns: NonemptyReadonlyArray<Middleware<C>>) {
if (fns.length === 0) {
throw new TypeError('At least one handler must be provided')
}
this.handlers.set(route, Composer.compose(fns))
return this
}
otherwise(...fns: NonemptyReadonlyArray<Middleware<C>>) {
if (fns.length === 0) {
throw new TypeError('At least one otherwise handler must be provided')
}
this.otherwiseHandler = Composer.compose(fns)
return this
}
middleware() {
return Composer.lazy<C>((ctx) => {
const result = this.routeFn(ctx)
if (result == null) {
return this.otherwiseHandler
}
Object.assign(ctx, result.context)
Object.assign(ctx.state, result.state)
return this.handlers.get(result.route) ?? this.otherwiseHandler
})
}
}

1
node_modules/telegraf/src/scenes.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './scenes/index.js'

52
node_modules/telegraf/src/scenes/base.ts generated vendored Normal file
View File

@@ -0,0 +1,52 @@
import { Middleware, MiddlewareFn } from '../middleware'
import Composer from '../composer'
import Context from '../context'
const { compose } = Composer
export interface SceneOptions<C extends Context> {
ttl?: number
handlers: ReadonlyArray<MiddlewareFn<C>>
enterHandlers: ReadonlyArray<MiddlewareFn<C>>
leaveHandlers: ReadonlyArray<MiddlewareFn<C>>
}
export class BaseScene<C extends Context = Context> extends Composer<C> {
id: string
ttl?: number
enterHandler: MiddlewareFn<C>
leaveHandler: MiddlewareFn<C>
constructor(id: string, options?: SceneOptions<C>) {
const opts: SceneOptions<C> = {
handlers: [],
enterHandlers: [],
leaveHandlers: [],
...options,
}
super(...opts.handlers)
this.id = id
this.ttl = opts.ttl
this.enterHandler = compose(opts.enterHandlers)
this.leaveHandler = compose(opts.leaveHandlers)
}
enter(...fns: Array<Middleware<C>>) {
this.enterHandler = compose([this.enterHandler, ...fns])
return this
}
leave(...fns: Array<Middleware<C>>) {
this.leaveHandler = compose([this.leaveHandler, ...fns])
return this
}
enterMiddleware() {
return this.enterHandler
}
leaveMiddleware() {
return this.leaveHandler
}
}
export default BaseScene

136
node_modules/telegraf/src/scenes/context.ts generated vendored Normal file
View File

@@ -0,0 +1,136 @@
import BaseScene from './base'
import Composer from '../composer'
import Context from '../context'
import d from 'debug'
import { SessionContext } from '../session'
const debug = d('telegraf:scenes:context')
const noop = () => Promise.resolve()
const now = () => Math.floor(Date.now() / 1000)
export interface SceneContext<D extends SceneSessionData = SceneSessionData>
extends Context {
session: SceneSession<D>
scene: SceneContextScene<SceneContext<D>, D>
}
export interface SceneSessionData {
current?: string
expires?: number
state?: object
}
export interface SceneSession<S extends SceneSessionData = SceneSessionData> {
__scenes?: S
}
export interface SceneContextSceneOptions<D extends SceneSessionData> {
ttl?: number
default?: string
defaultSession: D
}
export default class SceneContextScene<
C extends SessionContext<SceneSession<D>>,
D extends SceneSessionData = SceneSessionData,
> {
private readonly options: SceneContextSceneOptions<D>
constructor(
private readonly ctx: C,
private readonly scenes: Map<string, BaseScene<C>>,
options: Partial<SceneContextSceneOptions<D>>
) {
// @ts-expect-error {} might not be assignable to D
const fallbackSessionDefault: D = {}
this.options = { defaultSession: fallbackSessionDefault, ...options }
}
get session(): D {
const defaultSession = Object.assign({}, this.options.defaultSession)
let session = this.ctx.session?.__scenes ?? defaultSession
if (session.expires !== undefined && session.expires < now()) {
session = defaultSession
}
if (this.ctx.session === undefined) {
this.ctx.session = { __scenes: session }
} else {
this.ctx.session.__scenes = session
}
return session
}
get state() {
return (this.session.state ??= {})
}
set state(value) {
this.session.state = { ...value }
}
get current() {
const sceneId = this.session.current ?? this.options.default
return sceneId === undefined || !this.scenes.has(sceneId)
? undefined
: this.scenes.get(sceneId)
}
reset() {
if (this.ctx.session !== undefined)
this.ctx.session.__scenes = Object.assign({}, this.options.defaultSession)
}
async enter(sceneId: string, initialState: object = {}, silent = false) {
if (!this.scenes.has(sceneId)) {
throw new Error(`Can't find scene: ${sceneId}`)
}
if (!silent) {
await this.leave()
}
debug('Entering scene', sceneId, initialState, silent)
this.session.current = sceneId
this.state = initialState
const ttl = this.current?.ttl ?? this.options.ttl
if (ttl !== undefined) {
this.session.expires = now() + ttl
}
if (this.current === undefined || silent) {
return
}
const handler =
'enterMiddleware' in this.current &&
typeof this.current.enterMiddleware === 'function'
? this.current.enterMiddleware()
: this.current.middleware()
return await handler(this.ctx, noop)
}
reenter() {
return this.session.current === undefined
? undefined
: this.enter(this.session.current, this.state)
}
private leaving = false
async leave() {
if (this.leaving) return
debug('Leaving scene')
try {
this.leaving = true
if (this.current === undefined) {
return
}
const handler =
'leaveMiddleware' in this.current &&
typeof this.current.leaveMiddleware === 'function'
? this.current.leaveMiddleware()
: Composer.passThru()
await handler(this.ctx, noop)
return this.reset()
} finally {
this.leaving = false
}
}
}

21
node_modules/telegraf/src/scenes/index.ts generated vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* @see https://github.com/telegraf/telegraf/issues/705#issuecomment-549056045
* @see https://www.npmjs.com/package/telegraf-stateless-question
* @packageDocumentation
*/
export { Stage } from './stage'
export {
SceneContext,
SceneSession,
default as SceneContextScene,
SceneSessionData,
} from './context'
export { BaseScene } from './base'
export { WizardScene } from './wizard'
export {
WizardContext,
WizardSession,
default as WizardContextWizard,
WizardSessionData,
} from './wizard/context'

71
node_modules/telegraf/src/scenes/stage.ts generated vendored Normal file
View File

@@ -0,0 +1,71 @@
import { isSessionContext, SessionContext } from '../session'
import SceneContextScene, {
SceneContextSceneOptions,
SceneSession,
SceneSessionData,
} from './context'
import { BaseScene } from './base'
import { Composer } from '../composer'
import { Context } from '../context'
export class Stage<
C extends SessionContext<SceneSession<D>> & {
scene: SceneContextScene<C, D>
},
D extends SceneSessionData = SceneSessionData,
> extends Composer<C> {
options: Partial<SceneContextSceneOptions<D>>
scenes: Map<string, BaseScene<C>>
constructor(
scenes: ReadonlyArray<BaseScene<C>> = [],
options?: Partial<SceneContextSceneOptions<D>>
) {
super()
this.options = { ...options }
this.scenes = new Map<string, BaseScene<C>>()
scenes.forEach((scene) => this.register(scene))
}
register(...scenes: ReadonlyArray<BaseScene<C>>) {
scenes.forEach((scene) => {
if (scene?.id == null || typeof scene.middleware !== 'function') {
throw new Error('telegraf: Unsupported scene')
}
this.scenes.set(scene.id, scene)
})
return this
}
middleware() {
const handler = Composer.compose<C>([
(ctx, next) => {
const scenes: Map<string, BaseScene<C>> = this.scenes
const scene = new SceneContextScene<C, D>(ctx, scenes, this.options)
ctx.scene = scene
return next()
},
super.middleware(),
Composer.lazy<C>((ctx) => ctx.scene.current ?? Composer.passThru()),
])
return Composer.optional(isSessionContext, handler)
}
static enter<C extends Context & { scene: SceneContextScene<C> }>(
...args: Parameters<SceneContextScene<C>['enter']>
) {
return (ctx: C) => ctx.scene.enter(...args)
}
static reenter<C extends Context & { scene: SceneContextScene<C> }>(
...args: Parameters<SceneContextScene<C>['reenter']>
) {
return (ctx: C) => ctx.scene.reenter(...args)
}
static leave<C extends Context & { scene: SceneContextScene<C> }>(
...args: Parameters<SceneContextScene<C>['leave']>
) {
return (ctx: C) => ctx.scene.leave(...args)
}
}

58
node_modules/telegraf/src/scenes/wizard/context.ts generated vendored Normal file
View File

@@ -0,0 +1,58 @@
import SceneContextScene, { SceneSession, SceneSessionData } from '../context'
import Context from '../../context'
import { Middleware } from '../../middleware'
import { SessionContext } from '../../session'
export interface WizardContext<D extends WizardSessionData = WizardSessionData>
extends Context {
session: WizardSession<D>
scene: SceneContextScene<WizardContext<D>, D>
wizard: WizardContextWizard<WizardContext<D>>
}
export interface WizardSessionData extends SceneSessionData {
cursor: number
}
export interface WizardSession<S extends WizardSessionData = WizardSessionData>
extends SceneSession<S> {}
export default class WizardContextWizard<
C extends SessionContext<WizardSession> & {
scene: SceneContextScene<C, WizardSessionData>
},
> {
readonly state: object
constructor(
private readonly ctx: C,
private readonly steps: ReadonlyArray<Middleware<C>>
) {
this.state = ctx.scene.state
this.cursor = ctx.scene.session.cursor ?? 0
}
get step() {
return this.steps[this.cursor]
}
get cursor() {
return this.ctx.scene.session.cursor
}
set cursor(cursor: number) {
this.ctx.scene.session.cursor = cursor
}
selectStep(index: number) {
this.cursor = index
return this
}
next() {
return this.selectStep(this.cursor + 1)
}
back() {
return this.selectStep(this.cursor - 1)
}
}

63
node_modules/telegraf/src/scenes/wizard/index.ts generated vendored Normal file
View File

@@ -0,0 +1,63 @@
import BaseScene, { SceneOptions } from '../base'
import { Middleware, MiddlewareObj } from '../../middleware'
import WizardContextWizard, { WizardSessionData } from './context'
import Composer from '../../composer'
import Context from '../../context'
import SceneContextScene from '../context'
export class WizardScene<
C extends Context & {
scene: SceneContextScene<C, WizardSessionData>
wizard: WizardContextWizard<C>
},
>
extends BaseScene<C>
implements MiddlewareObj<C>
{
steps: Array<Middleware<C>>
constructor(id: string, ...steps: Array<Middleware<C>>)
constructor(
id: string,
options: SceneOptions<C>,
...steps: Array<Middleware<C>>
)
constructor(
id: string,
options: SceneOptions<C> | Middleware<C>,
...steps: Array<Middleware<C>>
) {
let opts: SceneOptions<C> | undefined
let s: Array<Middleware<C>>
if (typeof options === 'function' || 'middleware' in options) {
opts = undefined
s = [options, ...steps]
} else {
opts = options
s = steps
}
super(id, opts)
this.steps = s
}
middleware() {
return Composer.compose<C>([
(ctx, next) => {
ctx.wizard = new WizardContextWizard<C>(ctx, this.steps)
return next()
},
super.middleware(),
(ctx, next) => {
if (ctx.wizard.step === undefined) {
ctx.wizard.selectStep(0)
return ctx.scene.leave()
}
return Composer.unwrap(ctx.wizard.step)(ctx, next)
},
])
}
enterMiddleware() {
return Composer.compose([this.enterHandler, this.middleware()])
}
}

204
node_modules/telegraf/src/session.ts generated vendored Normal file
View File

@@ -0,0 +1,204 @@
import { Context } from './context'
import { ExclusiveKeys, MaybePromise } from './core/helpers/util'
import { MiddlewareFn } from './middleware'
import d from 'debug'
const debug = d('telegraf:session')
export interface SyncSessionStore<T> {
get: (name: string) => T | undefined
set: (name: string, value: T) => void
delete: (name: string) => void
}
export interface AsyncSessionStore<T> {
get: (name: string) => Promise<T | undefined>
set: (name: string, value: T) => Promise<unknown>
delete: (name: string) => Promise<unknown>
}
export type SessionStore<T> = SyncSessionStore<T> | AsyncSessionStore<T>
interface SessionOptions<S, C extends Context, P extends string> {
/** Customise the session prop. Defaults to "session" and is available as ctx.session. */
property?: P
getSessionKey?: (ctx: C) => MaybePromise<string | undefined>
store?: SessionStore<S>
defaultSession?: (ctx: C) => S
}
/** @deprecated session can use custom properties now. Construct this type directly. */
export interface SessionContext<S extends object> extends Context {
session?: S
}
/**
* Returns middleware that adds `ctx.session` for storing arbitrary state per session key.
*
* The default `getSessionKey` is `${ctx.from.id}:${ctx.chat.id}`.
* If either `ctx.from` or `ctx.chat` is `undefined`, default session key and thus `ctx.session` are also `undefined`.
*
* > ⚠️ Session data is kept only in memory by default, which means that all data will be lost when the process is terminated.
* >
* > If you want to persist data across process restarts, or share it among multiple instances, you should use
* [@telegraf/session](https://www.npmjs.com/package/@telegraf/session), or pass custom `storage`.
*
* @see {@link https://github.com/feathers-studio/telegraf-docs/blob/b694bcc36b4f71fb1cd650a345c2009ab4d2a2a5/guide/session.md Telegraf Docs | Session}
* @see {@link https://github.com/feathers-studio/telegraf-docs/blob/master/examples/session-bot.ts Example}
*/
export function session<
S extends NonNullable<C[P]>,
C extends Context & { [key in P]?: C[P] },
P extends (ExclusiveKeys<C, Context> & string) | 'session' = 'session',
// ^ Only allow prop names that aren't keys in base Context.
// At type level, this is cosmetic. To not get cluttered with all Context keys.
>(options?: SessionOptions<S, C, P>): MiddlewareFn<C> {
const prop = options?.property ?? ('session' as P)
const getSessionKey = options?.getSessionKey ?? defaultGetSessionKey
const store = options?.store ?? new MemorySessionStore()
// caches value from store in-memory while simultaneous updates share it
// when counter reaches 0, the cached ref will be freed from memory
const cache = new Map<string, { ref?: S; counter: number }>()
// temporarily stores concurrent requests
const concurrents = new Map<string, MaybePromise<S | undefined>>()
// this function must be handled with care
// read full description on the original PR: https://github.com/telegraf/telegraf/pull/1713
// make sure to update the tests in test/session.js if you make any changes or fix bugs here
return async (ctx, next) => {
const updId = ctx.update.update_id
let released = false
function releaseChecks() {
if (released && process.env.EXPERIMENTAL_SESSION_CHECKS)
throw new Error(
"Session was accessed or assigned to after the middleware chain exhausted. This is a bug in your code. You're probably accessing session asynchronously and missing awaits."
)
}
// because this is async, requests may still race here, but it will get autocorrected at (1)
// v5 getSessionKey should probably be synchronous to avoid that
const key = await getSessionKey(ctx)
if (!key) {
// Leaving this here could be useful to check for `prop in ctx` in future middleware
ctx[prop] = undefined as unknown as S
return await next()
}
let cached = cache.get(key)
if (cached) {
debug(`(${updId}) found cached session, reusing from cache`)
++cached.counter
} else {
debug(`(${updId}) did not find cached session`)
// if another concurrent request has already sent a store request, fetch that instead
let promise = concurrents.get(key)
if (promise)
debug(`(${updId}) found a concurrent request, reusing promise`)
else {
debug(`(${updId}) fetching from upstream store`)
promise = store.get(key)
}
// synchronously store promise so concurrent requests can share response
concurrents.set(key, promise)
const upstream = await promise
// all concurrent awaits will have promise in their closure, safe to remove now
concurrents.delete(key)
debug(`(${updId}) updating cache`)
// another request may have beaten us to the punch
const c = cache.get(key)
if (c) {
// another request did beat us to the punch
c.counter++
// (1) preserve cached reference; in-memory reference is always newer than from store
cached = c
} else {
// we're the first, so we must cache the reference
cached = { ref: upstream ?? options?.defaultSession?.(ctx), counter: 1 }
cache.set(key, cached)
}
}
// TS already knows cached is always defined by this point, but does not guard cached.
// It will, however, guard `c` here.
const c = cached
let touched = false
Object.defineProperty(ctx, prop, {
get() {
releaseChecks()
touched = true
return c.ref
},
set(value: S) {
releaseChecks()
touched = true
c.ref = value
},
})
try {
await next()
released = true
} finally {
if (--c.counter === 0) {
// decrement to avoid memory leak
debug(`(${updId}) refcounter reached 0, removing cached`)
cache.delete(key)
}
debug(`(${updId}) middlewares completed, checking session`)
// only update store if ctx.session was touched
if (touched)
if (c.ref == null) {
debug(`(${updId}) ctx.${prop} missing, removing from store`)
await store.delete(key)
} else {
debug(`(${updId}) ctx.${prop} found, updating store`)
await store.set(key, c.ref)
}
}
}
}
function defaultGetSessionKey(ctx: Context): string | undefined {
const fromId = ctx.from?.id
const chatId = ctx.chat?.id
if (fromId == null || chatId == null) return undefined
return `${fromId}:${chatId}`
}
/** @deprecated Use `Map` */
export class MemorySessionStore<T> implements SyncSessionStore<T> {
private readonly store = new Map<string, { session: T; expires: number }>()
constructor(private readonly ttl = Infinity) {}
get(name: string): T | undefined {
const entry = this.store.get(name)
if (entry == null) {
return undefined
} else if (entry.expires < Date.now()) {
this.delete(name)
return undefined
}
return entry.session
}
set(name: string, value: T): void {
const now = Date.now()
this.store.set(name, { session: value, expires: now + this.ttl })
}
delete(name: string): void {
this.store.delete(name)
}
}
/** @deprecated session can use custom properties now. Directly use `'session' in ctx` instead */
export function isSessionContext<S extends object>(
ctx: Context
): ctx is SessionContext<S> {
return 'session' in ctx
}

354
node_modules/telegraf/src/telegraf.ts generated vendored Normal file
View File

@@ -0,0 +1,354 @@
import * as crypto from 'crypto'
import * as http from 'http'
import * as https from 'https'
import * as tg from './core/types/typegram'
import * as tt from './telegram-types'
import { Composer } from './composer'
import { MaybePromise } from './core/helpers/util'
import ApiClient from './core/network/client'
import { compactOptions } from './core/helpers/compact'
import Context from './context'
import d from 'debug'
import generateCallback from './core/network/webhook'
import { Polling } from './core/network/polling'
import pTimeout from 'p-timeout'
import Telegram from './telegram'
import { TlsOptions } from 'tls'
import { URL } from 'url'
import safeCompare = require('safe-compare')
const debug = d('telegraf:main')
const DEFAULT_OPTIONS: Telegraf.Options<Context> = {
telegram: {},
handlerTimeout: 90_000, // 90s in ms
contextType: Context,
}
function always<T>(x: T) {
return () => x
}
const anoop = always(Promise.resolve())
export namespace Telegraf {
export interface Options<TContext extends Context> {
contextType: new (
...args: ConstructorParameters<typeof Context>
) => TContext
handlerTimeout: number
telegram?: Partial<ApiClient.Options>
}
export interface LaunchOptions {
dropPendingUpdates?: boolean
/** List the types of updates you want your bot to receive */
allowedUpdates?: tt.UpdateType[]
/** Configuration options for when the bot is run via webhooks */
webhook?: {
/** Public domain for webhook. */
domain: string
/**
* Webhook url path; will be automatically generated if not specified
* @deprecated Pass `path` instead
* */
hookPath?: string
/** Webhook url path; will be automatically generated if not specified */
path?: string
host?: string
port?: number
/** The fixed IP address which will be used to send webhook requests instead of the IP address resolved through DNS */
ipAddress?: string
/**
* Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100. Defaults to 40.
* Use lower values to limit the load on your bot's server, and higher values to increase your bot's throughput.
*/
maxConnections?: number
/** TLS server options. Omit to use http. */
tlsOptions?: TlsOptions
/**
* A secret token to be sent in a header `“X-Telegram-Bot-Api-Secret-Token”` in every webhook request.
* 1-256 characters. Only characters `A-Z`, `a-z`, `0-9`, `_` and `-` are allowed.
* The header is useful to ensure that the request comes from a webhook set by you.
*/
secretToken?: string
/**
* Upload your public key certificate so that the root certificate in use can be checked.
* See [self-signed guide](https://core.telegram.org/bots/self-signed) for details.
*/
certificate?: tg.InputFile
cb?: http.RequestListener
}
}
}
const TOKEN_HEADER = 'x-telegram-bot-api-secret-token'
export class Telegraf<C extends Context = Context> extends Composer<C> {
private readonly options: Telegraf.Options<C>
private webhookServer?: http.Server | https.Server
private polling?: Polling
/** Set manually to avoid implicit `getMe` call in `launch` or `webhookCallback` */
public botInfo?: tg.UserFromGetMe
public telegram: Telegram
readonly context: Partial<C> = {}
/** Assign to this to customise the webhook filter middleware.
* `{ path, secretToken }` will be bound to this rather than the Telegraf instance.
* Remember to assign a regular function and not an arrow function so it's bindable.
*/
public webhookFilter = function (
// NOTE: this function is assigned to a variable instead of being a method to signify that it's assignable
// NOTE: the `this` binding is so custom impls don't need to double wrap
this: {
/** @deprecated Use path instead */
hookPath: string
path: string
secretToken?: string
},
req: http.IncomingMessage
) {
const debug = d('telegraf:webhook')
if (req.method === 'POST') {
if (safeCompare(this.path, req.url as string)) {
// no need to check if secret_token was not set
if (!this.secretToken) return true
else {
const token = req.headers[TOKEN_HEADER] as string
if (safeCompare(this.secretToken, token)) return true
else debug('Secret token does not match:', token, this.secretToken)
}
} else debug('Path does not match:', req.url, this.path)
} else debug('Unexpected request method, not POST. Received:', req.method)
return false
}
private handleError = (err: unknown, ctx: C): MaybePromise<void> => {
// set exit code to emulate `warn-with-error-code` behavior of
// https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode
// to prevent a clean exit despite an error being thrown
process.exitCode = 1
console.error('Unhandled error while processing', ctx.update)
throw err
}
constructor(token: string, options?: Partial<Telegraf.Options<C>>) {
super()
// @ts-expect-error Trust me, TS
this.options = {
...DEFAULT_OPTIONS,
...compactOptions(options),
}
this.telegram = new Telegram(token, this.options.telegram)
debug('Created a `Telegraf` instance')
}
private get token() {
return this.telegram.token
}
/** @deprecated use `ctx.telegram.webhookReply` */
set webhookReply(webhookReply: boolean) {
this.telegram.webhookReply = webhookReply
}
/** @deprecated use `ctx.telegram.webhookReply` */
get webhookReply() {
return this.telegram.webhookReply
}
/**
* _Override_ error handling
*/
catch(handler: (err: unknown, ctx: C) => MaybePromise<void>) {
this.handleError = handler
return this
}
/**
* You must call `bot.telegram.setWebhook` for this to work.
* You should probably use {@link Telegraf.createWebhook} instead.
*/
webhookCallback(path = '/', opts: { secretToken?: string } = {}) {
const { secretToken } = opts
return generateCallback(
this.webhookFilter.bind({ hookPath: path, path, secretToken }),
(update: tg.Update, res: http.ServerResponse) =>
this.handleUpdate(update, res)
)
}
private getDomainOpts(opts: { domain: string; path?: string }) {
const protocol =
opts.domain.startsWith('https://') || opts.domain.startsWith('http://')
if (protocol)
debug(
'Unexpected protocol in domain, telegraf will use https:',
opts.domain
)
const domain = protocol ? new URL(opts.domain).host : opts.domain
const path = opts.path ?? `/telegraf/${this.secretPathComponent()}`
const url = `https://${domain}${path}`
return { domain, path, url }
}
/**
* Specify a url to receive incoming updates via webhook.
* Returns an Express-style middleware you can pass to app.use()
*/
async createWebhook(
opts: { domain: string; path?: string } & tt.ExtraSetWebhook
) {
const { domain, path, ...extra } = opts
const domainOpts = this.getDomainOpts({ domain, path })
await this.telegram.setWebhook(domainOpts.url, extra)
debug(`Webhook set to ${domainOpts.url}`)
return this.webhookCallback(domainOpts.path, {
secretToken: extra.secret_token,
})
}
private startPolling(allowedUpdates: tt.UpdateType[] = []) {
this.polling = new Polling(this.telegram, allowedUpdates)
return this.polling.loop(async (update) => {
await this.handleUpdate(update)
})
}
private startWebhook(
path: string,
tlsOptions?: TlsOptions,
port?: number,
host?: string,
cb?: http.RequestListener,
secretToken?: string
) {
const webhookCb = this.webhookCallback(path, { secretToken })
const callback: http.RequestListener =
typeof cb === 'function'
? (req, res) => webhookCb(req, res, () => cb(req, res))
: webhookCb
this.webhookServer =
tlsOptions != null
? https.createServer(tlsOptions, callback)
: http.createServer(callback)
this.webhookServer.listen(port, host, () => {
debug('Webhook listening on port: %s', port)
})
return this
}
secretPathComponent() {
return crypto
.createHash('sha3-256')
.update(this.token)
.update(process.version) // salt
.digest('hex')
}
async launch(onLaunch?: () => void): Promise<void>
async launch(
config: Telegraf.LaunchOptions,
onLaunch?: () => void
): Promise<void>
/**
* @see https://github.com/telegraf/telegraf/discussions/1344#discussioncomment-335700
*/
async launch(
config: Telegraf.LaunchOptions | (() => void) = {},
/** @experimental */
onLaunch?: () => void
) {
const [cfg, onMe] =
typeof config === 'function' ? [{}, config] : [config, onLaunch]
const drop_pending_updates = cfg.dropPendingUpdates
const allowed_updates = cfg.allowedUpdates
const webhook = cfg.webhook
debug('Connecting to Telegram')
this.botInfo ??= await this.telegram.getMe()
onMe?.()
debug(`Launching @${this.botInfo.username}`)
if (webhook === undefined) {
await this.telegram.deleteWebhook({ drop_pending_updates })
debug('Bot started with long polling')
await this.startPolling(allowed_updates)
return
}
const domainOpts = this.getDomainOpts({
domain: webhook.domain,
path: webhook.path ?? webhook.hookPath,
})
const { tlsOptions, port, host, cb, secretToken } = webhook
this.startWebhook(domainOpts.path, tlsOptions, port, host, cb, secretToken)
await this.telegram.setWebhook(domainOpts.url, {
drop_pending_updates: drop_pending_updates,
allowed_updates: allowed_updates,
ip_address: webhook.ipAddress,
max_connections: webhook.maxConnections,
secret_token: webhook.secretToken,
certificate: webhook.certificate,
})
debug(`Bot started with webhook @ ${domainOpts.url}`)
}
stop(reason = 'unspecified') {
debug('Stopping bot... Reason:', reason)
// https://github.com/telegraf/telegraf/pull/1224#issuecomment-742693770
if (this.polling === undefined && this.webhookServer === undefined) {
throw new Error('Bot is not running!')
}
this.webhookServer?.close()
this.polling?.stop()
}
private botInfoCall?: Promise<tg.UserFromGetMe>
async handleUpdate(update: tg.Update, webhookResponse?: http.ServerResponse) {
this.botInfo ??=
(debug(
'Update %d is waiting for `botInfo` to be initialized',
update.update_id
),
await (this.botInfoCall ??= this.telegram.getMe()))
debug('Processing update', update.update_id)
const tg = new Telegram(this.token, this.telegram.options, webhookResponse)
const TelegrafContext = this.options.contextType
const ctx = new TelegrafContext(update, tg, this.botInfo)
Object.assign(ctx, this.context)
try {
await pTimeout(
Promise.resolve(this.middleware()(ctx, anoop)),
this.options.handlerTimeout
)
} catch (err) {
return await this.handleError(err, ctx)
} finally {
if (webhookResponse?.writableEnded === false) {
webhookResponse.end()
}
debug('Finished processing update', update.update_id)
}
}
}

219
node_modules/telegraf/src/telegram-types.ts generated vendored Normal file
View File

@@ -0,0 +1,219 @@
/** @format */
import { Expand } from './core/helpers/util'
import {
Message,
Opts,
Telegram,
Update,
InputMediaAudio,
InputMediaDocument,
InputMediaPhoto,
InputMediaVideo,
} from './core/types/typegram'
import { UnionKeys } from './core/helpers/deunionize'
import { FmtString } from './format'
export { Markup } from './markup'
// tiny helper types
export type ChatAction = Opts<'sendChatAction'>['action']
// Modify type so caption, if exists, can be FmtString
export type WrapCaption<T> = T extends { caption?: string }
? Expand<Omit<T, 'caption'> & { caption?: string | FmtString }>
: T
// extra types
/**
* Create an `Extra*` type from the arguments of a given method `M extends keyof Telegram` but `Omit`ting fields with key `K` from it.
*
* Note that `chat_id` may not be specified in `K` because it is `Omit`ted by default.
*/
type MakeExtra<
M extends keyof Telegram,
K extends keyof Omit<Opts<M>, 'chat_id'> = never,
> = WrapCaption<Omit<Opts<M>, 'chat_id' | K>>
export type ExtraAddStickerToSet = MakeExtra<
'addStickerToSet',
'name' | 'user_id'
>
export type ExtraAnimation = MakeExtra<'sendAnimation', 'animation'>
export type ExtraAnswerCbQuery = MakeExtra<
'answerCallbackQuery',
'text' | 'callback_query_id'
>
export type ExtraAnswerInlineQuery = MakeExtra<
'answerInlineQuery',
'inline_query_id' | 'results'
>
export type ExtraSetChatPermissions = MakeExtra<
'setChatPermissions',
'permissions'
>
export type ExtraAudio = MakeExtra<'sendAudio', 'audio'>
export type ExtraContact = MakeExtra<
'sendContact',
'phone_number' | 'first_name'
>
export type ExtraCopyMessage = MakeExtra<
'copyMessage',
'from_chat_id' | 'message_id'
>
export type ExtraCopyMessages = MakeExtra<
'copyMessages',
'from_chat_id' | 'message_ids'
>
export type ExtraCreateChatInviteLink = MakeExtra<'createChatInviteLink'>
export type NewInvoiceLinkParameters = MakeExtra<'createInvoiceLink'>
export type ExtraCreateNewStickerSet = MakeExtra<
'createNewStickerSet',
'name' | 'title' | 'user_id'
>
export type ExtraDice = MakeExtra<'sendDice'>
export type ExtraDocument = MakeExtra<'sendDocument', 'document'>
export type ExtraEditChatInviteLink = MakeExtra<
'editChatInviteLink',
'invite_link'
>
export type ExtraEditMessageCaption = MakeExtra<
'editMessageCaption',
'message_id' | 'inline_message_id' | 'caption'
>
export type ExtraEditMessageLiveLocation = MakeExtra<
'editMessageLiveLocation',
'message_id' | 'inline_message_id' | 'latitude' | 'longitude'
>
export type ExtraEditMessageMedia = MakeExtra<
'editMessageMedia',
'message_id' | 'inline_message_id' | 'media'
>
export type ExtraEditMessageText = MakeExtra<
'editMessageText',
'message_id' | 'inline_message_id' | 'text'
>
export type ExtraGame = MakeExtra<'sendGame', 'game_short_name'>
export type NewInvoiceParameters = MakeExtra<
'sendInvoice',
| 'disable_notification'
| 'reply_parameters'
| 'reply_markup'
| 'message_thread_id'
>
export type ExtraInvoice = MakeExtra<'sendInvoice', keyof NewInvoiceParameters>
export type ExtraBanChatMember = MakeExtra<
'banChatMember',
'user_id' | 'until_date'
>
export type ExtraKickChatMember = ExtraBanChatMember
export type ExtraLocation = MakeExtra<'sendLocation', 'latitude' | 'longitude'>
export type ExtraMediaGroup = MakeExtra<'sendMediaGroup', 'media'>
export type ExtraPhoto = MakeExtra<'sendPhoto', 'photo'>
export type ExtraPoll = MakeExtra<'sendPoll', 'question' | 'options' | 'type'>
export type ExtraPromoteChatMember = MakeExtra<'promoteChatMember', 'user_id'>
export type ExtraReplyMessage = MakeExtra<'sendMessage', 'text'>
export type ExtraForwardMessage = MakeExtra<
'forwardMessage',
'from_chat_id' | 'message_id'
>
export type ExtraForwardMessages = MakeExtra<
'forwardMessages',
'from_chat_id' | 'message_ids'
>
export type ExtraSendChatAction = MakeExtra<'sendChatAction', 'action'>
export type ExtraRestrictChatMember = MakeExtra<'restrictChatMember', 'user_id'>
export type ExtraSetMyCommands = MakeExtra<'setMyCommands', 'commands'>
export type ExtraSetWebhook = MakeExtra<'setWebhook', 'url'>
export type ExtraSticker = MakeExtra<'sendSticker', 'sticker'>
export type ExtraStopPoll = MakeExtra<'stopPoll', 'message_id'>
export type ExtraVenue = MakeExtra<
'sendVenue',
'latitude' | 'longitude' | 'title' | 'address'
>
export type ExtraVideo = MakeExtra<'sendVideo', 'video'>
export type ExtraVideoNote = MakeExtra<'sendVideoNote', 'video_note'>
export type ExtraVoice = MakeExtra<'sendVoice', 'voice'>
export type ExtraBanChatSenderChat = MakeExtra<
'banChatSenderChat',
'sender_chat_id'
>
export type ExtraCreateForumTopic = MakeExtra<'createForumTopic', 'name'>
export type ExtraEditForumTopic = MakeExtra<
'editForumTopic',
'message_thread_id'
>
export type MediaGroup =
| readonly (InputMediaPhoto | InputMediaVideo)[]
| readonly InputMediaAudio[]
| readonly InputMediaDocument[]
// types used for inference of ctx object
/** Possible update types */
export type UpdateType = Exclude<UnionKeys<Update>, keyof Update>
/** Possible message subtypes. Same as the properties on a message object */
export type MessageSubType =
| 'forward_date'
| Exclude<
UnionKeys<Message>,
keyof Message.CaptionableMessage | 'entities' | 'media_group_id'
>
type ExtractPartial<T extends object, U extends object> = T extends unknown
? Required<T> extends U
? T
: never
: never
/**
* Maps [[`Composer.on`]]'s `updateType` or `messageSubType` to a `tt.Update` subtype.
* @deprecated
*/
export type MountMap = {
[T in UpdateType]: Extract<Update, Record<T, object>>
} & {
[T in MessageSubType]: {
message: ExtractPartial<Update.MessageUpdate['message'], Record<T, unknown>>
update_id: number
}
}
export interface CommandContextExtn {
match: RegExpExecArray
/**
* Matched command. This will always be the actual command, excluding preceeding slash and `@botname`
*
* Examples:
* ```
* /command abc -> command
* /command@xyzbot abc -> command
* ```
*/
command: string
/**
* The unparsed payload part of the command
*
* Examples:
* ```
* /command abc def -> "abc def"
* /command "token1 token2" -> "\"token1 token2\""
* ```
*/
payload: string
/**
* Command args parsed into an array.
*
* Examples:
* ```
* /command token1 token2 -> [ "token1", "token2" ]
* /command "token1 token2" -> [ "token1 token2" ]
* /command token1 "token2 token3" -> [ "token1" "token2 token3" ]
* ```
* @unstable Parser implementation might vary until considered stable
* */
args: string[]
}

1635
node_modules/telegraf/src/telegram.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

2
node_modules/telegraf/src/types.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export type * from './core/types/typegram'
export type * as Convenience from './telegram-types'

1
node_modules/telegraf/src/utils.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export { argsParser } from './core/helpers/args'

1
node_modules/telegraf/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './typings/types'

1
node_modules/telegraf/types.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/types')

36
node_modules/telegraf/typings/button.d.ts generated vendored Normal file
View File

@@ -0,0 +1,36 @@
import { InlineKeyboardButton, KeyboardButton, KeyboardButtonRequestChat, KeyboardButtonRequestUsers } from './core/types/typegram';
type Hideable<B> = B & {
hide: boolean;
};
export declare function text(text: string, hide?: boolean): Hideable<KeyboardButton.CommonButton>;
export declare function contactRequest(text: string, hide?: boolean): Hideable<KeyboardButton.RequestContactButton>;
export declare function locationRequest(text: string, hide?: boolean): Hideable<KeyboardButton.RequestLocationButton>;
export declare function pollRequest(text: string, type?: 'quiz' | 'regular', hide?: boolean): Hideable<KeyboardButton.RequestPollButton>;
export declare function userRequest(text: string,
/** Must fit in a signed 32 bit int */
request_id: number, extra?: Omit<KeyboardButtonRequestUsers, 'request_id' | 'text'>, hide?: boolean): Hideable<KeyboardButton.RequestUsersButton>;
export declare function botRequest(text: string,
/** Must fit in a signed 32 bit int */
request_id: number, extra?: Omit<KeyboardButtonRequestUsers, 'request_id' | 'user_is_bot' | 'text'>, hide?: boolean): Hideable<KeyboardButton.RequestUsersButton>;
type KeyboardButtonRequestGroup = Omit<KeyboardButtonRequestChat, 'request_id' | 'chat_is_channel'>;
export declare function groupRequest(text: string,
/** Must fit in a signed 32 bit int */
request_id: number, extra?: KeyboardButtonRequestGroup, hide?: boolean): Hideable<KeyboardButton.RequestChatButton>;
type KeyboardButtonRequestChannel = Omit<KeyboardButtonRequestChat, 'request_id' | 'chat_is_channel' | 'chat_is_forum'>;
export declare function channelRequest(text: string,
/** Must fit in a signed 32 bit int */
request_id: number, extra?: KeyboardButtonRequestChannel, hide?: boolean): Hideable<KeyboardButton.RequestChatButton>;
export declare function url(text: string, url: string, hide?: boolean): Hideable<InlineKeyboardButton.UrlButton>;
export declare function callback(text: string, data: string, hide?: boolean): Hideable<InlineKeyboardButton.CallbackButton>;
export declare function switchToChat(text: string, value: string, hide?: boolean): Hideable<InlineKeyboardButton.SwitchInlineButton>;
export declare function switchToCurrentChat(text: string, value: string, hide?: boolean): Hideable<InlineKeyboardButton.SwitchInlineCurrentChatButton>;
export declare function game(text: string, hide?: boolean): Hideable<InlineKeyboardButton.GameButton>;
export declare function pay(text: string, hide?: boolean): Hideable<InlineKeyboardButton.PayButton>;
export declare function login(text: string, url: string, opts?: {
forward_text?: string;
bot_username?: string;
request_write_access?: boolean;
}, hide?: boolean): Hideable<InlineKeyboardButton.LoginButton>;
export declare function webApp(text: string, url: string, hide?: boolean): Hideable<InlineKeyboardButton.WebAppButton>;
export {};
//# sourceMappingURL=button.d.ts.map

1
node_modules/telegraf/typings/button.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../src/button.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,yBAAyB,EACzB,0BAA0B,EAC3B,MAAM,uBAAuB,CAAA;AAE9B,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAExC,wBAAgB,IAAI,CAClB,IAAI,EAAE,MAAM,EACZ,IAAI,UAAQ,GACX,QAAQ,CAAC,cAAc,CAAC,YAAY,CAAC,CAEvC;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,UAAQ,GACX,QAAQ,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAE/C;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,UAAQ,GACX,QAAQ,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAEhD;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,UAAQ,GACX,QAAQ,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAE5C;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM;AACZ,sCAAsC;AACtC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,IAAI,CAAC,0BAA0B,EAAE,YAAY,GAAG,MAAM,CAAC,EAC/D,IAAI,UAAQ,GACX,QAAQ,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAM7C;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM;AACZ,sCAAsC;AACtC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,IAAI,CACV,0BAA0B,EAC1B,YAAY,GAAG,aAAa,GAAG,MAAM,CACtC,EACD,IAAI,UAAQ,GACX,QAAQ,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAM7C;AAED,KAAK,0BAA0B,GAAG,IAAI,CACpC,yBAAyB,EACzB,YAAY,GAAG,iBAAiB,CACjC,CAAA;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM;AACZ,sCAAsC;AACtC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,0BAA0B,EAClC,IAAI,UAAQ,GACX,QAAQ,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAM5C;AAED,KAAK,4BAA4B,GAAG,IAAI,CACtC,yBAAyB,EACzB,YAAY,GAAG,iBAAiB,GAAG,eAAe,CACnD,CAAA;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM;AACZ,sCAAsC;AACtC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,4BAA4B,EACpC,IAAI,UAAQ,GACX,QAAQ,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAM5C;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,UAAQ,GACX,QAAQ,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAE1C;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,UAAQ,GACX,QAAQ,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAE/C;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,UAAQ,GACX,QAAQ,CAAC,oBAAoB,CAAC,kBAAkB,CAAC,CAEnD;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,UAAQ,GACX,QAAQ,CAAC,oBAAoB,CAAC,6BAA6B,CAAC,CAE9D;AAED,wBAAgB,IAAI,CAClB,IAAI,EAAE,MAAM,EACZ,IAAI,UAAQ,GACX,QAAQ,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAE3C;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,MAAM,EACZ,IAAI,UAAQ,GACX,QAAQ,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAE1C;AAED,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IACJ,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC1B,EACN,IAAI,UAAQ,GACX,QAAQ,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAM5C;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,UAAQ,GAEX,QAAQ,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAM7C"}

227
node_modules/telegraf/typings/composer.d.ts generated vendored Normal file
View File

@@ -0,0 +1,227 @@
/** @format */
import * as tg from './core/types/typegram';
import * as tt from './telegram-types';
import { Middleware, MiddlewareFn, MiddlewareObj } from './middleware';
import Context, { FilteredContext, NarrowedContext } from './context';
import { MaybeArray, NonemptyReadonlyArray, MaybePromise, Guard } from './core/helpers/util';
import { type CallbackQuery } from './core/types/typegram';
import { Digit, Reaction } from './reactions';
type ReactionAddedOrRemoved = Reaction | `-${tg.TelegramEmoji}` | `-${Digit}${string}`;
export type Triggers<C> = MaybeArray<string | RegExp | TriggerFn<C>>;
type TriggerFn<C> = (value: string, ctx: C) => RegExpExecArray | null;
export type Predicate<T> = (t: T) => boolean;
export type AsyncPredicate<T> = (t: T) => Promise<boolean>;
export type MatchedMiddleware<C extends Context, T extends tt.UpdateType | tt.MessageSubType = 'message' | 'channel_post'> = NonemptyReadonlyArray<Middleware<NarrowedContext<C, tt.MountMap[T]> & {
match: RegExpExecArray;
}, tt.MountMap[T]>>;
interface StartContextExtn extends tt.CommandContextExtn {
/**
* @deprecated Use ctx.payload instead
*/
startPayload: string;
}
export declare class Composer<C extends Context> implements MiddlewareObj<C> {
private handler;
constructor(...fns: ReadonlyArray<Middleware<C>>);
/**
* Registers a middleware.
*/
use(...fns: ReadonlyArray<Middleware<C>>): this;
/**
* Registers middleware for handling updates
* matching given type guard function.
* @deprecated use `Composer::on`
*/
guard<U extends tg.Update>(guardFn: (update: tg.Update) => update is U, ...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, U>, U>>): this;
/**
* Registers middleware for handling updates narrowed by update types or filter queries.
*/
on<Filter extends tt.UpdateType | Guard<C['update']>>(filters: MaybeArray<Filter>, ...fns: NonemptyReadonlyArray<Middleware<FilteredContext<C, Filter>>>): this;
/**
* Registers middleware for handling updates narrowed by update types or message subtypes.
* @deprecated Use filter utils instead. Support for Message subtype in `Composer::on` will be removed in Telegraf v5.
*/
on<Filter extends tt.UpdateType | tt.MessageSubType>(filters: MaybeArray<Filter>, ...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tt.MountMap[Filter]>, tt.MountMap[Filter]>>): this;
/**
* Registers middleware for handling matching text messages.
*/
hears(triggers: Triggers<NarrowedContext<C, tt.MountMap['text']>>, ...fns: MatchedMiddleware<C, 'text'>): this;
/**
* Registers middleware for handling specified commands.
*/
command(command: Triggers<NarrowedContext<C, tt.MountMap['text']>>, ...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tt.MountMap['text']> & tt.CommandContextExtn>>): this;
/**
* Registers middleware for handling matching callback queries.
*/
action(triggers: Triggers<NarrowedContext<C, tt.MountMap['callback_query']>>, ...fns: MatchedMiddleware<C, 'callback_query'>): this;
/**
* Registers middleware for handling matching inline queries.
*/
inlineQuery(triggers: Triggers<NarrowedContext<C, tt.MountMap['inline_query']>>, ...fns: MatchedMiddleware<C, 'inline_query'>): this;
/**
* Registers middleware for handling game queries
*/
gameQuery(...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tg.Update.CallbackQueryUpdate<CallbackQuery.GameQuery>>>>): this;
reaction(reaction: MaybeArray<ReactionAddedOrRemoved>, ...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tg.Update.MessageReactionUpdate> & {
match: ReactionAddedOrRemoved;
}, tg.Update.MessageReactionUpdate>>): this;
/**
* Registers middleware for dropping matching updates.
*/
drop(predicate: Predicate<C>): this;
/** @deprecated use `Composer::drop` */
filter(predicate: Predicate<C>): this;
private entity;
email(email: Triggers<C>, ...fns: MatchedMiddleware<C>): this;
url(url: Triggers<C>, ...fns: MatchedMiddleware<C>): this;
textLink(link: Triggers<C>, ...fns: MatchedMiddleware<C>): this;
textMention(mention: Triggers<C>, ...fns: MatchedMiddleware<C>): this;
mention(mention: MaybeArray<string>, ...fns: MatchedMiddleware<C>): this;
phone(number: Triggers<C>, ...fns: MatchedMiddleware<C>): this;
hashtag(hashtag: MaybeArray<string>, ...fns: MatchedMiddleware<C>): this;
cashtag(cashtag: MaybeArray<string>, ...fns: MatchedMiddleware<C>): this;
spoiler(text: Triggers<C>, ...fns: MatchedMiddleware<C>): this;
/**
* Registers a middleware for handling /start
*/
start(...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tt.MountMap['text']> & StartContextExtn>>): this;
/**
* Registers a middleware for handling /help
*/
help(...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tt.MountMap['text']> & tt.CommandContextExtn>>): this;
/**
* Registers a middleware for handling /settings
*/
settings(...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tt.MountMap['text']> & tt.CommandContextExtn>>): this;
middleware(): MiddlewareFn<C>;
static reply(...args: Parameters<Context['reply']>): MiddlewareFn<Context>;
static catch<C extends Context>(errorHandler: (err: unknown, ctx: C) => void, ...fns: ReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
/**
* Generates middleware that runs in the background.
*/
static fork<C extends Context>(middleware: Middleware<C>): MiddlewareFn<C>;
static tap<C extends Context>(middleware: Middleware<C>): MiddlewareFn<C>;
/**
* Generates middleware that gives up control to the next middleware.
*/
static passThru(): MiddlewareFn<Context>;
static lazy<C extends Context>(factoryFn: (ctx: C) => MaybePromise<Middleware<C>>): MiddlewareFn<C>;
static log(logFn?: (s: string) => void): MiddlewareFn<Context>;
/**
* @param trueMiddleware middleware to run if the predicate returns true
* @param falseMiddleware middleware to run if the predicate returns false
*/
static branch<C extends Context>(predicate: boolean | Predicate<C> | AsyncPredicate<C>, trueMiddleware: Middleware<C>, falseMiddleware: Middleware<C>): MiddlewareFn<C>;
/**
* Generates optional middleware.
* @param predicate predicate to decide on a context object whether to run the middleware
* @param fns middleware to run if the predicate returns true
*/
static optional<C extends Context>(predicate: Predicate<C> | AsyncPredicate<C>, ...fns: NonemptyReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
/** @deprecated use `Composer.drop` */
static filter<C extends Context>(predicate: Predicate<C>): MiddlewareFn<C>;
/**
* Generates middleware for dropping matching updates.
*/
static drop<C extends Context>(predicate: Predicate<C>): MiddlewareFn<C>;
static dispatch<C extends Context, Handlers extends Record<string | number | symbol, Middleware<C>>>(routeFn: (ctx: C) => MaybePromise<keyof Handlers>, handlers: Handlers): Middleware<C>;
/**
* Generates optional middleware based on a predicate that only operates on `ctx.update`.
*
* Example:
* ```ts
* import { Composer, Update } from 'telegraf'
*
* const predicate = (u): u is Update.MessageUpdate => 'message' in u
* const middleware = Composer.guard(predicate, (ctx) => {
* const message = ctx.update.message
* })
* ```
*
* Note that `Composer.on('message')` is preferred over this.
*
* @param guardFn predicate to decide whether to run the middleware based on the `ctx.update` object
* @param fns middleware to run if the predicate returns true
* @see `Composer.optional` for a more generic version of this method that allows the predicate to operate on `ctx` itself
* @deprecated use `Composer.on`
*/
static guard<C extends Context, U extends tg.Update>(guardFn: (u: tg.Update) => u is U, ...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, U>, U>>): MiddlewareFn<C>;
/**
* Generates middleware for handling updates narrowed by update types or filter queries.
*/
static on<Ctx extends Context, Filter extends tt.UpdateType | Guard<Ctx['update']>>(filters: MaybeArray<Filter>, ...fns: NonemptyReadonlyArray<Middleware<FilteredContext<Ctx, Filter>>>): MiddlewareFn<Ctx>;
/**
* Generates middleware for handling updates narrowed by update types or message subtype.
* @deprecated Use filter utils instead. Support for Message subtype in `Composer.on` will be removed in Telegraf v5.
*/
static on<Ctx extends Context, Filter extends tt.UpdateType | tt.MessageSubType>(filters: MaybeArray<Filter>, ...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<Ctx, tt.MountMap[Filter]>, tt.MountMap[Filter]>>): MiddlewareFn<Ctx>;
/**
* Generates middleware for handling provided update types.
* @deprecated use `Composer.on` instead
*/
static mount: typeof Composer.on;
private static entity;
static entityText<C extends Context>(entityType: MaybeArray<string>, predicate: Triggers<C>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static email<C extends Context>(email: Triggers<C>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static phone<C extends Context>(number: Triggers<C>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static url<C extends Context>(url: Triggers<C>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static textLink<C extends Context>(link: Triggers<C>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static textMention<C extends Context>(mention: Triggers<C>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static mention<C extends Context>(mention: MaybeArray<string>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static hashtag<C extends Context>(hashtag: MaybeArray<string>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static cashtag<C extends Context>(cashtag: MaybeArray<string>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
static spoiler<C extends Context>(text: Triggers<C>, ...fns: MatchedMiddleware<C>): MiddlewareFn<C>;
private static match;
/**
* Generates middleware for handling matching text messages.
*/
static hears<C extends Context>(triggers: Triggers<NarrowedContext<C, tt.MountMap['text']>>, ...fns: MatchedMiddleware<C, 'text'>): MiddlewareFn<C>;
/**
* Generates middleware for handling specified commands.
*/
static command<C extends Context>(command: Triggers<NarrowedContext<C, tt.MountMap['text']>>, ...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tt.MountMap['text']> & tt.CommandContextExtn>>): MiddlewareFn<C>;
/**
* Generates middleware for handling matching callback queries.
*/
static action<C extends Context>(triggers: Triggers<NarrowedContext<C, tt.MountMap['callback_query']>>, ...fns: MatchedMiddleware<C, 'callback_query'>): MiddlewareFn<C>;
/**
* Generates middleware for handling matching inline queries.
*/
static inlineQuery<C extends Context>(triggers: Triggers<NarrowedContext<C, tt.MountMap['inline_query']>>, ...fns: MatchedMiddleware<C, 'inline_query'>): MiddlewareFn<C>;
static reaction<C extends Context>(reaction: MaybeArray<ReactionAddedOrRemoved>, ...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tg.Update.MessageReactionUpdate> & {
match: ReactionAddedOrRemoved;
}, tg.Update.MessageReactionUpdate>>): MiddlewareFn<C>;
/**
* Generates middleware responding only to specified users.
*/
static acl<C extends Context>(userId: MaybeArray<number>, ...fns: NonemptyReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
private static memberStatus;
/**
* Generates middleware responding only to chat admins and chat creator.
*/
static admin<C extends Context>(...fns: NonemptyReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
/**
* Generates middleware responding only to chat creator.
*/
static creator<C extends Context>(...fns: NonemptyReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
/**
* Generates middleware running only in specified chat types.
*/
static chatType<C extends Context>(type: MaybeArray<tg.Chat['type']>, ...fns: NonemptyReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
/**
* Generates middleware running only in private chats.
*/
static privateChat<C extends Context>(...fns: NonemptyReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
/**
* Generates middleware running only in groups and supergroups.
*/
static groupChat<C extends Context>(...fns: NonemptyReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
/**
* Generates middleware for handling game queries.
*/
static gameQuery<C extends Context>(...fns: NonemptyReadonlyArray<Middleware<NarrowedContext<C, tg.Update.CallbackQueryUpdate<CallbackQuery.GameQuery>>>>): MiddlewareFn<C>;
static unwrap<C extends Context>(handler: Middleware<C>): MiddlewareFn<C>;
static compose<C extends Context>(middlewares: ReadonlyArray<Middleware<C>>): MiddlewareFn<C>;
}
export default Composer;
//# sourceMappingURL=composer.d.ts.map

1
node_modules/telegraf/typings/composer.d.ts.map generated vendored Normal file

File diff suppressed because one or more lines are too long

655
node_modules/telegraf/typings/context.d.ts generated vendored Normal file
View File

@@ -0,0 +1,655 @@
import * as tg from './core/types/typegram';
import * as tt from './telegram-types';
import { Deunionize, PropOr, UnionKeys } from './core/helpers/deunionize';
import ApiClient from './core/network/client';
import { Guard, Guarded, Keyed, MaybeArray } from './core/helpers/util';
import Telegram from './telegram';
import { FmtString } from './format';
import { Digit, MessageReactions } from './reactions';
type Tail<T> = T extends [unknown, ...infer U] ? U : never;
type Shorthand<FName extends Exclude<keyof Telegram, keyof ApiClient>> = Tail<Parameters<Telegram[FName]>>;
/**
* Narrows down `C['update']` (and derived getters)
* to specific update type `U`.
*
* Used by [[`Composer`]],
* possibly useful for splitting a bot into multiple files.
*/
export type NarrowedContext<C extends Context, U extends tg.Update> = Context<U> & Omit<C, keyof Context>;
export type FilteredContext<Ctx extends Context, Filter extends tt.UpdateType | Guard<Ctx['update']>> = Filter extends tt.UpdateType ? NarrowedContext<Ctx, Extract<tg.Update, Record<Filter, object>>> : NarrowedContext<Ctx, Guarded<Filter>>;
export declare class Context<U extends Deunionize<tg.Update> = tg.Update> {
readonly update: U;
readonly telegram: Telegram;
readonly botInfo: tg.UserFromGetMe;
readonly state: Record<string | symbol, any>;
constructor(update: U, telegram: Telegram, botInfo: tg.UserFromGetMe);
get updateType(): Extract<UnionKeys<U>, tt.UpdateType>;
get me(): string;
/**
* @deprecated Use ctx.telegram instead
*/
get tg(): Telegram;
get message(): PropOr<U, "message">;
get editedMessage(): PropOr<U, "edited_message">;
get inlineQuery(): PropOr<U, "inline_query">;
get shippingQuery(): PropOr<U, "shipping_query">;
get preCheckoutQuery(): PropOr<U, "pre_checkout_query">;
get chosenInlineResult(): PropOr<U, "chosen_inline_result">;
get channelPost(): PropOr<U, "channel_post">;
get editedChannelPost(): PropOr<U, "edited_channel_post">;
get messageReaction(): PropOr<U, "message_reaction">;
get messageReactionCount(): PropOr<U, "message_reaction_count">;
get callbackQuery(): PropOr<U, "callback_query">;
get poll(): PropOr<U, "poll">;
get pollAnswer(): PropOr<U, "poll_answer">;
get myChatMember(): PropOr<U, "my_chat_member">;
get chatMember(): PropOr<U, "chat_member">;
get chatJoinRequest(): PropOr<U, "chat_join_request">;
get chatBoost(): PropOr<U, "chat_boost">;
get removedChatBoost(): PropOr<U, "removed_chat_boost">;
/** Shorthand for any `message` object present in the current update. One of
* `message`, `edited_message`, `channel_post`, `edited_channel_post` or
* `callback_query.message`
*/
get msg(): GetMsg<U> & Msg;
/** Shorthand for any message_id present in the current update. */
get msgId(): GetMsgId<U>;
get chat(): Getter<U, 'chat'>;
get senderChat(): PropOr<GetUpdateContent<U>, "sender_chat", undefined>;
get from(): GetUserFromAnySource<U>;
get inlineMessageId(): string | undefined;
get passportData(): tg.PassportData | undefined;
get webAppData(): {
data: {
json<T>(): T;
text(): string;
};
button_text: string;
} | undefined;
/**
* @deprecated use {@link Telegram.webhookReply}
*/
get webhookReply(): boolean;
set webhookReply(enable: boolean);
get reactions(): MessageReactions;
has<Filter extends tt.UpdateType | Guard<Context['update']>>(filters: MaybeArray<Filter>): this is FilteredContext<Context, Filter>;
get text(): GetText<U>;
entities<EntityTypes extends tg.MessageEntity['type'][]>(...types: EntityTypes): (tg.MessageEntity & {
type: EntityTypes extends [] ? "mention" | "hashtag" | "cashtag" | "bot_command" | "url" | "email" | "phone_number" | "bold" | "blockquote" | "italic" | "underline" | "strikethrough" | "spoiler" | "code" | "custom_emoji" | "pre" | "text_link" | "text_mention" : EntityTypes[number];
fragment: string;
})[];
/**
* @see https://core.telegram.org/bots/api#answerinlinequery
*/
answerInlineQuery(...args: Shorthand<'answerInlineQuery'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#answercallbackquery
*/
answerCbQuery(...args: Shorthand<'answerCbQuery'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#answercallbackquery
*/
answerGameQuery(...args: Shorthand<'answerGameQuery'>): Promise<true>;
/**
* Shorthand for {@link Telegram.getUserChatBoosts}
*/
getUserChatBoosts(): Promise<tg.UserChatBoosts[]>;
/**
* @see https://core.telegram.org/bots/api#answershippingquery
*/
answerShippingQuery(...args: Shorthand<'answerShippingQuery'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#answerprecheckoutquery
*/
answerPreCheckoutQuery(...args: Shorthand<'answerPreCheckoutQuery'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#editmessagetext
*/
editMessageText(text: string | FmtString, extra?: tt.ExtraEditMessageText): Promise<true | (tg.Update.Edited & tg.Message.TextMessage)>;
/**
* @see https://core.telegram.org/bots/api#editmessagecaption
*/
editMessageCaption(caption: string | FmtString | undefined, extra?: tt.ExtraEditMessageCaption): Promise<true | (tg.Update.Edited & tg.Message.CaptionableMessage)>;
/**
* @see https://core.telegram.org/bots/api#editmessagemedia
*/
editMessageMedia(media: tt.WrapCaption<tg.InputMedia>, extra?: tt.ExtraEditMessageMedia): Promise<true | (tg.Update.Edited & tg.Message)>;
/**
* @see https://core.telegram.org/bots/api#editmessagereplymarkup
*/
editMessageReplyMarkup(markup: tg.InlineKeyboardMarkup | undefined): Promise<true | (tg.Update.Edited & tg.Message)>;
/**
* @see https://core.telegram.org/bots/api#editmessagelivelocation
*/
editMessageLiveLocation(latitude: number, longitude: number, extra?: tt.ExtraEditMessageLiveLocation): Promise<true | (tg.Update.Edited & tg.Message.LocationMessage)>;
/**
* @see https://core.telegram.org/bots/api#stopmessagelivelocation
*/
stopMessageLiveLocation(markup?: tg.InlineKeyboardMarkup): Promise<true | (tg.Update.Edited & tg.Message.LocationMessage)>;
/**
* @see https://core.telegram.org/bots/api#sendmessage
*/
sendMessage(text: string | FmtString, extra?: tt.ExtraReplyMessage): Promise<tg.Message.TextMessage>;
/**
* @see https://core.telegram.org/bots/api#sendmessage
*/
reply(...args: Shorthand<'sendMessage'>): Promise<tg.Message.TextMessage>;
/**
* @see https://core.telegram.org/bots/api#getchat
*/
getChat(...args: Shorthand<'getChat'>): Promise<tg.ChatFromGetChat>;
/**
* @see https://core.telegram.org/bots/api#exportchatinvitelink
*/
exportChatInviteLink(...args: Shorthand<'exportChatInviteLink'>): Promise<string>;
/**
* @see https://core.telegram.org/bots/api#createchatinvitelink
*/
createChatInviteLink(...args: Shorthand<'createChatInviteLink'>): Promise<tg.ChatInviteLink>;
/**
* @see https://core.telegram.org/bots/api#editchatinvitelink
*/
editChatInviteLink(...args: Shorthand<'editChatInviteLink'>): Promise<tg.ChatInviteLink>;
/**
* @see https://core.telegram.org/bots/api#revokechatinvitelink
*/
revokeChatInviteLink(...args: Shorthand<'revokeChatInviteLink'>): Promise<tg.ChatInviteLink>;
/**
* @see https://core.telegram.org/bots/api#banchatmember
*/
banChatMember(...args: Shorthand<'banChatMember'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#banchatmember
* @deprecated since API 5.3. Use {@link Context.banChatMember}
*/
get kickChatMember(): (userId: number, untilDate?: number | undefined, extra?: Omit<{
chat_id: string | number;
user_id: number;
until_date?: number | undefined;
revoke_messages?: boolean | undefined;
}, "chat_id" | "user_id" | "until_date"> | undefined) => Promise<true>;
/**
* @see https://core.telegram.org/bots/api#unbanchatmember
*/
unbanChatMember(...args: Shorthand<'unbanChatMember'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#restrictchatmember
*/
restrictChatMember(...args: Shorthand<'restrictChatMember'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#promotechatmember
*/
promoteChatMember(...args: Shorthand<'promoteChatMember'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#setchatadministratorcustomtitle
*/
setChatAdministratorCustomTitle(...args: Shorthand<'setChatAdministratorCustomTitle'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#setchatphoto
*/
setChatPhoto(...args: Shorthand<'setChatPhoto'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#deletechatphoto
*/
deleteChatPhoto(...args: Shorthand<'deleteChatPhoto'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#setchattitle
*/
setChatTitle(...args: Shorthand<'setChatTitle'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#setchatdescription
*/
setChatDescription(...args: Shorthand<'setChatDescription'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#pinchatmessage
*/
pinChatMessage(...args: Shorthand<'pinChatMessage'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#unpinchatmessage
*/
unpinChatMessage(...args: Shorthand<'unpinChatMessage'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#unpinallchatmessages
*/
unpinAllChatMessages(...args: Shorthand<'unpinAllChatMessages'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#leavechat
*/
leaveChat(...args: Shorthand<'leaveChat'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#setchatpermissions
*/
setChatPermissions(...args: Shorthand<'setChatPermissions'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#getchatadministrators
*/
getChatAdministrators(...args: Shorthand<'getChatAdministrators'>): Promise<(tg.ChatMemberOwner | tg.ChatMemberAdministrator)[]>;
/**
* @see https://core.telegram.org/bots/api#getchatmember
*/
getChatMember(...args: Shorthand<'getChatMember'>): Promise<tg.ChatMember>;
/**
* @see https://core.telegram.org/bots/api#getchatmembercount
*/
getChatMembersCount(...args: Shorthand<'getChatMembersCount'>): Promise<number>;
/**
* @see https://core.telegram.org/bots/api#setpassportdataerrors
*/
setPassportDataErrors(errors: readonly tg.PassportElementError[]): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#sendphoto
*/
sendPhoto(photo: string | tg.InputFile, extra?: tt.ExtraPhoto): Promise<tg.Message.PhotoMessage>;
/**
* @see https://core.telegram.org/bots/api#sendphoto
*/
replyWithPhoto(...args: Shorthand<'sendPhoto'>): Promise<tg.Message.PhotoMessage>;
/**
* @see https://core.telegram.org/bots/api#sendmediagroup
*/
sendMediaGroup(media: tt.MediaGroup, extra?: tt.ExtraMediaGroup): Promise<(tg.Message.DocumentMessage | tg.Message.AudioMessage | tg.Message.PhotoMessage | tg.Message.VideoMessage)[]>;
/**
* @see https://core.telegram.org/bots/api#sendmediagroup
*/
replyWithMediaGroup(...args: Shorthand<'sendMediaGroup'>): Promise<(tg.Message.DocumentMessage | tg.Message.AudioMessage | tg.Message.PhotoMessage | tg.Message.VideoMessage)[]>;
/**
* @see https://core.telegram.org/bots/api#sendaudio
*/
sendAudio(audio: string | tg.InputFile, extra?: tt.ExtraAudio): Promise<tg.Message.AudioMessage>;
/**
* @see https://core.telegram.org/bots/api#sendaudio
*/
replyWithAudio(...args: Shorthand<'sendAudio'>): Promise<tg.Message.AudioMessage>;
/**
* @see https://core.telegram.org/bots/api#senddice
*/
sendDice(extra?: tt.ExtraDice): Promise<tg.Message.DiceMessage>;
/**
* @see https://core.telegram.org/bots/api#senddice
*/
replyWithDice(...args: Shorthand<'sendDice'>): Promise<tg.Message.DiceMessage>;
/**
* @see https://core.telegram.org/bots/api#senddocument
*/
sendDocument(document: string | tg.InputFile, extra?: tt.ExtraDocument): Promise<tg.Message.DocumentMessage>;
/**
* @see https://core.telegram.org/bots/api#senddocument
*/
replyWithDocument(...args: Shorthand<'sendDocument'>): Promise<tg.Message.DocumentMessage>;
/**
* @see https://core.telegram.org/bots/api#sendsticker
*/
sendSticker(sticker: string | tg.InputFile, extra?: tt.ExtraSticker): Promise<tg.Message.StickerMessage>;
/**
* @see https://core.telegram.org/bots/api#sendsticker
*/
replyWithSticker(...args: Shorthand<'sendSticker'>): Promise<tg.Message.StickerMessage>;
/**
* @see https://core.telegram.org/bots/api#sendvideo
*/
sendVideo(video: string | tg.InputFile, extra?: tt.ExtraVideo): Promise<tg.Message.VideoMessage>;
/**
* @see https://core.telegram.org/bots/api#sendvideo
*/
replyWithVideo(...args: Shorthand<'sendVideo'>): Promise<tg.Message.VideoMessage>;
/**
* @see https://core.telegram.org/bots/api#sendanimation
*/
sendAnimation(animation: string | tg.InputFile, extra?: tt.ExtraAnimation): Promise<tg.Message.AnimationMessage>;
/**
* @see https://core.telegram.org/bots/api#sendanimation
*/
replyWithAnimation(...args: Shorthand<'sendAnimation'>): Promise<tg.Message.AnimationMessage>;
/**
* @see https://core.telegram.org/bots/api#sendvideonote
*/
sendVideoNote(videoNote: string | tg.InputFileVideoNote, extra?: tt.ExtraVideoNote): Promise<tg.Message.VideoNoteMessage>;
/**
* @see https://core.telegram.org/bots/api#sendvideonote
*/
replyWithVideoNote(...args: Shorthand<'sendVideoNote'>): Promise<tg.Message.VideoNoteMessage>;
/**
* @see https://core.telegram.org/bots/api#sendinvoice
*/
sendInvoice(invoice: tt.NewInvoiceParameters, extra?: tt.ExtraInvoice): Promise<tg.Message.InvoiceMessage>;
/**
* @see https://core.telegram.org/bots/api#sendinvoice
*/
replyWithInvoice(...args: Shorthand<'sendInvoice'>): Promise<tg.Message.InvoiceMessage>;
/**
* @see https://core.telegram.org/bots/api#sendgame
*/
sendGame(game: string, extra?: tt.ExtraGame): Promise<tg.Message.GameMessage>;
/**
* @see https://core.telegram.org/bots/api#sendgame
*/
replyWithGame(...args: Shorthand<'sendGame'>): Promise<tg.Message.GameMessage>;
/**
* @see https://core.telegram.org/bots/api#sendvoice
*/
sendVoice(voice: string | tg.InputFile, extra?: tt.ExtraVoice): Promise<tg.Message.VoiceMessage>;
/**
* @see https://core.telegram.org/bots/api#sendvoice
*/
replyWithVoice(...args: Shorthand<'sendVoice'>): Promise<tg.Message.VoiceMessage>;
/**
* @see https://core.telegram.org/bots/api#sendpoll
*/
sendPoll(poll: string, options: readonly string[], extra?: tt.ExtraPoll): Promise<tg.Message.PollMessage>;
/**
* @see https://core.telegram.org/bots/api#sendpoll
*/
replyWithPoll(...args: Shorthand<'sendPoll'>): Promise<tg.Message.PollMessage>;
/**
* @see https://core.telegram.org/bots/api#sendpoll
*/
sendQuiz(quiz: string, options: readonly string[], extra?: tt.ExtraPoll): Promise<tg.Message.PollMessage>;
/**
* @see https://core.telegram.org/bots/api#sendpoll
*/
replyWithQuiz(...args: Shorthand<'sendQuiz'>): Promise<tg.Message.PollMessage>;
/**
* @see https://core.telegram.org/bots/api#stoppoll
*/
stopPoll(...args: Shorthand<'stopPoll'>): Promise<tg.Poll>;
/**
* @see https://core.telegram.org/bots/api#sendchataction
*/
sendChatAction(action: Shorthand<'sendChatAction'>[0], extra?: tt.ExtraSendChatAction): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#sendchataction
*
* Sends the sendChatAction request repeatedly, with a delay between requests,
* as long as the provided callback function is being processed.
*
* The sendChatAction errors should be ignored, because the goal is the actual long process completing and performing an action.
*
* @param action - chat action type.
* @param callback - a function to run along with the chat action.
* @param extra - extra parameters for sendChatAction.
* @param {number} [extra.intervalDuration=8000] - The duration (in milliseconds) between subsequent sendChatAction requests.
*/
persistentChatAction(action: Shorthand<'sendChatAction'>[0], callback: () => Promise<void>, { intervalDuration, ...extra }?: tt.ExtraSendChatAction & {
intervalDuration?: number;
}): Promise<void>;
/**
* @deprecated use {@link Context.sendChatAction} instead
* @see https://core.telegram.org/bots/api#sendchataction
*/
replyWithChatAction(...args: Shorthand<'sendChatAction'>): Promise<true>;
/**
* Shorthand for {@link Telegram.setMessageReaction}
* @param reaction An emoji or custom_emoji_id to set as reaction to current message. Leave empty to remove reactions.
* @param is_big Pass True to set the reaction with a big animation
*/
react(reaction?: MaybeArray<tg.TelegramEmoji | `${Digit}${string}` | tg.ReactionType>, is_big?: boolean): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#sendlocation
*/
sendLocation(latitude: number, longitude: number, extra?: tt.ExtraLocation): Promise<tg.Message.LocationMessage>;
/**
* @see https://core.telegram.org/bots/api#sendlocation
*/
replyWithLocation(...args: Shorthand<'sendLocation'>): Promise<tg.Message.LocationMessage>;
/**
* @see https://core.telegram.org/bots/api#sendvenue
*/
sendVenue(latitude: number, longitude: number, title: string, address: string, extra?: tt.ExtraVenue): Promise<tg.Message.VenueMessage>;
/**
* @see https://core.telegram.org/bots/api#sendvenue
*/
replyWithVenue(...args: Shorthand<'sendVenue'>): Promise<tg.Message.VenueMessage>;
/**
* @see https://core.telegram.org/bots/api#sendcontact
*/
sendContact(phoneNumber: string, firstName: string, extra?: tt.ExtraContact): Promise<tg.Message.ContactMessage>;
/**
* @see https://core.telegram.org/bots/api#sendcontact
*/
replyWithContact(...args: Shorthand<'sendContact'>): Promise<tg.Message.ContactMessage>;
/**
* @deprecated use {@link Telegram.getStickerSet}
* @see https://core.telegram.org/bots/api#getstickerset
*/
getStickerSet(setName: string): Promise<tg.StickerSet>;
/**
* @see https://core.telegram.org/bots/api#setchatstickerset
*/
setChatStickerSet(setName: string): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#deletechatstickerset
*/
deleteChatStickerSet(): Promise<true>;
/**
* Use this method to create a topic in a forum supergroup chat. The bot must be an administrator in the chat for this
* to work and must have the can_manage_topics administrator rights. Returns information about the created topic as a
* ForumTopic object.
*
* @see https://core.telegram.org/bots/api#createforumtopic
*/
createForumTopic(...args: Shorthand<'createForumTopic'>): Promise<tg.ForumTopic>;
/**
* Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must be an administrator in
* the chat for this to work and must have can_manage_topics administrator rights, unless it is the creator of the
* topic. Returns True on success.
*
* @see https://core.telegram.org/bots/api#editforumtopic
*/
editForumTopic(extra: tt.ExtraEditForumTopic): Promise<true>;
/**
* Use this method to close an open topic in a forum supergroup chat. The bot must be an administrator in the chat
* for this to work and must have the can_manage_topics administrator rights, unless it is the creator of the topic.
* Returns True on success.
*
* @see https://core.telegram.org/bots/api#closeforumtopic
*/
closeForumTopic(): Promise<true>;
/**
* Use this method to reopen a closed topic in a forum supergroup chat. The bot must be an administrator in the chat
* for this to work and must have the can_manage_topics administrator rights, unless it is the creator of the topic.
* Returns True on success.
*
* @see https://core.telegram.org/bots/api#reopenforumtopic
*/
reopenForumTopic(): Promise<true>;
/**
* Use this method to delete a forum topic along with all its messages in a forum supergroup chat. The bot must be an
* administrator in the chat for this to work and must have the can_delete_messages administrator rights.
* Returns True on success.
*
* @see https://core.telegram.org/bots/api#deleteforumtopic
*/
deleteForumTopic(): Promise<true>;
/**
* Use this method to clear the list of pinned messages in a forum topic. The bot must be an administrator in the chat
* for this to work and must have the can_pin_messages administrator right in the supergroup. Returns True on success.
*
* @see https://core.telegram.org/bots/api#unpinallforumtopicmessages
*/
unpinAllForumTopicMessages(): Promise<true>;
/**
* Use this method to edit the name of the 'General' topic in a forum supergroup chat. The bot must be an administrator
* in the chat for this to work and must have can_manage_topics administrator rights. Returns True on success.
*
* @see https://core.telegram.org/bots/api#editgeneralforumtopic
*/
editGeneralForumTopic(name: string): Promise<true>;
/**
* Use this method to close an open 'General' topic in a forum supergroup chat. The bot must be an administrator in the
* chat for this to work and must have the can_manage_topics administrator rights. Returns True on success.
*
* @see https://core.telegram.org/bots/api#closegeneralforumtopic
*/
closeGeneralForumTopic(): Promise<true>;
/**
* Use this method to reopen a closed 'General' topic in a forum supergroup chat. The bot must be an administrator in
* the chat for this to work and must have the can_manage_topics administrator rights. The topic will be automatically
* unhidden if it was hidden. Returns True on success.
*
* @see https://core.telegram.org/bots/api#reopengeneralforumtopic
*/
reopenGeneralForumTopic(): Promise<true>;
/**
* Use this method to hide the 'General' topic in a forum supergroup chat. The bot must be an administrator in the chat
* for this to work and must have the can_manage_topics administrator rights. The topic will be automatically closed
* if it was open. Returns True on success.
*
* @see https://core.telegram.org/bots/api#hidegeneralforumtopic
*/
hideGeneralForumTopic(): Promise<true>;
/**
* Use this method to unhide the 'General' topic in a forum supergroup chat. The bot must be an administrator in the
* chat for this to work and must have the can_manage_topics administrator rights. Returns True on success.
*
* @see https://core.telegram.org/bots/api#unhidegeneralforumtopic
*/
unhideGeneralForumTopic(): Promise<true>;
/**
* Use this method to clear the list of pinned messages in a General forum topic.
* The bot must be an administrator in the chat for this to work and must have the can_pin_messages administrator
* right in the supergroup.
*
* @param chat_id Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
*
* @see https://core.telegram.org/bots/api#unpinallgeneralforumtopicmessages
*/
unpinAllGeneralForumTopicMessages(): Promise<true>;
/**
* @deprecated use {@link Telegram.setStickerPositionInSet}
* @see https://core.telegram.org/bots/api#setstickerpositioninset
*/
setStickerPositionInSet(sticker: string, position: number): Promise<true>;
/**
* @deprecated use {@link Telegram.setStickerSetThumbnail}
* @see https://core.telegram.org/bots/api#setstickersetthumbnail
*/
setStickerSetThumb(...args: Parameters<Telegram['setStickerSetThumbnail']>): Promise<true>;
setStickerSetThumbnail(...args: Parameters<Telegram['setStickerSetThumbnail']>): Promise<true>;
setStickerMaskPosition(...args: Parameters<Telegram['setStickerMaskPosition']>): Promise<true>;
setStickerKeywords(...args: Parameters<Telegram['setStickerKeywords']>): Promise<true>;
setStickerEmojiList(...args: Parameters<Telegram['setStickerEmojiList']>): Promise<true>;
deleteStickerSet(...args: Parameters<Telegram['deleteStickerSet']>): Promise<true>;
setStickerSetTitle(...args: Parameters<Telegram['setStickerSetTitle']>): Promise<true>;
setCustomEmojiStickerSetThumbnail(...args: Parameters<Telegram['setCustomEmojiStickerSetThumbnail']>): Promise<true>;
/**
* @deprecated use {@link Telegram.deleteStickerFromSet}
* @see https://core.telegram.org/bots/api#deletestickerfromset
*/
deleteStickerFromSet(sticker: string): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#uploadstickerfile
*/
uploadStickerFile(...args: Shorthand<'uploadStickerFile'>): Promise<tg.File>;
/**
* @see https://core.telegram.org/bots/api#createnewstickerset
*/
createNewStickerSet(...args: Shorthand<'createNewStickerSet'>): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#addstickertoset
*/
addStickerToSet(...args: Shorthand<'addStickerToSet'>): Promise<true>;
/**
* @deprecated use {@link Telegram.getMyCommands}
* @see https://core.telegram.org/bots/api#getmycommands
*/
getMyCommands(): Promise<tg.BotCommand[]>;
/**
* @deprecated use {@link Telegram.setMyCommands}
* @see https://core.telegram.org/bots/api#setmycommands
*/
setMyCommands(commands: readonly tg.BotCommand[]): Promise<true>;
/**
* @deprecated use {@link Context.replyWithMarkdownV2}
* @see https://core.telegram.org/bots/api#sendmessage
*/
replyWithMarkdown(markdown: string, extra?: tt.ExtraReplyMessage): Promise<tg.Message.TextMessage>;
/**
* @see https://core.telegram.org/bots/api#sendmessage
*/
replyWithMarkdownV2(markdown: string, extra?: tt.ExtraReplyMessage): Promise<tg.Message.TextMessage>;
/**
* @see https://core.telegram.org/bots/api#sendmessage
*/
replyWithHTML(html: string, extra?: tt.ExtraReplyMessage): Promise<tg.Message.TextMessage>;
/**
* @see https://core.telegram.org/bots/api#deletemessage
*/
deleteMessage(messageId?: number): Promise<true>;
/**
* Context-aware shorthand for {@link Telegram.deleteMessages}
* @param messageIds Identifiers of 1-100 messages to delete. See deleteMessage for limitations on which messages can be deleted
*/
deleteMessages(messageIds: number[]): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#forwardmessage
*/
forwardMessage(chatId: string | number, extra?: Shorthand<'forwardMessage'>[2]): Promise<tg.Message>;
/**
* Shorthand for {@link Telegram.forwardMessages}
* @see https://core.telegram.org/bots/api#forwardmessages
*/
forwardMessages(chatId: string | number, messageIds: number[], extra?: Shorthand<'forwardMessages'>[2]): Promise<tg.MessageId[]>;
/**
* @see https://core.telegram.org/bots/api#copymessage
*/
copyMessage(chatId: string | number, extra?: tt.ExtraCopyMessage): Promise<tg.MessageId>;
/**
* Context-aware shorthand for {@link Telegram.copyMessages}
* @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername)
* @param messageIds Identifiers of 1-100 messages in the chat from_chat_id to copy. The identifiers must be specified in a strictly increasing order.
*/
copyMessages(chatId: number | string, messageIds: number[], extra?: tt.ExtraCopyMessages): Promise<tg.MessageId[]>;
/**
* @see https://core.telegram.org/bots/api#approvechatjoinrequest
*/
approveChatJoinRequest(userId: number): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#declinechatjoinrequest
*/
declineChatJoinRequest(userId: number): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#banchatsenderchat
*/
banChatSenderChat(senderChatId: number): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#unbanchatsenderchat
*/
unbanChatSenderChat(senderChatId: number): Promise<true>;
/**
* Use this method to change the bot's menu button in the current private chat. Returns true on success.
* @see https://core.telegram.org/bots/api#setchatmenubutton
*/
setChatMenuButton(menuButton?: tg.MenuButton): Promise<true>;
/**
* Use this method to get the current value of the bot's menu button in the current private chat. Returns MenuButton on success.
* @see https://core.telegram.org/bots/api#getchatmenubutton
*/
getChatMenuButton(): Promise<tg.MenuButton>;
/**
* @see https://core.telegram.org/bots/api#setmydefaultadministratorrights
*/
setMyDefaultAdministratorRights(extra?: Parameters<Telegram['setMyDefaultAdministratorRights']>[0]): Promise<true>;
/**
* @see https://core.telegram.org/bots/api#getmydefaultadministratorrights
*/
getMyDefaultAdministratorRights(extra?: Parameters<Telegram['getMyDefaultAdministratorRights']>[0]): Promise<tg.ChatAdministratorRights>;
}
export default Context;
type UpdateTypes<U extends Deunionize<tg.Update>> = Extract<UnionKeys<U>, tt.UpdateType>;
export type GetUpdateContent<U extends tg.Update> = U extends tg.Update.CallbackQueryUpdate ? U['callback_query']['message'] : U[UpdateTypes<U>];
type Getter<U extends Deunionize<tg.Update>, P extends string> = PropOr<GetUpdateContent<U>, P>;
interface Msg {
isAccessible(): this is MaybeMessage<tg.Message>;
has<Ks extends UnionKeys<tg.Message>[]>(...keys: Ks): this is MaybeMessage<Keyed<tg.Message, Ks[number]>>;
}
declare const Msg: Msg;
export type MaybeMessage<M extends tg.MaybeInaccessibleMessage = tg.MaybeInaccessibleMessage> = M & Msg;
type GetMsg<U extends tg.Update> = U extends tg.Update.MessageUpdate ? U['message'] : U extends tg.Update.ChannelPostUpdate ? U['channel_post'] : U extends tg.Update.EditedChannelPostUpdate ? U['edited_channel_post'] : U extends tg.Update.EditedMessageUpdate ? U['edited_message'] : U extends tg.Update.CallbackQueryUpdate ? U['callback_query']['message'] : undefined;
type GetUserFromAnySource<U extends tg.Update> = GetMsg<U> extends {
from: tg.User;
} ? tg.User : U extends tg.Update.CallbackQueryUpdate | tg.Update.InlineQueryUpdate | tg.Update.ShippingQueryUpdate | tg.Update.PreCheckoutQueryUpdate | tg.Update.ChosenInlineResultUpdate | tg.Update.ChatMemberUpdate | tg.Update.MyChatMemberUpdate | tg.Update.ChatJoinRequestUpdate | tg.Update.MessageReactionUpdate | tg.Update.PollAnswerUpdate | tg.Update.ChatBoostUpdate ? tg.User : undefined;
type GetMsgId<U extends tg.Update> = GetMsg<U> extends {
message_id: number;
} ? number : U extends tg.Update.MessageReactionUpdate ? number : U extends tg.Update.MessageReactionCountUpdate ? number : undefined;
type GetText<U extends tg.Update> = GetMsg<U> extends tg.Message.TextMessage ? string : GetMsg<U> extends tg.Message ? string | undefined : U extends tg.Update.PollUpdate ? string | undefined : undefined;
//# sourceMappingURL=context.d.ts.map

1
node_modules/telegraf/typings/context.d.ts.map generated vendored Normal file

File diff suppressed because one or more lines are too long

11
node_modules/telegraf/typings/core/helpers/args.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
interface Entity {
/** Type of the entity. Currently, can be “mention” (@username), “hashtag” (#hashtag), “cashtag” ($USD), “bot_command” (/start@jobs_bot), “url” (https://telegram.org), “email” (do-not-reply@telegram.org), “phone_number” (+1-212-555-0123), “bold” (bold text), “italic” (italic text), “underline” (underlined text), “strikethrough” (strikethrough text), “spoiler” (spoiler message), “code” (monowidth string), “pre” (monowidth block), “text_link” (for clickable text URLs), “text_mention” (for users without usernames), “custom_emoji” (for inline custom emoji stickers) */
type: string;
/** Offset in UTF-16 code units to the start of the entity */
offset: number;
/** Length of the entity in UTF-16 code units */
length: number;
}
export declare function argsParser(str: string, entities?: Entity[], entityOffset?: number): string[];
export {};
//# sourceMappingURL=args.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../src/core/helpers/args.ts"],"names":[],"mappings":"AAAA,UAAU,MAAM;IACd,0jBAA0jB;IAC1jB,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAA;IACd,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAA;CACf;AAKD,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,EAAO,EACvB,YAAY,SAAI,YA+CjB"}

Some files were not shown because too many files have changed in this diff Show More