docs: support docs versioning, new update hook decorators docs added

This commit is contained in:
Aleksandr Bukhalo 2020-09-10 11:23:04 +03:00
parent 7043f247da
commit df2b6a5ab3
20 changed files with 711 additions and 20 deletions

View File

@ -1,10 +1,16 @@
import { SetMetadata } from '@nestjs/common';
import { DECORATORS } from '../telegraf.constants';
import * as tt from 'telegraf/typings/telegram-types';
export type TelegrafInlineQueryTriggers = string | string[] | RegExp | RegExp[];
export interface InlineQueryOptions {
triggers: TelegrafInlineQueryTriggers;
triggers?: TelegrafInlineQueryTriggers;
updateType:
| tt.UpdateType
| tt.UpdateType[]
| tt.MessageSubTypes
| tt.MessageSubTypes[];
}
/**
@ -13,9 +19,12 @@ export interface InlineQueryOptions {
* @see https://telegraf.js.org/#/?id=inlinequery
*/
export const InlineQuery = (
triggers: TelegrafInlineQueryTriggers,
triggers?: TelegrafInlineQueryTriggers,
): MethodDecorator => {
return SetMetadata(DECORATORS.INLINE_QUERY, { triggers });
return SetMetadata(DECORATORS.INLINE_QUERY, {
triggers,
updateType: 'inline_query',
});
};
/**

View File

@ -14,7 +14,7 @@ export interface UpdateHookOptions {
* New incoming message of any kind text, photo, sticker, etc.
* @constructor
*/
export const OnMessage = (): MethodDecorator => {
export const Message = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'message',
});
@ -24,7 +24,7 @@ export const OnMessage = (): MethodDecorator => {
* New version of a message that is known to the bot and was edited
* @constructor
*/
export const OnEditedMessage = (): MethodDecorator => {
export const EditedMessage = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'edited_message',
});
@ -34,7 +34,7 @@ export const OnEditedMessage = (): MethodDecorator => {
* New incoming channel post of any kind text, photo, sticker, etc.
* @constructor
*/
export const OnChannelPost = (): MethodDecorator => {
export const ChannelPost = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'channel_post',
});
@ -44,7 +44,7 @@ export const OnChannelPost = (): MethodDecorator => {
* New version of a channel post that is known to the bot and was edited
* @constructor
*/
export const OnEditedChannelPost = (): MethodDecorator => {
export const EditedChannelPost = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'edited_channel_post',
});
@ -52,19 +52,20 @@ export const OnEditedChannelPost = (): MethodDecorator => {
/**
* New incoming inline query
* See this decorator in inline-query.decorator.ts
* @constructor
*/
export const OnInlineQuery = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'inline_query',
});
};
// export const InlineQuery = (): MethodDecorator => {
// return SetMetadata(DECORATORS.UPDATE_HOOK, {
// updateType: 'inline_query',
// });
// };
/**
* The result of an inline query that was chosen by a user and sent to their chat partner.
* @constructor
*/
export const OnChosenInlineResult = (): MethodDecorator => {
export const ChosenInlineResult = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'chosen_inline_result',
});
@ -74,7 +75,7 @@ export const OnChosenInlineResult = (): MethodDecorator => {
* New incoming callback query
* @constructor
*/
export const OnCallbackQuery = (): MethodDecorator => {
export const CallbackQuery = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'callback_query',
});
@ -84,7 +85,7 @@ export const OnCallbackQuery = (): MethodDecorator => {
* New incoming shipping query. Only for invoices with flexible price
* @constructor
*/
export const OnShippingQuery = (): MethodDecorator => {
export const ShippingQuery = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'shipping_query',
});
@ -94,7 +95,7 @@ export const OnShippingQuery = (): MethodDecorator => {
* New incoming pre-checkout query. Contains full information about checkout
* @constructor
*/
export const OnPreCheckoutQuery = (): MethodDecorator => {
export const PreCheckoutQuery = (): MethodDecorator => {
return SetMetadata(DECORATORS.UPDATE_HOOK, {
updateType: 'pre_checkout_query',
});

View File

@ -228,8 +228,15 @@ export class TelegrafExplorer implements OnModuleInit {
key: string,
metadata: InlineQueryOptions,
) {
// @ts-ignore
this.telegraf.inlineQuery(metadata.triggers, instance[key].bind(instance));
if (metadata.triggers) {
// @ts-ignore
this.telegraf.inlineQuery(
metadata.triggers,
instance[key].bind(instance),
);
} else {
this.telegraf.on(metadata.updateType, instance[key].bind(instance));
}
}
handleTelegrafGameQuery(instance: object, key: string) {

View File

@ -0,0 +1,185 @@
---
id: decorators
title: Decorators
sidebar_label: Decorators
slug: /api-reference/decorators
---
:::caution
The described functionality is under development, the functionality has not been tested and can be changed at any time!
:::
### Update
`@Update` class decorator, it's like NestJS [`@Controller`](https://docs.nestjs.com/controllers) decorator, but for [Telegram Bot API updates](https://core.telegram.org/bots/api#getting-updates).
```typescript {3}
import { Update, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
...
}
```
### Message
Use `@Message` method decorator for handling new incoming message of any kind — text, photo, sticker, etc.
```typescript {5}
import { Update, Message, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@Message()
message(ctx: Context) {
ctx.reply(`You say: ${ctx.message.text}`);
}
}
```
### EditedMessage
Use `@EditedMessage` method decorator for handling new version of a message that is known to the bot and was edited.
```typescript {5}
import { Update, EditedMessage, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@EditedMessage()
editedMessage(ctx: Context) {
...
}
}
```
### ChannelPost
Use `@ChannelPost` method decorator for handling new incoming channel post of any kind — text, photo, sticker, etc.
```typescript {5}
import { Update, ChannelPost, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@ChannelPost()
channelPost(ctx: Context) {
...
}
}
```
### EditedChannelPost
Use `@EditedChannelPost` method decorator for handling new version of a channel post that is known to the bot and was edited.
```typescript {5}
import { Update, EditedChannelPost, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@EditedChannelPost()
editedChannelPost(ctx: Context) {
...
}
}
```
### InlineQuery
Use `@InlineQuery` method decorator for handling new incoming inline query.
```typescript {5}
import { Update, InlineQuery, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@InlineQuery()
inlineQuery(ctx: Context) {
...
}
}
```
The `@InlineQuery` decorator can take a `triggers` option to handle inline query with specific value.
```typescript {6}
import { Update, InlineQuery, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@InlineQuery({
triggers: 'trigger' // string/string[]/RegEx/RegEx[]
})
inlineQuery(ctx: Context) {
...
}
}
```
### ChosenInlineResult
Use `@ChosenInlineResult` method decorator for handling result of an inline query that was chosen by a user and sent to their chat partner.
```typescript {5}
import { Update, ChosenInlineResult, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@ChosenInlineResult()
chosenInlineResult(ctx: Context) {
...
}
}
```
### CallbackQuery
Use `@CallbackQuery` method decorator for handling new incoming callback query.
```typescript {5}
import { Update, CallbackQuery, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@CallbackQuery()
callbackQuery(ctx: Context) {
...
}
}
```
### ShippingQuery
Use `@ShippingQuery` method decorator for handling new incoming shipping query. Only for invoices with flexible price.
```typescript {5}
import { Update, ShippingQuery, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@ShippingQuery()
shippingQuery(ctx: Context) {
...
}
}
```
### PreCheckoutQuery
Use `@PreCheckoutQuery` method decorator for handling new incoming pre-checkout query. Contains full information about checkout.
```typescript {5}
import { Update, PreCheckoutQuery, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
@PreCheckoutQuery()
preCheckoutQuery(ctx: Context) {
...
}
}
```

View File

@ -15,6 +15,10 @@ module.exports = {
// src: 'img/logo.svg',
// },
items: [
{
type: 'docsVersionDropdown',
position: 'left',
},
{
to: 'docs/',
activeBasePath: 'docs',
@ -88,6 +92,8 @@ module.exports = {
// Please change this to your repo.
editUrl:
'https://github.com/bukhalo/nestjs-telegraf/edit/master/website/',
showLastUpdateAuthor: true,
showLastUpdateTime: true,
},
// blog: {
// showReadingTime: true,

View File

@ -1,5 +1,12 @@
module.exports = {
someSidebar: {
'Getting Started': ['installation', 'telegraf-methods', 'bot-injection', 'async-configuration', 'webhooks'],
docs: {
'Getting Started': [
'installation',
'telegraf-methods',
'bot-injection',
'async-configuration',
'webhooks',
],
'API Reference': ['api-reference/decorators'],
},
};

View File

@ -0,0 +1,60 @@
---
id: async-configuration
title: Async configuration
sidebar_label: Async configuration
slug: /async-configuration
---
When you need to pass module options asynchronously instead of statically, use the forRootAsync() method. As with most dynamic modules, Nest provides several techniques to deal with async configuration.
One technique is to use a factory function:
```typescript
TelegrafModule.forRootAsync({
useFactory: () => ({
token: 'TELEGRAM_BOT_TOKEN',
}),
});
```
Like other [factory providers](https://docs.nestjs.com/fundamentals/custom-providers#factory-providers-usefactory), our factory function can be async and can inject dependencies through inject.
```typescript
TelegrafModule.forRootAsync({
imports: [ConfigModule.forFeature(telegrafModuleConfig)],
useFactory: async (configService: ConfigService) => ({
token: configService.get<string>('TELEGRAM_BOT_TOKEN'),
}),
inject: [ConfigService],
});
```
Alternatively, you can configure the TelegrafModule using a class instead of a factory, as shown below:
```typescript
TelegrafModule.forRootAsync({
useClass: TelegrafConfigService,
});
```
The construction above instantiates `TelegrafConfigService` inside `TelegrafModule`, using it to create the required options object. Note that in this example, the `TelegrafConfigService` has to implement the `TelegrafOptionsFactory` interface, as shown below. The `TelegrafModule` will call the `createTelegrafOptions()` method on the instantiated object of the supplied class.
```typescript
@Injectable()
class TelegrafConfigService implements TelegrafOptionsFactory {
createTelegrafOptions(): TelegrafModuleOptions {
return {
token: 'TELEGRAM_BOT_TOKEN',
};
}
}
```
If you want to reuse an existing options provider instead of creating a private copy inside the `TelegrafModule`, use the `useExisting` syntax.
```typescript
TelegrafModule.forRootAsync({
imports: [ConfigModule.forFeature(telegrafModuleConfig)],
useExisting: ConfigService,
});
```

View File

@ -0,0 +1,17 @@
---
id: bot-injection
title: Bot injection
sidebar_label: Bot injection
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:
```typescript
import { Injectable } from '@nestjs/common';
import { InjectBot, TelegrafProvider } from 'nestjs-telegraf';
@Injectable()
export class BotSettingsService {
constructor(@InjectBot() private bot: TelegrafProvider) {}
}
```

View File

@ -0,0 +1,30 @@
---
id: installation
title: Installation
sidebar_label: Installation
slug: /
---
```bash
$ npm i nestjs-telegraf
```
Once the installation process is complete, we can import the TelegrafModule into the root AppModule.
```typescript
/* app.module.ts */
import { Module } from '@nestjs/common';
import { TelegrafModule } from 'nestjs-telegraf';
@Module({
imports: [
TelegrafModule.forRoot({
token: 'TELEGRAM_BOT_TOKEN',
})
],
})
export class AppModule {}
```
The `forRoot()` method accepts the same configuration object as Telegraf class constructor from the Telegraf package, as described [here](https://telegraf.js.org/#/?id=constructor).

View File

@ -0,0 +1,46 @@
---
id: telegraf-methods
title: Telegraf methods
sidebar_label: Telegraf methods
slug: /telegraf-methods
---
Each Telegraf instance method described [here](https://telegraf.js.org/#/?id=telegraf) has own decorator in `nestjs-telegraf` package. The name of the decorator corresponds to the name of the Telegraf method. For example [`@TelegrafHears`](https://telegraf.js.org/#/?id=hears), [`@TelegrafOn`](https://telegraf.js.org/#/?id=on), [`@TelegrafAction`](https://telegraf.js.org/#/?id=action) and so on.
Now let's try to repeat the example from the Telegraf [documentation page](https://telegraf.js.org/#/?id=example).
```typescript
/* app.service.ts */
import { Injectable } from '@nestjs/common';
import {
TelegrafStart,
TelegrafHelp,
TelegrafOn,
TelegrafHears,
Context,
} from 'nestjs-telegraf';
@Injectable()
export class AppService {
@TelegrafStart()
start(ctx: Context) {
ctx.reply('Welcome');
}
@TelegrafHelp()
help(ctx: Context) {
ctx.reply('Send me a sticker');
}
@TelegrafOn('sticker')
on(ctx: Context) {
ctx.reply('👍');
}
@TelegrafHears('hi')
hears(ctx: Context) {
ctx.reply('Hey there');
}
}
```

View File

@ -0,0 +1,35 @@
---
id: webhooks
title: Webhooks
sidebar_label: Webhooks
slug: webhooks
---
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.
To access it, you must use the `app.get()` method, followed by the provider reference:
```typescript
const telegrafProvider = app.get('TelegrafProvider');
```
Now you can connect middleware:
```typescript
app.use(telegrafProvider.webhookCallback('/secret-path'));
```
The last step is to specify launchOptions in `forRoot` method:
```typescript
TelegrafModule.forRootAsync({
imports: [ConfigModule.forFeature(telegrafModuleConfig)],
useFactory: async (configService: ConfigService) => ({
token: configService.get<string>('TELEGRAM_BOT_TOKEN'),
launchOptions: {
webhook: {
domain: 'domain.tld',
hookPath: '/secret-path',
}
}
}),
inject: [ConfigService],
});
```

View File

@ -0,0 +1,23 @@
---
id: decorators
title: Decorators
sidebar_label: Decorators
slug: /api-reference/decorators
---
:::caution
The described functionality is under development, the functionality has not been tested and can be changed at any time!
:::
### Update
`@Update` class decorator, it's like NestJS [`@Controller`](https://docs.nestjs.com/controllers) decorator, but for [Telegram Bot API updates](https://core.telegram.org/bots/api#getting-updates). Reserved for future use.
```typescript {3}
import { Update, Context } from 'nestjs-telegraf';
@Update()
export class SomeBotService {
...
}
```

View File

@ -0,0 +1,60 @@
---
id: async-configuration
title: Async configuration
sidebar_label: Async configuration
slug: /async-configuration
---
When you need to pass module options asynchronously instead of statically, use the forRootAsync() method. As with most dynamic modules, Nest provides several techniques to deal with async configuration.
One technique is to use a factory function:
```typescript
TelegrafModule.forRootAsync({
useFactory: () => ({
token: 'TELEGRAM_BOT_TOKEN',
}),
});
```
Like other [factory providers](https://docs.nestjs.com/fundamentals/custom-providers#factory-providers-usefactory), our factory function can be async and can inject dependencies through inject.
```typescript
TelegrafModule.forRootAsync({
imports: [ConfigModule.forFeature(telegrafModuleConfig)],
useFactory: async (configService: ConfigService) => ({
token: configService.get<string>('TELEGRAM_BOT_TOKEN'),
}),
inject: [ConfigService],
});
```
Alternatively, you can configure the TelegrafModule using a class instead of a factory, as shown below:
```typescript
TelegrafModule.forRootAsync({
useClass: TelegrafConfigService,
});
```
The construction above instantiates `TelegrafConfigService` inside `TelegrafModule`, using it to create the required options object. Note that in this example, the `TelegrafConfigService` has to implement the `TelegrafOptionsFactory` interface, as shown below. The `TelegrafModule` will call the `createTelegrafOptions()` method on the instantiated object of the supplied class.
```typescript
@Injectable()
class TelegrafConfigService implements TelegrafOptionsFactory {
createTelegrafOptions(): TelegrafModuleOptions {
return {
token: 'TELEGRAM_BOT_TOKEN',
};
}
}
```
If you want to reuse an existing options provider instead of creating a private copy inside the `TelegrafModule`, use the `useExisting` syntax.
```typescript
TelegrafModule.forRootAsync({
imports: [ConfigModule.forFeature(telegrafModuleConfig)],
useExisting: ConfigService,
});
```

View File

@ -0,0 +1,17 @@
---
id: bot-injection
title: Bot injection
sidebar_label: Bot injection
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:
```typescript
import { Injectable } from '@nestjs/common';
import { InjectBot, TelegrafProvider } from 'nestjs-telegraf';
@Injectable()
export class BotSettingsService {
constructor(@InjectBot() private bot: TelegrafProvider) {}
}
```

View File

@ -0,0 +1,30 @@
---
id: installation
title: Installation
sidebar_label: Installation
slug: /
---
```bash
$ npm i nestjs-telegraf
```
Once the installation process is complete, we can import the TelegrafModule into the root AppModule.
```typescript
/* app.module.ts */
import { Module } from '@nestjs/common';
import { TelegrafModule } from 'nestjs-telegraf';
@Module({
imports: [
TelegrafModule.forRoot({
token: 'TELEGRAM_BOT_TOKEN',
})
],
})
export class AppModule {}
```
The `forRoot()` method accepts the same configuration object as Telegraf class constructor from the Telegraf package, as described [here](https://telegraf.js.org/#/?id=constructor).

View File

@ -0,0 +1,46 @@
---
id: telegraf-methods
title: Telegraf methods
sidebar_label: Telegraf methods
slug: /telegraf-methods
---
Each Telegraf instance method described [here](https://telegraf.js.org/#/?id=telegraf) has own decorator in `nestjs-telegraf` package. The name of the decorator corresponds to the name of the Telegraf method. For example [`@Hears`](https://telegraf.js.org/#/?id=hears), [`@On`](https://telegraf.js.org/#/?id=on), [`@Action`](https://telegraf.js.org/#/?id=action) and so on.
Now let's try to repeat the example from the Telegraf [documentation page](https://telegraf.js.org/#/?id=example).
```typescript
/* app.service.ts */
import { Injectable } from '@nestjs/common';
import {
Start,
Help,
On,
Hears,
Context,
} from 'nestjs-telegraf';
@Injectable()
export class AppService {
@Start()
start(ctx: Context) {
ctx.reply('Welcome');
}
@Help()
help(ctx: Context) {
ctx.reply('Send me a sticker');
}
@On('sticker')
on(ctx: Context) {
ctx.reply('👍');
}
@Hears('hi')
hears(ctx: Context) {
ctx.reply('Hey there');
}
}
```

View File

@ -0,0 +1,35 @@
---
id: webhooks
title: Webhooks
sidebar_label: Webhooks
slug: webhooks
---
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.
To access it, you must use the `app.get()` method, followed by the provider reference:
```typescript
const telegrafProvider = app.get('TelegrafProvider');
```
Now you can connect middleware:
```typescript
app.use(telegrafProvider.webhookCallback('/secret-path'));
```
The last step is to specify launchOptions in `forRoot` method:
```typescript
TelegrafModule.forRootAsync({
imports: [ConfigModule.forFeature(telegrafModuleConfig)],
useFactory: async (configService: ConfigService) => ({
token: configService.get<string>('TELEGRAM_BOT_TOKEN'),
launchOptions: {
webhook: {
domain: 'domain.tld',
hookPath: '/secret-path',
}
}
}),
inject: [ConfigService],
});
```

View File

@ -0,0 +1,31 @@
{
"version-1.2.1/docs": [
{
"collapsed": true,
"type": "category",
"label": "Getting Started",
"items": [
{
"type": "doc",
"id": "version-1.2.1/installation"
},
{
"type": "doc",
"id": "version-1.2.1/telegraf-methods"
},
{
"type": "doc",
"id": "version-1.2.1/bot-injection"
},
{
"type": "doc",
"id": "version-1.2.1/async-configuration"
},
{
"type": "doc",
"id": "version-1.2.1/webhooks"
}
]
}
]
}

View File

@ -0,0 +1,42 @@
{
"version-1.3.0/docs": [
{
"collapsed": false,
"type": "category",
"label": "Getting Started",
"items": [
{
"type": "doc",
"id": "version-1.3.0/installation"
},
{
"type": "doc",
"id": "version-1.3.0/telegraf-methods"
},
{
"type": "doc",
"id": "version-1.3.0/bot-injection"
},
{
"type": "doc",
"id": "version-1.3.0/async-configuration"
},
{
"type": "doc",
"id": "version-1.3.0/webhooks"
}
]
},
{
"collapsed": true,
"type": "category",
"label": "API Reference",
"items": [
{
"type": "doc",
"id": "version-1.3.0/api-reference/decorators"
}
]
}
]
}

4
website/versions.json Normal file
View File

@ -0,0 +1,4 @@
[
"1.3.0",
"1.2.1"
]