mirror of
https://github.com/Maks1mS/nestjs-telegraf.git
synced 2024-12-24 15:04:38 +03:00
merge refactor/v2
This commit is contained in:
commit
320ee3077e
@ -1,64 +0,0 @@
|
|||||||
{
|
|
||||||
"files": [
|
|
||||||
"README.md"
|
|
||||||
],
|
|
||||||
"imageSize": 100,
|
|
||||||
"commit": false,
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"login": "Sedjj",
|
|
||||||
"name": "Eldar Salimzebarov",
|
|
||||||
"avatar_url": "https://avatars3.githubusercontent.com/u/5383030?v=4",
|
|
||||||
"profile": "https://github.com/Sedjj",
|
|
||||||
"contributions": [
|
|
||||||
"bug"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "lamuertepeluda",
|
|
||||||
"name": "Vito Macchia",
|
|
||||||
"avatar_url": "https://avatars3.githubusercontent.com/u/2249342?v=4",
|
|
||||||
"profile": "http://www.ismb.it/vito.macchia",
|
|
||||||
"contributions": [
|
|
||||||
"code",
|
|
||||||
"bug"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "edgesite",
|
|
||||||
"name": "KITAHARA SETSUNA",
|
|
||||||
"avatar_url": "https://avatars3.githubusercontent.com/u/10336620?v=4",
|
|
||||||
"profile": "https://github.com/edgesite",
|
|
||||||
"contributions": [
|
|
||||||
"code",
|
|
||||||
"bug"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "bukhalo",
|
|
||||||
"name": "Aleksandr Bukhalo",
|
|
||||||
"avatar_url": "https://avatars2.githubusercontent.com/u/14031838?v=4",
|
|
||||||
"profile": "https://bukhalo.com/",
|
|
||||||
"contributions": [
|
|
||||||
"code",
|
|
||||||
"doc",
|
|
||||||
"review"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "VyacheslavSaloidWork",
|
|
||||||
"name": "Vyacheslav Saloid",
|
|
||||||
"avatar_url": "https://avatars3.githubusercontent.com/u/43011265?v=4",
|
|
||||||
"profile": "https://github.com/VyacheslavSaloidWork",
|
|
||||||
"contributions": [
|
|
||||||
"bug"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"contributorsPerLine": 7,
|
|
||||||
"projectName": "nestjs-telegraf",
|
|
||||||
"projectOwner": "bukhalo",
|
|
||||||
"repoType": "github",
|
|
||||||
"repoHost": "https://github.com",
|
|
||||||
"skipCi": true
|
|
||||||
}
|
|
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1 +1 @@
|
|||||||
custom: ["https://www.tinkoff.ru/sl/95M2htqoxux"]
|
custom: ['https://www.tinkoff.ru/sl/95M2htqoxux']
|
||||||
|
11
.github/dependabot.yml
vendored
11
.github/dependabot.yml
vendored
@ -1,11 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
# Configuration for npm
|
|
||||||
- package-ecosystem: "npm"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
reviewers:
|
|
||||||
- "bukhalo"
|
|
||||||
assignees:
|
|
||||||
- "bukhalo"
|
|
4
.github/workflows/build-test.yml
vendored
4
.github/workflows/build-test.yml
vendored
@ -12,12 +12,12 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [12.x, 13.x]
|
node-version: [14.x, 15.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
|||||||
# lock
|
# lock
|
||||||
package-lock.json
|
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2019 - present Bukhalo Aleksandr Aleksandrovich
|
Copyright (c) 2019 - present Alexander Bukhalo (a@bukhalo.com)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
37
README.md
37
README.md
@ -71,40 +71,3 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
|
||||||
|
|
||||||
## People
|
|
||||||
|
|
||||||
- Authors - [Aleksandr Bukhalo](https://bukhalo.com/) & [Igor Kamyshev](https://kamyshev.me/)
|
|
||||||
- Maintainers - [Aleksandr Bukhalo](https://bukhalo.com/)
|
|
||||||
- Website - [https://nestjs.com](https://nestjs.com/)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
|
|
||||||
|
|
||||||
## Contributors ✨
|
|
||||||
|
|
||||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
|
||||||
|
|
||||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
|
||||||
<!-- prettier-ignore-start -->
|
|
||||||
<!-- markdownlint-disable -->
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td align="center"><a href="https://github.com/Sedjj"><img src="https://avatars3.githubusercontent.com/u/5383030?v=4" width="100px;" alt=""/><br /><sub><b>Eldar Salimzebarov</b></sub></a><br /><a href="https://github.com/bukhalo/nestjs-telegraf/issues?q=author%3ASedjj" title="Bug reports">🐛</a></td>
|
|
||||||
<td align="center"><a href="http://www.ismb.it/vito.macchia"><img src="https://avatars3.githubusercontent.com/u/2249342?v=4" width="100px;" alt=""/><br /><sub><b>Vito Macchia</b></sub></a><br /><a href="https://github.com/bukhalo/nestjs-telegraf/commits?author=lamuertepeluda" title="Code">💻</a> <a href="https://github.com/bukhalo/nestjs-telegraf/issues?q=author%3Alamuertepeluda" title="Bug reports">🐛</a></td>
|
|
||||||
<td align="center"><a href="https://github.com/edgesite"><img src="https://avatars3.githubusercontent.com/u/10336620?v=4" width="100px;" alt=""/><br /><sub><b>KITAHARA SETSUNA</b></sub></a><br /><a href="https://github.com/bukhalo/nestjs-telegraf/commits?author=edgesite" title="Code">💻</a> <a href="https://github.com/bukhalo/nestjs-telegraf/issues?q=author%3Aedgesite" title="Bug reports">🐛</a></td>
|
|
||||||
<td align="center"><a href="https://bukhalo.com/"><img src="https://avatars2.githubusercontent.com/u/14031838?v=4" width="100px;" alt=""/><br /><sub><b>Aleksandr Bukhalo</b></sub></a><br /><a href="https://github.com/bukhalo/nestjs-telegraf/commits?author=bukhalo" title="Code">💻</a> <a href="https://github.com/bukhalo/nestjs-telegraf/commits?author=bukhalo" title="Documentation">📖</a> <a href="https://github.com/bukhalo/nestjs-telegraf/pulls?q=is%3Apr+reviewed-by%3Abukhalo" title="Reviewed Pull Requests">👀</a></td>
|
|
||||||
<td align="center"><a href="https://github.com/VyacheslavSaloidWork"><img src="https://avatars3.githubusercontent.com/u/43011265?v=4" width="100px;" alt=""/><br /><sub><b>Vyacheslav Saloid</b></sub></a><br /><a href="https://github.com/bukhalo/nestjs-telegraf/issues?q=author%3AVyacheslavSaloidWork" title="Bug reports">🐛</a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- markdownlint-enable -->
|
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
||||||
|
|
||||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Inject } from '@nestjs/common';
|
import { Inject } from '@nestjs/common';
|
||||||
import { Telegraf } from 'telegraf';
|
import { getBotToken } from '../../utils';
|
||||||
|
|
||||||
export const InjectBot = (): ParameterDecorator => Inject(Telegraf);
|
export const InjectBot = (name?: string): ParameterDecorator =>
|
||||||
|
Inject(getBotToken(name));
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for handling callback_data actions with regular expressions.
|
* Registers middleware for handling callback_data actions with regular expressions.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=action
|
* @see https://telegraf.js.org/#/?id=action
|
||||||
*/
|
*/
|
||||||
export const Action = createUpdateListenerDecorator('action');
|
export const Action = createListenerDecorator('action');
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cashtag handling.
|
* Cashtag handling.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=cashtag
|
* @see https://telegraf.js.org/#/?id=cashtag
|
||||||
*/
|
*/
|
||||||
export const Cashtag = createUpdateListenerDecorator('cashtag');
|
export const Cashtag = createMissedListenerDecorator<[string | string[]]>(
|
||||||
|
'cashtag',
|
||||||
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command handling.
|
* Command handling.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=command
|
* @see https://telegraf.js.org/#/?id=command
|
||||||
*/
|
*/
|
||||||
export const Command = createUpdateListenerDecorator('command');
|
export const Command = createListenerDecorator('command');
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for handling messages with email entity.
|
* Registers middleware for handling messages with email entity.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=telegraf-email
|
* @see https://telegraf.js.org/#/?id=telegraf-email
|
||||||
*/
|
*/
|
||||||
export const Email = createUpdateListenerDecorator('email');
|
export const Email = createMissedListenerDecorator<[string | string[]]>(
|
||||||
|
'email',
|
||||||
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for handling callback_data actions with game query.
|
* Registers middleware for handling callback_data actions with game query.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=inlinequery
|
* @see https://telegraf.js.org/#/?id=inlinequery
|
||||||
*/
|
*/
|
||||||
export const GameQuery = createUpdateListenerDecorator('gameQuery');
|
export const GameQuery = createListenerDecorator('gameQuery');
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hashtag handling.
|
* Hashtag handling.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=hashtag
|
* @see https://telegraf.js.org/#/?id=hashtag
|
||||||
*/
|
*/
|
||||||
export const Hashtag = createUpdateListenerDecorator('hashtag');
|
export const Hashtag = createMissedListenerDecorator<[string | string[]]>(
|
||||||
|
'hashtag',
|
||||||
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for handling text messages.
|
* Registers middleware for handling text messages.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=hears
|
* @see https://telegraf.js.org/#/?id=hears
|
||||||
*/
|
*/
|
||||||
export const Hears = createUpdateListenerDecorator('hears');
|
export const Hears = createListenerDecorator('hears');
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for /help command.
|
* Handler for /help command.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=help
|
* @see https://telegraf.js.org/#/?id=help
|
||||||
*/
|
*/
|
||||||
export const Help = createUpdateListenerDecorator('help');
|
export const Help = createListenerDecorator('help');
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
import { HearsTriggers } from 'telegraf/typings/composer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for handling inline_query actions with regular expressions.
|
* Registers middleware for handling inline_query actions with regular expressions.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=inlinequery
|
* @see https://telegraf.js.org/#/?id=inlinequery
|
||||||
*/
|
*/
|
||||||
export const InlineQuery = createUpdateListenerDecorator('inlineQuery');
|
export const InlineQuery = createMissedListenerDecorator<
|
||||||
|
[HearsTriggers<unknown>]
|
||||||
|
>('inlineQuery');
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mention handling.
|
* Mention handling.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=mention
|
* @see https://telegraf.js.org/#/?id=mention
|
||||||
*/
|
*/
|
||||||
export const Mention = createUpdateListenerDecorator('mention');
|
export const Mention = createMissedListenerDecorator<[string | string[]]>(
|
||||||
|
'mention',
|
||||||
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for provided update type.
|
* Registers middleware for provided update type.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=on
|
* @see https://telegraf.js.org/#/?id=on
|
||||||
*/
|
*/
|
||||||
export const On = createUpdateListenerDecorator('on');
|
export const On = createListenerDecorator('on');
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Phone number handling.
|
* Phone number handling.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=phone
|
* @see https://telegraf.js.org/#/?id=phone
|
||||||
*/
|
*/
|
||||||
export const Phone = createUpdateListenerDecorator('phone');
|
export const Phone = createMissedListenerDecorator<[string | string[]]>(
|
||||||
|
'phone',
|
||||||
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for /settings command.
|
* Handler for /settings command.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=settings
|
* @see https://telegraf.js.org/#/?id=settings
|
||||||
*/
|
*/
|
||||||
export const Settings = createUpdateListenerDecorator('settings');
|
export const Settings = createMissedListenerDecorator<[]>('settings');
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for /start command.
|
* Handler for /start command.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=start
|
* @see https://telegraf.js.org/#/?id=start
|
||||||
*/
|
*/
|
||||||
export const Start = createUpdateListenerDecorator('start');
|
export const Start = createListenerDecorator('start');
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for handling messages with text_link entity.
|
* Registers middleware for handling messages with text_link entity.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=telegraf-textlink
|
* @see https://telegraf.js.org/#/?id=telegraf-textlink
|
||||||
*/
|
*/
|
||||||
export const TextLink = createUpdateListenerDecorator('textLink');
|
export const TextLink = createMissedListenerDecorator<[string | string[]]>(
|
||||||
|
'textLink',
|
||||||
|
);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for handling messages with text_mention entity.
|
* Registers middleware for handling messages with text_mention entity.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=telegraf-textlink
|
* @see https://telegraf.js.org/#/?id=telegraf-textlink
|
||||||
*/
|
*/
|
||||||
export const TextMention = createUpdateListenerDecorator('textMention');
|
export const TextMention = createMissedListenerDecorator<[string | string[]]>(
|
||||||
|
'textMention',
|
||||||
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createMissedListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers middleware for handling messages with url entity.
|
* Registers middleware for handling messages with url entity.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=telegraf-url
|
* @see https://telegraf.js.org/#/?id=telegraf-url
|
||||||
*/
|
*/
|
||||||
export const Url = createUpdateListenerDecorator('url');
|
export const Url = createMissedListenerDecorator<[string | string[]]>('url');
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createUpdateListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a middleware.
|
* Registers a middleware.
|
||||||
*
|
*
|
||||||
* @see https://telegraf.js.org/#/?id=use
|
* @see https://telegraf.js.org/#/?id=use
|
||||||
*/
|
*/
|
||||||
export const Use = createUpdateListenerDecorator('use');
|
export const Use = createListenerDecorator('use');
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
import { createSceneListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
export const SceneEnter = createSceneListenerDecorator('enter');
|
export const SceneEnter = createListenerDecorator('enter');
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
import { createSceneListenerDecorator } from '../../utils';
|
import { createListenerDecorator } from '../../utils';
|
||||||
|
|
||||||
export const SceneLeave = createSceneListenerDecorator('leave');
|
export const SceneLeave = createListenerDecorator('leave');
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
|
|
||||||
import { DiscoveryService } from '@nestjs/core';
|
|
||||||
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
|
||||||
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
|
||||||
import { BaseScene as Scene, Stage, Telegraf } from 'telegraf';
|
|
||||||
import { TelegrafMetadataAccessor } from '../telegraf.metadata-accessor';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class TelegrafSceneExplorer implements OnModuleInit {
|
|
||||||
private readonly stage = new Stage([]);
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
@Inject(Telegraf)
|
|
||||||
private readonly telegraf: Telegraf<never>,
|
|
||||||
private readonly discoveryService: DiscoveryService,
|
|
||||||
private readonly metadataAccessor: TelegrafMetadataAccessor,
|
|
||||||
private readonly metadataScanner: MetadataScanner,
|
|
||||||
) {
|
|
||||||
this.telegraf.use(this.stage.middleware());
|
|
||||||
}
|
|
||||||
|
|
||||||
onModuleInit(): void {
|
|
||||||
this.explore();
|
|
||||||
}
|
|
||||||
|
|
||||||
private explore(): void {
|
|
||||||
const sceneClasses = this.filterSceneClasses();
|
|
||||||
|
|
||||||
sceneClasses.forEach((wrapper) => {
|
|
||||||
const { instance } = wrapper;
|
|
||||||
|
|
||||||
const sceneId = this.metadataAccessor.getSceneMetadata(
|
|
||||||
instance.constructor,
|
|
||||||
);
|
|
||||||
const scene = new Scene(sceneId);
|
|
||||||
this.stage.register(scene);
|
|
||||||
|
|
||||||
const prototype = Object.getPrototypeOf(instance);
|
|
||||||
this.metadataScanner.scanFromPrototype(
|
|
||||||
instance,
|
|
||||||
prototype,
|
|
||||||
(methodKey: string) =>
|
|
||||||
this.registerIfListener(scene, instance, methodKey),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private filterSceneClasses(): InstanceWrapper[] {
|
|
||||||
return this.discoveryService
|
|
||||||
.getProviders()
|
|
||||||
.filter((wrapper) => wrapper.instance)
|
|
||||||
.filter((wrapper) =>
|
|
||||||
this.metadataAccessor.isScene(wrapper.instance.constructor),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private registerIfListener(
|
|
||||||
scene: Scene<never>,
|
|
||||||
instance: Record<string, Function>,
|
|
||||||
methodKey: string,
|
|
||||||
): void {
|
|
||||||
const methodRef = instance[methodKey];
|
|
||||||
const middlewareFn = methodRef.bind(instance);
|
|
||||||
|
|
||||||
const listenerMetadata = this.metadataAccessor.getListenerMetadata(
|
|
||||||
methodRef,
|
|
||||||
);
|
|
||||||
if (!listenerMetadata) return;
|
|
||||||
|
|
||||||
const { method, args } = listenerMetadata;
|
|
||||||
(scene[method] as any)(...args, middlewareFn);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
export * from './decorators';
|
export * from './decorators';
|
||||||
export * from './interfaces';
|
export * from './interfaces';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
export * from './errors';
|
export * from './types';
|
||||||
export * from './execution-context';
|
export * from './telegraf.constants';
|
||||||
export * from './telegraf.module';
|
export * from './telegraf.module';
|
||||||
export * from './telegraf.types';
|
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';
|
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';
|
||||||
import { Middleware, Context } from 'telegraf';
|
import { Middleware, Context } from 'telegraf';
|
||||||
import {
|
import {
|
||||||
|
TelegrafOptions,
|
||||||
LaunchPollingOptions,
|
LaunchPollingOptions,
|
||||||
LaunchWebhookOptions,
|
LaunchWebhookOptions,
|
||||||
TelegrafOptions,
|
|
||||||
} from 'telegraf/typings/telegraf';
|
} from 'telegraf/typings/telegraf';
|
||||||
|
|
||||||
export interface TelegrafModuleOptions<C extends Context = Context> {
|
export interface TelegrafModuleOptions<C extends Context = Context> {
|
||||||
token: string;
|
token: string;
|
||||||
|
name?: string;
|
||||||
options?: TelegrafOptions;
|
options?: TelegrafOptions;
|
||||||
launchOptions?: {
|
launchOptions?: {
|
||||||
polling?: LaunchPollingOptions;
|
polling?: LaunchPollingOptions;
|
||||||
webhook?: LaunchWebhookOptions;
|
webhook?: LaunchWebhookOptions;
|
||||||
};
|
};
|
||||||
middlewares?: Middleware<C>[];
|
include?: Function[];
|
||||||
|
middlewares?: ReadonlyArray<Middleware<C>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TelegrafOptionsFactory {
|
export interface TelegrafOptionsFactory {
|
||||||
@ -22,6 +24,7 @@ export interface TelegrafOptionsFactory {
|
|||||||
|
|
||||||
export interface TelegrafModuleAsyncOptions
|
export interface TelegrafModuleAsyncOptions
|
||||||
extends Pick<ModuleMetadata, 'imports'> {
|
extends Pick<ModuleMetadata, 'imports'> {
|
||||||
|
botName?: string;
|
||||||
useExisting?: Type<TelegrafOptionsFactory>;
|
useExisting?: Type<TelegrafOptionsFactory>;
|
||||||
useClass?: Type<TelegrafOptionsFactory>;
|
useClass?: Type<TelegrafOptionsFactory>;
|
||||||
useFactory?: (
|
useFactory?: (
|
||||||
|
37
lib/services/base-explorer.service.ts
Normal file
37
lib/services/base-explorer.service.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
||||||
|
import { Module } from '@nestjs/core/injector/module';
|
||||||
|
import { flattenDeep, identity, isEmpty } from 'lodash';
|
||||||
|
|
||||||
|
export class BaseExplorerService {
|
||||||
|
getModules(
|
||||||
|
modulesContainer: Map<string, Module>,
|
||||||
|
include: Function[],
|
||||||
|
): Module[] {
|
||||||
|
if (!include || isEmpty(include)) {
|
||||||
|
return [...modulesContainer.values()];
|
||||||
|
}
|
||||||
|
const whitelisted = this.includeWhitelisted(modulesContainer, include);
|
||||||
|
return whitelisted;
|
||||||
|
}
|
||||||
|
|
||||||
|
includeWhitelisted(
|
||||||
|
modulesContainer: Map<string, Module>,
|
||||||
|
include: Function[],
|
||||||
|
): Module[] {
|
||||||
|
const modules = [...modulesContainer.values()];
|
||||||
|
return modules.filter(({ metatype }) => include.includes(metatype));
|
||||||
|
}
|
||||||
|
|
||||||
|
flatMap<T>(
|
||||||
|
modules: Module[],
|
||||||
|
callback: (instance: InstanceWrapper, moduleRef: Module) => T | T[],
|
||||||
|
): T[] {
|
||||||
|
const invokeMap = () => {
|
||||||
|
return modules.map((moduleRef) => {
|
||||||
|
const providers = [...moduleRef.providers.values()];
|
||||||
|
return providers.map((wrapper) => callback(wrapper, moduleRef));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return flattenDeep(invokeMap()).filter(identity);
|
||||||
|
}
|
||||||
|
}
|
3
lib/services/index.ts
Normal file
3
lib/services/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './listeners-explorer.service';
|
||||||
|
export * from './metadata-accessor.service';
|
||||||
|
export * from './listeners-explorer.service';
|
111
lib/services/listeners-explorer.service.ts
Normal file
111
lib/services/listeners-explorer.service.ts
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
|
||||||
|
import { DiscoveryService, ModuleRef, ModulesContainer } from '@nestjs/core';
|
||||||
|
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
||||||
|
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
||||||
|
import { Module } from '@nestjs/core/injector/module';
|
||||||
|
import { BaseScene, Composer, Stage, Telegraf } from 'telegraf';
|
||||||
|
|
||||||
|
import { MetadataAccessorService } from './metadata-accessor.service';
|
||||||
|
import { TELEGRAF_MODULE_OPTIONS } from '../telegraf.constants';
|
||||||
|
import { TelegrafModuleOptions } from '../interfaces';
|
||||||
|
import { BaseExplorerService } from './base-explorer.service';
|
||||||
|
import { getBotToken } from '../utils';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ListenersExplorerService
|
||||||
|
extends BaseExplorerService
|
||||||
|
implements OnModuleInit {
|
||||||
|
private readonly stage = new Stage([]);
|
||||||
|
private bot: Telegraf<any>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(TELEGRAF_MODULE_OPTIONS)
|
||||||
|
private readonly telegrafOptions: TelegrafModuleOptions,
|
||||||
|
private readonly moduleRef: ModuleRef,
|
||||||
|
private readonly discoveryService: DiscoveryService,
|
||||||
|
private readonly metadataAccessor: MetadataAccessorService,
|
||||||
|
private readonly metadataScanner: MetadataScanner,
|
||||||
|
private readonly modulesContainer: ModulesContainer,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
onModuleInit(): void {
|
||||||
|
const botToken = getBotToken(this.telegrafOptions.name);
|
||||||
|
this.bot = this.moduleRef.get<Telegraf<never>>(botToken);
|
||||||
|
this.bot.use(this.stage.middleware());
|
||||||
|
|
||||||
|
this.explore();
|
||||||
|
}
|
||||||
|
|
||||||
|
explore(): void {
|
||||||
|
const modules = this.getModules(
|
||||||
|
this.modulesContainer,
|
||||||
|
this.telegrafOptions.include || [],
|
||||||
|
);
|
||||||
|
|
||||||
|
this.registerUpdates(modules);
|
||||||
|
this.registerScenes(modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerUpdates(modules: Module[]): void {
|
||||||
|
const updates = this.flatMap<InstanceWrapper>(modules, (instance) =>
|
||||||
|
this.filterUpdates(instance),
|
||||||
|
);
|
||||||
|
updates.forEach(({ instance }) =>
|
||||||
|
this.registerInstanceMethodListeners(this.bot, instance),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerScenes(modules: Module[]): void {
|
||||||
|
const scenes = this.flatMap<InstanceWrapper>(modules, (instance) =>
|
||||||
|
this.filterScenes(instance),
|
||||||
|
);
|
||||||
|
scenes.forEach(({ instance }) => {
|
||||||
|
const sceneId = this.metadataAccessor.getSceneMetadata(
|
||||||
|
instance.constructor,
|
||||||
|
);
|
||||||
|
const scene = new BaseScene(sceneId);
|
||||||
|
this.stage.register(scene);
|
||||||
|
|
||||||
|
this.registerInstanceMethodListeners(scene, instance);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterUpdates(wrapper: InstanceWrapper): InstanceWrapper<unknown> {
|
||||||
|
const { instance } = wrapper;
|
||||||
|
if (!instance) return undefined;
|
||||||
|
|
||||||
|
const isUpdate = this.metadataAccessor.isUpdate(wrapper.metatype);
|
||||||
|
if (!isUpdate) return undefined;
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterScenes(wrapper: InstanceWrapper): InstanceWrapper<unknown> {
|
||||||
|
const { instance } = wrapper;
|
||||||
|
if (!instance) return undefined;
|
||||||
|
|
||||||
|
const isScene = this.metadataAccessor.isScene(wrapper.metatype);
|
||||||
|
if (!isScene) return undefined;
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerInstanceMethodListeners(
|
||||||
|
composer: Composer<never>,
|
||||||
|
instance: Record<string, Function>,
|
||||||
|
): void {
|
||||||
|
const prototype = Object.getPrototypeOf(instance);
|
||||||
|
this.metadataScanner.scanFromPrototype(instance, prototype, (name) => {
|
||||||
|
const methodRef = instance[name];
|
||||||
|
|
||||||
|
const metadata = this.metadataAccessor.getListenerMetadata(methodRef);
|
||||||
|
if (!metadata) return;
|
||||||
|
|
||||||
|
const middlewareFn = methodRef.bind(instance);
|
||||||
|
const { method, args } = metadata;
|
||||||
|
composer[method](...args, middlewareFn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -4,18 +4,25 @@ import {
|
|||||||
SCENE_METADATA,
|
SCENE_METADATA,
|
||||||
UPDATE_LISTENER_METADATA,
|
UPDATE_LISTENER_METADATA,
|
||||||
UPDATE_METADATA,
|
UPDATE_METADATA,
|
||||||
} from './telegraf.constants';
|
} from '../telegraf.constants';
|
||||||
import { ListenerMetadata } from './interfaces';
|
import { ListenerMetadata } from '../interfaces';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TelegrafMetadataAccessor {
|
export class MetadataAccessorService {
|
||||||
constructor(private readonly reflector: Reflector) {}
|
constructor(private readonly reflector: Reflector) {}
|
||||||
|
|
||||||
isUpdate(target: Function): boolean {
|
isUpdate(target: Function): boolean {
|
||||||
|
// TODO: We really need this check?
|
||||||
|
if (!target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return !!this.reflector.get(UPDATE_METADATA, target);
|
return !!this.reflector.get(UPDATE_METADATA, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
isScene(target: Function): boolean {
|
isScene(target: Function): boolean {
|
||||||
|
if (!target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return !!this.reflector.get(SCENE_METADATA, target);
|
return !!this.reflector.get(SCENE_METADATA, target);
|
||||||
}
|
}
|
||||||
|
|
115
lib/telegraf-core.module.ts
Normal file
115
lib/telegraf-core.module.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { DiscoveryModule, ModuleRef } from '@nestjs/core';
|
||||||
|
import {
|
||||||
|
Module,
|
||||||
|
DynamicModule,
|
||||||
|
Provider,
|
||||||
|
Type,
|
||||||
|
Global,
|
||||||
|
Inject,
|
||||||
|
OnApplicationShutdown,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
TelegrafModuleOptions,
|
||||||
|
TelegrafModuleAsyncOptions,
|
||||||
|
TelegrafOptionsFactory,
|
||||||
|
} from './interfaces';
|
||||||
|
import { TELEGRAF_MODULE_OPTIONS } from './telegraf.constants';
|
||||||
|
import { MetadataAccessorService, ListenersExplorerService } from './services';
|
||||||
|
import { getBotToken, createBotFactory } from './utils';
|
||||||
|
|
||||||
|
@Global()
|
||||||
|
@Module({
|
||||||
|
imports: [DiscoveryModule],
|
||||||
|
providers: [ListenersExplorerService, MetadataAccessorService],
|
||||||
|
})
|
||||||
|
export class TelegrafCoreModule implements OnApplicationShutdown {
|
||||||
|
constructor(
|
||||||
|
@Inject(TELEGRAF_MODULE_OPTIONS)
|
||||||
|
private readonly options: TelegrafModuleOptions,
|
||||||
|
private readonly moduleRef: ModuleRef,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
||||||
|
const telegrafBotProvider: Provider = {
|
||||||
|
provide: getBotToken(options.name),
|
||||||
|
useFactory: async () => await createBotFactory(options),
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
module: TelegrafCoreModule,
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: TELEGRAF_MODULE_OPTIONS,
|
||||||
|
useValue: options,
|
||||||
|
},
|
||||||
|
telegrafBotProvider,
|
||||||
|
],
|
||||||
|
exports: [telegrafBotProvider],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static forRootAsync(
|
||||||
|
options: TelegrafModuleAsyncOptions,
|
||||||
|
): DynamicModule {
|
||||||
|
const telegrafBotName = getBotToken(options.botName);
|
||||||
|
|
||||||
|
const telegrafBotProvider: Provider = {
|
||||||
|
provide: telegrafBotName,
|
||||||
|
useFactory: async (options: TelegrafModuleOptions) =>
|
||||||
|
await createBotFactory(options),
|
||||||
|
inject: [TELEGRAF_MODULE_OPTIONS],
|
||||||
|
};
|
||||||
|
|
||||||
|
const asyncProviders = this.createAsyncProviders(options);
|
||||||
|
return {
|
||||||
|
module: TelegrafCoreModule,
|
||||||
|
imports: options.imports,
|
||||||
|
providers: [...asyncProviders, telegrafBotProvider],
|
||||||
|
exports: [telegrafBotProvider],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async onApplicationShutdown(): Promise<void> {
|
||||||
|
const botName = getBotToken(this.options.name);
|
||||||
|
const bot = this.moduleRef.get<any>(botName);
|
||||||
|
bot && (await bot.stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static createAsyncProviders(
|
||||||
|
options: TelegrafModuleAsyncOptions,
|
||||||
|
): Provider[] {
|
||||||
|
if (options.useExisting || options.useFactory) {
|
||||||
|
return [this.createAsyncOptionsProvider(options)];
|
||||||
|
}
|
||||||
|
const useClass = options.useClass as Type<TelegrafOptionsFactory>;
|
||||||
|
return [
|
||||||
|
this.createAsyncOptionsProvider(options),
|
||||||
|
{
|
||||||
|
provide: useClass,
|
||||||
|
useClass,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static createAsyncOptionsProvider(
|
||||||
|
options: TelegrafModuleAsyncOptions,
|
||||||
|
): Provider {
|
||||||
|
if (options.useFactory) {
|
||||||
|
return {
|
||||||
|
provide: TELEGRAF_MODULE_OPTIONS,
|
||||||
|
useFactory: options.useFactory,
|
||||||
|
inject: options.inject || [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// `as Type<TelegrafOptionsFactory>` is a workaround for microsoft/TypeScript#31603
|
||||||
|
const inject = [
|
||||||
|
(options.useClass || options.useExisting) as Type<TelegrafOptionsFactory>,
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
provide: TELEGRAF_MODULE_OPTIONS,
|
||||||
|
useFactory: async (optionsFactory: TelegrafOptionsFactory) =>
|
||||||
|
await optionsFactory.createTelegrafOptions(),
|
||||||
|
inject,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { ROUTE_ARGS_METADATA } from '@nestjs/common/constants';
|
import { ROUTE_ARGS_METADATA } from '@nestjs/common/constants';
|
||||||
|
|
||||||
export const TELEGRAF_MODULE_OPTIONS = 'TELEGRAF_MODULE_OPTIONS';
|
export const TELEGRAF_MODULE_OPTIONS = 'TELEGRAF_MODULE_OPTIONS';
|
||||||
|
export const DEFAULT_BOT_NAME = 'DEFAULT_BOT_NAME';
|
||||||
|
|
||||||
export const UPDATE_METADATA = 'UPDATE_METADATA';
|
export const UPDATE_METADATA = 'UPDATE_METADATA';
|
||||||
export const UPDATE_LISTENER_METADATA = 'UPDATE_LISTENER_METADATA';
|
export const UPDATE_LISTENER_METADATA = 'UPDATE_LISTENER_METADATA';
|
||||||
|
@ -1,106 +1,27 @@
|
|||||||
import { DiscoveryModule, ModuleRef } from '@nestjs/core';
|
import { Module, DynamicModule } from '@nestjs/common';
|
||||||
|
import { TelegrafCoreModule } from './telegraf-core.module';
|
||||||
import {
|
import {
|
||||||
DynamicModule,
|
|
||||||
Inject,
|
|
||||||
Module,
|
|
||||||
OnApplicationBootstrap,
|
|
||||||
OnApplicationShutdown,
|
|
||||||
Provider,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { Telegraf } from 'telegraf';
|
|
||||||
import {
|
|
||||||
TelegrafModuleAsyncOptions,
|
|
||||||
TelegrafModuleOptions,
|
TelegrafModuleOptions,
|
||||||
TelegrafOptionsFactory,
|
TelegrafModuleAsyncOptions,
|
||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
import { TELEGRAF_MODULE_OPTIONS } from './telegraf.constants';
|
|
||||||
import { TelegrafMetadataAccessor } from './telegraf.metadata-accessor';
|
|
||||||
import { TelegrafUpdateExplorer } from './explorers/telegraf-update.explorer';
|
|
||||||
import { TelegrafSceneExplorer } from './explorers/telegraf-scene.explorer';
|
|
||||||
import { createProviders, TelegrafProvider } from './telegraf.providers';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [DiscoveryModule],
|
|
||||||
providers: [
|
|
||||||
TelegrafMetadataAccessor,
|
|
||||||
TelegrafSceneExplorer,
|
|
||||||
TelegrafUpdateExplorer,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class TelegrafModule
|
|
||||||
implements OnApplicationBootstrap, OnApplicationShutdown {
|
|
||||||
constructor(
|
|
||||||
@Inject(TELEGRAF_MODULE_OPTIONS)
|
|
||||||
private readonly options: TelegrafModuleOptions,
|
|
||||||
private readonly moduleRef: ModuleRef,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async onApplicationBootstrap(): Promise<void> {
|
|
||||||
const { launchOptions } = this.options;
|
|
||||||
const telegraf = this.moduleRef.get(Telegraf);
|
|
||||||
await telegraf.launch(launchOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
async onApplicationShutdown(): Promise<void> {
|
|
||||||
const telegraf = this.moduleRef.get(Telegraf);
|
|
||||||
await telegraf.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Module({})
|
||||||
|
export class TelegrafModule {
|
||||||
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
||||||
const providers = [...createProviders(options), TelegrafProvider];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
module: TelegrafModule,
|
module: TelegrafModule,
|
||||||
providers,
|
imports: [TelegrafCoreModule.forRoot(options)],
|
||||||
exports: providers,
|
exports: [TelegrafCoreModule],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static forRootAsync(
|
public static forRootAsync(
|
||||||
options: TelegrafModuleAsyncOptions,
|
options: TelegrafModuleAsyncOptions,
|
||||||
): DynamicModule {
|
): DynamicModule {
|
||||||
const providers = [...this.createAsyncProviders(options), TelegrafProvider];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
module: TelegrafModule,
|
module: TelegrafModule,
|
||||||
imports: options.imports || [],
|
imports: [TelegrafCoreModule.forRootAsync(options)],
|
||||||
providers,
|
exports: [TelegrafCoreModule],
|
||||||
exports: providers,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static createAsyncProviders(
|
|
||||||
options: TelegrafModuleAsyncOptions,
|
|
||||||
): Provider[] {
|
|
||||||
if (options.useExisting || options.useFactory) {
|
|
||||||
return [this.createAsyncOptionsProvider(options)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
this.createAsyncOptionsProvider(options),
|
|
||||||
{
|
|
||||||
provide: options.useClass,
|
|
||||||
useClass: options.useClass,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static createAsyncOptionsProvider(
|
|
||||||
options: TelegrafModuleAsyncOptions,
|
|
||||||
): Provider {
|
|
||||||
if (options.useFactory) {
|
|
||||||
return {
|
|
||||||
provide: TELEGRAF_MODULE_OPTIONS,
|
|
||||||
useFactory: options.useFactory,
|
|
||||||
inject: options.inject || [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
provide: TELEGRAF_MODULE_OPTIONS,
|
|
||||||
useFactory: async (optionsFactory: TelegrafOptionsFactory) =>
|
|
||||||
await optionsFactory.createTelegrafOptions(),
|
|
||||||
inject: [options.useExisting || options.useClass],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import { Provider } from '@nestjs/common';
|
|
||||||
import { Telegraf } from 'telegraf';
|
|
||||||
import { TELEGRAF_MODULE_OPTIONS } from './telegraf.constants';
|
|
||||||
import { TelegrafModuleOptions } from './interfaces';
|
|
||||||
|
|
||||||
export const TelegrafProvider = {
|
|
||||||
provide: Telegraf,
|
|
||||||
useFactory: (options: TelegrafModuleOptions) => {
|
|
||||||
const telegraf = new Telegraf(options.token, options.options);
|
|
||||||
telegraf.use(...options.middlewares);
|
|
||||||
return telegraf;
|
|
||||||
},
|
|
||||||
inject: [TELEGRAF_MODULE_OPTIONS],
|
|
||||||
};
|
|
||||||
|
|
||||||
export function createProviders(options: TelegrafModuleOptions): Provider[] {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
provide: TELEGRAF_MODULE_OPTIONS,
|
|
||||||
useValue: options,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
@ -17,5 +17,5 @@ export type ComposerMethodArgs<
|
|||||||
U extends OnlyFunctionPropertyNames<T> = OnlyFunctionPropertyNames<T>
|
U extends OnlyFunctionPropertyNames<T> = OnlyFunctionPropertyNames<T>
|
||||||
> = Filter<Parameters<T[U]>, Middleware<never>>;
|
> = Filter<Parameters<T[U]>, Middleware<never>>;
|
||||||
|
|
||||||
export type UpdateMethods = OnlyFunctionPropertyNames<Composer<never>>;
|
export type ComposerMethods = OnlyFunctionPropertyNames<Composer<never>>;
|
||||||
export type SceneMethods = OnlyFunctionPropertyNames<BaseScene<never>>;
|
export type SceneMethods = OnlyFunctionPropertyNames<BaseScene<never>>;
|
13
lib/utils/create-bot-factory.util.ts
Normal file
13
lib/utils/create-bot-factory.util.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Telegraf } from 'telegraf';
|
||||||
|
import { TelegrafModuleOptions } from '../interfaces';
|
||||||
|
|
||||||
|
export async function createBotFactory(
|
||||||
|
options: TelegrafModuleOptions,
|
||||||
|
): Promise<Telegraf<never>> {
|
||||||
|
const bot = new Telegraf<never>(options.token, options.options);
|
||||||
|
|
||||||
|
bot.use(...(options.middlewares ?? []));
|
||||||
|
await bot.launch(options.launchOptions);
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
29
lib/utils/create-listener-decorator.util.ts
Normal file
29
lib/utils/create-listener-decorator.util.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { SetMetadata } from '@nestjs/common';
|
||||||
|
import { BaseScene as Scene } from 'telegraf';
|
||||||
|
import { ComposerMethodArgs, SceneMethods } from '../types';
|
||||||
|
import { UPDATE_LISTENER_METADATA } from '../telegraf.constants';
|
||||||
|
import { ListenerMetadata } from '../interfaces';
|
||||||
|
|
||||||
|
export function createListenerDecorator<TMethod extends SceneMethods>(
|
||||||
|
method: TMethod,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
...args: ComposerMethodArgs<Scene<never>, TMethod>
|
||||||
|
): MethodDecorator => {
|
||||||
|
return SetMetadata(UPDATE_LISTENER_METADATA, {
|
||||||
|
method,
|
||||||
|
args,
|
||||||
|
} as ListenerMetadata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMissedListenerDecorator<TArgs extends any[]>(
|
||||||
|
method: string,
|
||||||
|
) {
|
||||||
|
return (...args: TArgs): MethodDecorator => {
|
||||||
|
return SetMetadata(UPDATE_LISTENER_METADATA, {
|
||||||
|
method,
|
||||||
|
args,
|
||||||
|
} as ListenerMetadata);
|
||||||
|
};
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { BaseScene as Scene } from 'telegraf';
|
|
||||||
import { ComposerMethodArgs, SceneMethods } from '../telegraf.types';
|
|
||||||
import { UPDATE_LISTENER_METADATA } from '../telegraf.constants';
|
|
||||||
import { ListenerMetadata } from '../interfaces';
|
|
||||||
|
|
||||||
export function createSceneListenerDecorator<Method extends SceneMethods>(
|
|
||||||
method: Method,
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
...args: ComposerMethodArgs<Scene<never>, Method>
|
|
||||||
): MethodDecorator => {
|
|
||||||
return SetMetadata(UPDATE_LISTENER_METADATA, {
|
|
||||||
method,
|
|
||||||
args,
|
|
||||||
} as ListenerMetadata);
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { Composer } from 'telegraf';
|
|
||||||
import { ComposerMethodArgs, UpdateMethods } from '../telegraf.types';
|
|
||||||
import { UPDATE_LISTENER_METADATA } from '../telegraf.constants';
|
|
||||||
import { ListenerMetadata } from '../interfaces';
|
|
||||||
|
|
||||||
export function createUpdateListenerDecorator<Method extends UpdateMethods>(
|
|
||||||
method: Method,
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
...args: ComposerMethodArgs<Composer<never>, Method>
|
|
||||||
): MethodDecorator => {
|
|
||||||
return SetMetadata(UPDATE_LISTENER_METADATA, {
|
|
||||||
method,
|
|
||||||
args,
|
|
||||||
} as ListenerMetadata);
|
|
||||||
};
|
|
||||||
}
|
|
5
lib/utils/get-bot-token.util.ts
Normal file
5
lib/utils/get-bot-token.util.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { DEFAULT_BOT_NAME } from '../telegraf.constants';
|
||||||
|
|
||||||
|
export function getBotToken(name?: string): string {
|
||||||
|
return name && name !== DEFAULT_BOT_NAME ? `${name}Bot` : DEFAULT_BOT_NAME;
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
export * from './create-update-listener-decorator.util';
|
export * from './get-bot-token.util';
|
||||||
export * from './create-scene-listener-decorator.util';
|
export * from './create-bot-factory.util';
|
||||||
|
export * from './create-listener-decorator.util';
|
||||||
|
1679
package-lock.json
generated
1679
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
35
package.json
35
package.json
@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "nestjs-telegraf",
|
"name": "nestjs-telegraf",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
"description": "Telegraf module for NestJS",
|
"description": "Telegraf module for NestJS",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"nest",
|
"nest",
|
||||||
@ -19,10 +21,9 @@
|
|||||||
"url": "https://github.com/bukhalo/nestjs-telegraf/issues"
|
"url": "https://github.com/bukhalo/nestjs-telegraf/issues"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "Aleksandr Bukhalo <a@bukhalo.com>",
|
"author": "Alexander Bukhalo <a@bukhalo.com>",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Aleksandr Bukhalo <a@bukhalo.com> (https://bukhalo.com/)",
|
"Alexander Bukhalo <a@bukhalo.com> (https://bukhalo.com/)"
|
||||||
"Igor Kamyshev <igor@kamyshev.me> (https://kamyshev.me/)"
|
|
||||||
],
|
],
|
||||||
"repository": "git@github.com:bukhalo/nestjs-telegraf.git",
|
"repository": "git@github.com:bukhalo/nestjs-telegraf.git",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -31,27 +32,28 @@
|
|||||||
"prepublish:npm": "npm run build",
|
"prepublish:npm": "npm run build",
|
||||||
"publish:npm": "npm publish --access public",
|
"publish:npm": "npm publish --access public",
|
||||||
"test": "",
|
"test": "",
|
||||||
"sample-app": "ts-node --transpile-only -r tsconfig-paths/register sample/main.ts"
|
"typedoc:build": "typedoc --tsconfig ./tsconfig.typedoc.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"telegraf": "^3.38.0"
|
"telegraf": "3.38.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/common": "7.6.1",
|
"@nestjs/common": "7.6.5",
|
||||||
"@nestjs/core": "7.6.1",
|
"@nestjs/core": "7.6.5",
|
||||||
"@typescript-eslint/eslint-plugin": "4.9.1",
|
"@types/lodash": "4.14.167",
|
||||||
"@typescript-eslint/parser": "4.9.1",
|
"@typescript-eslint/eslint-plugin": "4.11.1",
|
||||||
"eslint": "7.15.0",
|
"@typescript-eslint/parser": "4.11.1",
|
||||||
"eslint-config-prettier": "7.0.0",
|
"eslint": "7.17.0",
|
||||||
|
"eslint-config-prettier": "7.1.0",
|
||||||
"eslint-plugin-import": "2.22.1",
|
"eslint-plugin-import": "2.22.1",
|
||||||
"husky": "4.3.5",
|
"husky": "4.3.6",
|
||||||
"lint-staged": "10.5.3",
|
"lint-staged": "10.5.3",
|
||||||
|
"lodash": "4.17.20",
|
||||||
"prettier": "2.2.1",
|
"prettier": "2.2.1",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"rxjs": "6.6.3",
|
"rxjs": "6.6.3",
|
||||||
"ts-node": "^9.1.1",
|
"typedoc": "0.20.9",
|
||||||
"tsconfig-paths": "^3.9.0",
|
"typescript": "4.1.3"
|
||||||
"typescript": "4.1.2"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@nestjs/common": "^6.7.0 || ^7.0.0",
|
"@nestjs/common": "^6.7.0 || ^7.0.0",
|
||||||
@ -65,8 +67,7 @@
|
|||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.ts": [
|
"*.ts": [
|
||||||
"prettier --write",
|
"prettier --write"
|
||||||
"git add"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
renovate.json
Normal file
10
renovate.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"semanticCommits": true,
|
||||||
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"depTypeList": ["devDependencies"],
|
||||||
|
"automerge": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extends": ["config:base"]
|
||||||
|
}
|
2
sample/01-complete-app/.env.example
Normal file
2
sample/01-complete-app/.env.example
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ECHO_BOT_TOKEN=
|
||||||
|
GREETER_BOT_TOKEN=
|
25
sample/01-complete-app/.eslintrc.js
Normal file
25
sample/01-complete-app/.eslintrc.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module.exports = {
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
project: 'tsconfig.json',
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||||
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'prettier/@typescript-eslint',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
|
],
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
ignorePatterns: ['.eslintrc.js'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/interface-name-prefix': 'off',
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
},
|
||||||
|
};
|
398
sample/01-complete-app/.gitignore
vendored
Normal file
398
sample/01-complete-app/.gitignore
vendored
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.xml
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-debug/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
### VisualStudio template
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
**/Properties/launchSettings.json
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Typescript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# CodeRush
|
||||||
|
.cr/
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
### macOS template
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
=======
|
||||||
|
# Local
|
||||||
|
.env
|
||||||
|
dist
|
14
sample/01-complete-app/jest.json
Normal file
14
sample/01-complete-app/jest.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"ts",
|
||||||
|
"tsx",
|
||||||
|
"js",
|
||||||
|
"json"
|
||||||
|
],
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.tsx?$": "ts-jest"
|
||||||
|
},
|
||||||
|
"testRegex": "/src/.*\\.(test|spec).(ts|tsx|js)$",
|
||||||
|
"collectCoverageFrom" : ["src/**/*.{js,jsx,tsx,ts}", "!**/node_modules/**", "!**/vendor/**"],
|
||||||
|
"coverageReporters": ["json", "lcov"]
|
||||||
|
}
|
11357
sample/01-complete-app/package-lock.json
generated
Normal file
11357
sample/01-complete-app/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
72
sample/01-complete-app/package.json
Normal file
72
sample/01-complete-app/package.json
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name": "nest-typescript-starter",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Nest TypeScript starter repository",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"prebuild": "rimraf dist",
|
||||||
|
"build": "nest build",
|
||||||
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
|
"start": "nest start",
|
||||||
|
"start:dev": "nest start --watch",
|
||||||
|
"start:debug": "nest start --debug --watch",
|
||||||
|
"start:prod": "node dist/main",
|
||||||
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||||
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watch",
|
||||||
|
"test:cov": "jest --coverage",
|
||||||
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
|
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nestjs/common": "7.5.1",
|
||||||
|
"@nestjs/core": "7.5.1",
|
||||||
|
"@nestjs/platform-express": "7.5.1",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
|
"nestjs-telegraf": "*",
|
||||||
|
"reflect-metadata": "0.1.13",
|
||||||
|
"rimraf": "3.0.2",
|
||||||
|
"rxjs": "6.6.3",
|
||||||
|
"telegraf": "^3.38.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nestjs/cli": "7.5.1",
|
||||||
|
"@nestjs/schematics": "7.1.3",
|
||||||
|
"@nestjs/testing": "7.5.1",
|
||||||
|
"@types/express": "4.17.8",
|
||||||
|
"@types/jest": "26.0.15",
|
||||||
|
"@types/node": "14.14.6",
|
||||||
|
"@types/supertest": "2.0.10",
|
||||||
|
"@typescript-eslint/eslint-plugin": "4.6.1",
|
||||||
|
"@typescript-eslint/parser": "4.6.1",
|
||||||
|
"eslint": "7.12.1",
|
||||||
|
"eslint-config-prettier": "6.15.0",
|
||||||
|
"eslint-plugin-prettier": "3.1.4",
|
||||||
|
"jest": "26.6.3",
|
||||||
|
"prettier": "2.1.2",
|
||||||
|
"supertest": "6.0.0",
|
||||||
|
"ts-jest": "26.4.3",
|
||||||
|
"ts-loader": "8.0.8",
|
||||||
|
"ts-node": "9.0.0",
|
||||||
|
"tsconfig-paths": "3.9.0",
|
||||||
|
"typescript": "4.1.3"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"js",
|
||||||
|
"json",
|
||||||
|
"ts"
|
||||||
|
],
|
||||||
|
"rootDir": "src",
|
||||||
|
"testRegex": ".*\\.spec\\.ts$",
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
|
},
|
||||||
|
"collectCoverageFrom": [
|
||||||
|
"**/*.(t|j)s"
|
||||||
|
],
|
||||||
|
"coverageDirectory": "../coverage",
|
||||||
|
"testEnvironment": "node"
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,3 @@
|
|||||||
export const HELLO_SCENE_ID = 'HELLO_SCENE_ID';
|
export const HELLO_SCENE_ID = 'HELLO_SCENE_ID';
|
||||||
|
|
||||||
|
export const GreeterBotName = 'greeter';
|
25
sample/01-complete-app/src/app.module.ts
Normal file
25
sample/01-complete-app/src/app.module.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TelegrafModule } from 'nestjs-telegraf';
|
||||||
|
import { EchoModule } from './echo/echo.module';
|
||||||
|
import { GreeterModule } from './greeter/greeter.module';
|
||||||
|
import { sessionMiddleware } from './middleware/session.middleware';
|
||||||
|
import { GreeterBotName } from './app.constants';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TelegrafModule.forRoot({
|
||||||
|
token: process.env.ECHO_BOT_TOKEN,
|
||||||
|
middlewares: [sessionMiddleware],
|
||||||
|
include: [EchoModule],
|
||||||
|
}),
|
||||||
|
TelegrafModule.forRoot({
|
||||||
|
name: GreeterBotName,
|
||||||
|
token: process.env.GREETER_BOT_TOKEN,
|
||||||
|
middlewares: [sessionMiddleware],
|
||||||
|
include: [GreeterModule],
|
||||||
|
}),
|
||||||
|
EchoModule,
|
||||||
|
GreeterModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class AppModule {}
|
9
sample/01-complete-app/src/echo/echo.module.ts
Normal file
9
sample/01-complete-app/src/echo/echo.module.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { EchoUpdate } from './echo.update';
|
||||||
|
import { EchoService } from './echo.service';
|
||||||
|
import { HelloScene } from './scenes/hello.scene';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [EchoUpdate, EchoService, HelloScene],
|
||||||
|
})
|
||||||
|
export class EchoModule {}
|
43
sample/01-complete-app/src/echo/echo.update.ts
Normal file
43
sample/01-complete-app/src/echo/echo.update.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { Telegraf } from 'telegraf';
|
||||||
|
import { Command, Help, InjectBot, On, Start, Update } from 'nestjs-telegraf';
|
||||||
|
import { EchoService } from './echo.service';
|
||||||
|
import { HELLO_SCENE_ID } from '../app.constants';
|
||||||
|
import { Context } from '../interfaces/context.interface';
|
||||||
|
|
||||||
|
@Update()
|
||||||
|
export class EchoUpdate {
|
||||||
|
constructor(
|
||||||
|
@InjectBot()
|
||||||
|
private readonly bot: Telegraf<Context>,
|
||||||
|
private readonly echoService: EchoService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Start()
|
||||||
|
async onStart(ctx: Context): Promise<void> {
|
||||||
|
const me = await this.bot.telegram.getMe();
|
||||||
|
await ctx.reply(`Hey, I'm ${me.first_name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Help()
|
||||||
|
async onHelp(ctx: Context): Promise<void> {
|
||||||
|
await ctx.reply('Send me any text');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command('scene')
|
||||||
|
async onSceneCommand(ctx: Context): Promise<void> {
|
||||||
|
await ctx.scene.enter(HELLO_SCENE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@On('message')
|
||||||
|
async onMessage(ctx: Context): Promise<void> {
|
||||||
|
console.log('New message received');
|
||||||
|
|
||||||
|
if ('text' in ctx.message) {
|
||||||
|
const messageText = ctx.message.text;
|
||||||
|
const echoText = this.echoService.echo(messageText);
|
||||||
|
await ctx.reply(echoText);
|
||||||
|
} else {
|
||||||
|
await ctx.reply('Only text messages');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import { HELLO_SCENE_ID } from '../app.constants';
|
import { Scene, SceneEnter, SceneLeave, Command } from 'nestjs-telegraf';
|
||||||
import { Context } from '../interfaces/context.interface';
|
import { HELLO_SCENE_ID } from '../../app.constants';
|
||||||
import { Scene, SceneEnter, SceneLeave, Command } from '../../lib';
|
import { Context } from '../../interfaces/context.interface';
|
||||||
|
|
||||||
@Scene(HELLO_SCENE_ID)
|
@Scene(HELLO_SCENE_ID)
|
||||||
export class HelloScene {
|
export class HelloScene {
|
7
sample/01-complete-app/src/greeter/greeter.module.ts
Normal file
7
sample/01-complete-app/src/greeter/greeter.module.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { GreeterUpdate } from './greeter.update';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [GreeterUpdate],
|
||||||
|
})
|
||||||
|
export class GreeterModule {}
|
16
sample/01-complete-app/src/greeter/greeter.update.ts
Normal file
16
sample/01-complete-app/src/greeter/greeter.update.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Hears, Start, Update } from '../../../../lib';
|
||||||
|
import { Context } from '../interfaces/context.interface';
|
||||||
|
|
||||||
|
@Update()
|
||||||
|
export class GreeterUpdate {
|
||||||
|
@Start()
|
||||||
|
async onStart(ctx: Context): Promise<void> {
|
||||||
|
await ctx.reply('Say hello to me');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Hears(['hi', 'hello', 'hey', 'qq'])
|
||||||
|
async onGreetings(ctx: Context): Promise<void> {
|
||||||
|
const { first_name } = ctx.from;
|
||||||
|
await ctx.reply(`Hey ${first_name}`);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'dotenv/config';
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
|
4
sample/01-complete-app/tsconfig.build.json
Normal file
4
sample/01-complete-app/tsconfig.build.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
|
||||||
|
}
|
16
sample/01-complete-app/tsconfig.json
Normal file
16
sample/01-complete-app/tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"declaration": true,
|
||||||
|
"removeComments": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"target": "es2017",
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"baseUrl": "./src",
|
||||||
|
"incremental": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"]
|
||||||
|
}
|
@ -1,17 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { TelegrafModule } from '../lib';
|
|
||||||
import { EchoService } from './echo.service';
|
|
||||||
import { AppUpdate } from './app.update';
|
|
||||||
import { HelloScene } from './scenes/hello.scene';
|
|
||||||
import { sessionMiddleware } from './common/middleware/session.middleware';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [
|
|
||||||
TelegrafModule.forRoot({
|
|
||||||
token: '1467731595:AAHCvH65H9VQYKF9jE-E8c2rXsQBVAYseg8', // Don't steal >:(
|
|
||||||
middlewares: [sessionMiddleware],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
providers: [EchoService, AppUpdate],
|
|
||||||
})
|
|
||||||
export class AppModule {}
|
|
@ -1,66 +0,0 @@
|
|||||||
import { Telegraf } from 'telegraf';
|
|
||||||
import { SceneContextMessageUpdate } from 'telegraf/typings/stage';
|
|
||||||
import {
|
|
||||||
Command,
|
|
||||||
Ctx,
|
|
||||||
Help,
|
|
||||||
InjectBot,
|
|
||||||
MessageText,
|
|
||||||
On,
|
|
||||||
Start,
|
|
||||||
Update,
|
|
||||||
} from '../lib';
|
|
||||||
import { EchoService } from './echo.service';
|
|
||||||
import { HELLO_SCENE_ID } from './app.constants';
|
|
||||||
import { Context } from './interfaces/context.interface';
|
|
||||||
import { UseGuards, UseInterceptors } from '@nestjs/common';
|
|
||||||
import { AdminGuard } from './common/guards/admin.guard';
|
|
||||||
import { ResponseTimeInterceptor } from './common/interceptors/response-time.interceptor';
|
|
||||||
import { ReverseTextPipe } from './common/pipes/reverse-text.pipe';
|
|
||||||
|
|
||||||
@Update()
|
|
||||||
export class AppUpdate {
|
|
||||||
constructor(
|
|
||||||
@InjectBot()
|
|
||||||
private readonly bot: Telegraf<SceneContextMessageUpdate>,
|
|
||||||
private readonly echoService: EchoService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
@Start()
|
|
||||||
async onStart(): Promise<string> {
|
|
||||||
const me = await this.bot.telegram.getMe();
|
|
||||||
return `Hey, I'm ${me.first_name}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Help()
|
|
||||||
@UseInterceptors(ResponseTimeInterceptor)
|
|
||||||
async onHelp(@Ctx() ctx: Context): Promise<void> {
|
|
||||||
await ctx.reply('Send me any text');
|
|
||||||
}
|
|
||||||
|
|
||||||
@UseGuards(AdminGuard)
|
|
||||||
@Command('admin')
|
|
||||||
async onAdminCommand(@Ctx() ctx: Context): Promise<void> {
|
|
||||||
await ctx.reply('Welcome judge');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command('scene')
|
|
||||||
async onSceneCommand(@Ctx() ctx: Context): Promise<void> {
|
|
||||||
await ctx.scene.enter(HELLO_SCENE_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@On('message')
|
|
||||||
async onMessage(
|
|
||||||
@Ctx() ctx: Context,
|
|
||||||
@MessageText(new ReverseTextPipe()) reversedMessage: string,
|
|
||||||
): Promise<void> {
|
|
||||||
console.log('New message received');
|
|
||||||
|
|
||||||
if ('text' in ctx.message) {
|
|
||||||
const echoText = this.echoService.echo(reversedMessage);
|
|
||||||
await ctx.reply(echoText);
|
|
||||||
} else {
|
|
||||||
await ctx.reply('Only text messages');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,12 +7,12 @@
|
|||||||
"noLib": false,
|
"noLib": false,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"target": "es2020",
|
"target": "es2017",
|
||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
"baseUrl": "./",
|
"rootDir": "./lib",
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true
|
||||||
},
|
},
|
||||||
"include": ["lib/**/*", "sample/**/*"],
|
"include": ["lib/**/*"],
|
||||||
"exclude": ["node_modules", "**/*.spec.ts"]
|
"exclude": ["node_modules", "**/*.spec.ts"]
|
||||||
}
|
}
|
||||||
|
10
tsconfig.typedoc.json
Normal file
10
tsconfig.typedoc.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "./"
|
||||||
|
},
|
||||||
|
"typedocOptions": {
|
||||||
|
"entryPoints": ["./index.ts", "./lib"],
|
||||||
|
"out": "docs"
|
||||||
|
}
|
||||||
|
}
|
@ -8,11 +8,10 @@ slug: /bot-injection
|
|||||||
At times you may need to access the native `Telegraf` instance. For example, you may want to connect stage middleware. You can inject the Telegraf by using the `@InjectBot()` decorator as follows:
|
At times you may need to access the native `Telegraf` instance. For example, you may want to connect stage middleware. You can inject the Telegraf by using the `@InjectBot()` decorator as follows:
|
||||||
```typescript
|
```typescript
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectBot } from 'nestjs-telegraf';
|
import { InjectBot, TelegrafProvider, Context } from 'nestjs-telegraf';
|
||||||
import { Telegraf } from 'telegraf';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BotSettingsService {
|
export class BotSettingsService {
|
||||||
constructor(@InjectBot() private bot: Telegraf) {}
|
constructor(@InjectBot() private bot: TelegrafProvider<Context>) {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
31
website/docs/error-handling.md
Normal file
31
website/docs/error-handling.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
id: error-handling
|
||||||
|
title: Error handling
|
||||||
|
sidebar_label: Error handling
|
||||||
|
slug: /error-handling
|
||||||
|
---
|
||||||
|
|
||||||
|
By default, `nestjs-telegraf` catches all errors using the `Logger` built into NestJS.
|
||||||
|
|
||||||
|
Use can disable global errors catch with `disableGlobalCatch`:
|
||||||
|
```typescript
|
||||||
|
TelegrafModule.forRoot({
|
||||||
|
disableGlobalCatch: true,
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
|
||||||
|
After that you can override errors handling with bot instance `catch` function.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectBot, TelegrafProvider, Context } from 'nestjs-telegraf';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BotSettingsService {
|
||||||
|
constructor(@InjectBot() private bot: TelegrafProvider<Context>) {
|
||||||
|
this.bot.catch((err, ctx) => {
|
||||||
|
console.log(`Ooops, encountered an error for ${ctx.updateType}`, err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
27
website/docs/extras/standalone-applications.md
Normal file
27
website/docs/extras/standalone-applications.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
id: standalone-applications
|
||||||
|
title: Standalone applications
|
||||||
|
sidebar_label: Standalone applications
|
||||||
|
slug: standalone-applications
|
||||||
|
---
|
||||||
|
|
||||||
|
If you initialized your application with the [Nest CLI](https://docs.nestjs.com/cli/overview), [Express](https://expressjs.com/) framework will be installed by default along with Nest. Nest and NestJS Telegraf does not require Express for work. So if you don't plan to getting bot updates through webhooks, and you don't need a web server, you can remove Express.
|
||||||
|
|
||||||
|
To do this, change the `bootstrap` function in the `main.ts` file of your project on something like that:
|
||||||
|
```typescript
|
||||||
|
async function bootstrap() {
|
||||||
|
const app = await NestFactory.createApplicationContext(AppModule);
|
||||||
|
}
|
||||||
|
bootstrap();
|
||||||
|
```
|
||||||
|
|
||||||
|
This initializes Nest as a **standalone application** (without any network listeners).
|
||||||
|
|
||||||
|
All that remains is to remove unused dependencies:
|
||||||
|
```bash
|
||||||
|
npm un @nestjs/platform-express @types/express
|
||||||
|
```
|
||||||
|
|
||||||
|
:::info
|
||||||
|
More information about standalone applications located at [Nest documentation](https://docs.nestjs.com/standalone-applications)
|
||||||
|
:::
|
@ -1,28 +1,36 @@
|
|||||||
---
|
---
|
||||||
id: webhooks
|
id: getting-updates
|
||||||
title: Webhooks
|
title: Getting updates
|
||||||
sidebar_label: Webhooks
|
sidebar_label: Getting updates
|
||||||
slug: webhooks
|
slug: getting-updates
|
||||||
---
|
---
|
||||||
|
|
||||||
If you want to configure a telegram bot webhook, you need to get a middleware from `TelegrafProvider` for connect it in your `main.ts` file.
|
## Long polling
|
||||||
|
|
||||||
|
By default, the bot receives updates using long-polling and requires no additional action.
|
||||||
|
|
||||||
|
## Webhooks
|
||||||
|
|
||||||
|
If you want to configure a telegram bot webhook, you need to get a middleware via `getBotToken` helper in your `main.ts` file.
|
||||||
|
|
||||||
To access it, you must use the `app.get()` method, followed by the provider reference:
|
To access it, you must use the `app.get()` method, followed by the provider reference:
|
||||||
```typescript
|
```typescript
|
||||||
import { Telegraf } from 'telegraf';
|
import { getBotToken } from 'nestjs-telegraf';
|
||||||
const telegraf = app.get(Telegraf);
|
|
||||||
|
// ...
|
||||||
|
const bot = app.get(getBotToken());
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can connect middleware:
|
Now you can connect middleware:
|
||||||
```typescript
|
```typescript
|
||||||
app.use(telegraf.webhookCallback('/secret-path'));
|
app.use(bot.webhookCallback('/secret-path'));
|
||||||
```
|
```
|
||||||
|
|
||||||
The last step is to specify launchOptions in `forRoot` method:
|
The last step is to specify launchOptions in `forRoot` method:
|
||||||
```typescript
|
```typescript
|
||||||
TelegrafModule.forRootAsync({
|
TelegrafModule.forRootAsync({
|
||||||
imports: [ConfigModule.forFeature(telegrafModuleConfig)],
|
imports: [ConfigModule],
|
||||||
useFactory: async (configService: ConfigService) => ({
|
useFactory: (configService: ConfigService) => ({
|
||||||
token: configService.get<string>('TELEGRAM_BOT_TOKEN'),
|
token: configService.get<string>('TELEGRAM_BOT_TOKEN'),
|
||||||
launchOptions: {
|
launchOptions: {
|
||||||
webhook: {
|
webhook: {
|
13
website/docs/middlewares.md
Normal file
13
website/docs/middlewares.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
id: middlewares
|
||||||
|
title: Middlewares
|
||||||
|
sidebar_label: Middlewares
|
||||||
|
slug: /middlewares
|
||||||
|
---
|
||||||
|
|
||||||
|
`nestjs-telegraf` has support of the Telegraf middleware packages. To use an existing middleware package, simply import it and add it to the middlewares array:
|
||||||
|
```typescript
|
||||||
|
TelegrafModule.forRoot({
|
||||||
|
middlewares: [session()],
|
||||||
|
}),
|
||||||
|
```
|
74
website/docs/multiple-bots.md
Normal file
74
website/docs/multiple-bots.md
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
id: multiple-bots
|
||||||
|
title: Multiple bots
|
||||||
|
sidebar_label: Multiple bots
|
||||||
|
slug: /multiple-bots
|
||||||
|
---
|
||||||
|
|
||||||
|
In some cases, you may need to run multiple bots at the same time. This can also be achieved with this module. To work with multiple bots, first create the bots. In this case, bot naming becomes mandatory.
|
||||||
|
```typescript
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { TelegrafModule } from 'nestjs-telegraf';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
ConfigModule.forRoot(),
|
||||||
|
TelegrafModule.forRootAsync({
|
||||||
|
imports: [ConfigModule],
|
||||||
|
botName: 'cat',
|
||||||
|
useFactory: (configService: ConfigService) => ({
|
||||||
|
token: configService.get<string>('CAT_BOT_TOKEN'),
|
||||||
|
}),
|
||||||
|
inject: [ConfigService],
|
||||||
|
}),
|
||||||
|
TelegrafModule.forRootAsync({
|
||||||
|
imports: [ConfigModule.forFeature(telegrafModuleConfig)],
|
||||||
|
botName: 'dog',
|
||||||
|
useFactory: async (configService: ConfigService) => ({
|
||||||
|
token: configService.get<string>('DOG_BOT_TOKEN'),
|
||||||
|
}),
|
||||||
|
inject: [ConfigService],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class AppModule {}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
Please note that you shouldn't have multiple bots without a name, or with the same name, otherwise they will get overridden.
|
||||||
|
:::
|
||||||
|
|
||||||
|
You can also inject the `Bot` for a given bot:
|
||||||
|
```typescript
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectBot, Telegraf, Context } from 'nestjs-telegraf';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class EchoService {
|
||||||
|
constructor(@InjectBot('cat') private catBot: Telegraf<Context>) {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
To inject a given `Bot` to a custom provider (for example, factory provider), use the `getBotToken()` function passing the name of the bot as an argument.
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
provide: CatsService,
|
||||||
|
useFactory: (catBot: Telegraf<Context>) => {
|
||||||
|
return new CatsService(catBot);
|
||||||
|
},
|
||||||
|
inject: [getBotToken('cat')],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Another useful feature of the `nestjs-telegraf` module is the ability to choose which modules should handle updates for each launched bot. By default, module searches for handlers throughout the whole app. To limit this scan to only a subset of modules, use the include property.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
TelegrafModule.forRootAsync({
|
||||||
|
imports: [ConfigModule],
|
||||||
|
botName: 'cat',
|
||||||
|
useFactory: (configService: ConfigService) => ({
|
||||||
|
token: configService.get<string>('CAT_BOT_TOKEN'),
|
||||||
|
include: [CatsModule],
|
||||||
|
}),
|
||||||
|
inject: [ConfigService],
|
||||||
|
}),
|
||||||
|
```
|
23947
website/package-lock.json
generated
23947
website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,12 +11,12 @@
|
|||||||
"serve": "docusaurus serve"
|
"serve": "docusaurus serve"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "2.0.0-alpha.63",
|
"@docusaurus/core": "2.0.0-alpha.70",
|
||||||
"@docusaurus/preset-classic": "2.0.0-alpha.63",
|
"@docusaurus/preset-classic": "2.0.0-alpha.70",
|
||||||
"@mdx-js/react": "^1.5.8",
|
"@mdx-js/react": "1.6.22",
|
||||||
"clsx": "^1.1.1",
|
"clsx": "1.1.1",
|
||||||
"react": "^16.8.4",
|
"react": "17.0.1",
|
||||||
"react-dom": "^16.8.4"
|
"react-dom": "17.0.1"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
@ -31,11 +31,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "^2.0.0-alpha.51",
|
"@docusaurus/module-type-aliases": "2.0.0-alpha.f37987f32",
|
||||||
"@tsconfig/docusaurus": "^1.0.2",
|
"@tsconfig/docusaurus": "1.0.2",
|
||||||
"@types/react": "^16.9.49",
|
"@types/react": "17.0.0",
|
||||||
"@types/react-helmet": "^6.1.0",
|
"@types/react-helmet": "6.1.0",
|
||||||
"@types/react-router-dom": "^5.1.5",
|
"@types/react-router-dom": "5.1.7",
|
||||||
"typescript": "^4.0.2"
|
"typescript": "4.1.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,15 @@ module.exports = {
|
|||||||
docs: {
|
docs: {
|
||||||
'Getting Started': [
|
'Getting Started': [
|
||||||
'installation',
|
'installation',
|
||||||
|
'getting-updates',
|
||||||
'telegraf-methods',
|
'telegraf-methods',
|
||||||
'bot-injection',
|
'bot-injection',
|
||||||
'async-configuration',
|
'async-configuration',
|
||||||
'webhooks',
|
'multiple-bots',
|
||||||
|
'middlewares',
|
||||||
|
'error-handling',
|
||||||
],
|
],
|
||||||
|
Extras: ['extras/standalone-applications'],
|
||||||
'API Reference': ['api-reference/decorators'],
|
'API Reference': ['api-reference/decorators'],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user