mirror of
https://github.com/Maks1mS/nestjs-telegraf.git
synced 2024-12-23 22:52:59 +03:00
initial commit
This commit is contained in:
parent
1bb274e8e2
commit
2d23eba148
26
.eslintrc.js
26
.eslintrc.js
@ -1,26 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
|
||||||
project: 'tsconfig.json',
|
|
||||||
sourceType: 'module',
|
|
||||||
},
|
|
||||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
|
||||||
extends: [
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'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/no-explicit-any': 'off',
|
|
||||||
'@typescript-eslint/no-use-before-define': 'off',
|
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
||||||
'@typescript-eslint/ban-types': 'off',
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,14 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { SceneOptions } from 'telegraf/typings/scenes/base';
|
|
||||||
import { SceneMetadata } from '../../interfaces';
|
|
||||||
import { SCENE_METADATA } from '../../telegraf.constants';
|
|
||||||
|
|
||||||
export const Scene = (
|
|
||||||
sceneId: string,
|
|
||||||
options?: SceneOptions<any>,
|
|
||||||
): ClassDecorator =>
|
|
||||||
SetMetadata<string, SceneMetadata>(SCENE_METADATA, {
|
|
||||||
sceneId,
|
|
||||||
type: 'base',
|
|
||||||
options,
|
|
||||||
});
|
|
@ -1,14 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { SceneOptions } from 'telegraf/typings/scenes/base';
|
|
||||||
import { SceneMetadata } from '../../interfaces';
|
|
||||||
import { SCENE_METADATA } from '../../telegraf.constants';
|
|
||||||
|
|
||||||
export const Wizard = (
|
|
||||||
sceneId: string,
|
|
||||||
options?: SceneOptions<any>,
|
|
||||||
): ClassDecorator =>
|
|
||||||
SetMetadata<string, SceneMetadata>(SCENE_METADATA, {
|
|
||||||
sceneId,
|
|
||||||
type: 'wizard',
|
|
||||||
options,
|
|
||||||
});
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling callback_data actions with regular expressions.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=action
|
|
||||||
*/
|
|
||||||
export const Action = createListenerDecorator('action');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cashtag handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=cashtag
|
|
||||||
*/
|
|
||||||
export const Cashtag = createListenerDecorator('cashtag');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling messages with email entity.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=telegraf-email
|
|
||||||
*/
|
|
||||||
export const Email = createListenerDecorator('email');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hashtag handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=hashtag
|
|
||||||
*/
|
|
||||||
export const Hashtag = createListenerDecorator('hashtag');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for /help command.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=help
|
|
||||||
*/
|
|
||||||
export const Help = createListenerDecorator('help');
|
|
@ -1,18 +0,0 @@
|
|||||||
export * from './on.decorator';
|
|
||||||
export * from './use.decorator';
|
|
||||||
export * from './action.decorator';
|
|
||||||
export * from './cashtag.decorator';
|
|
||||||
export * from './command.decorator';
|
|
||||||
export * from './game-query.decorator';
|
|
||||||
export * from './hashtag.decorator';
|
|
||||||
export * from './hears.decorator';
|
|
||||||
export * from './help.decorator';
|
|
||||||
export * from './inline-query.decorator';
|
|
||||||
export * from './mention.decorator';
|
|
||||||
export * from './phone.decorator';
|
|
||||||
export * from './settings.decorator';
|
|
||||||
export * from './start.decorator';
|
|
||||||
export * from './email.decorator';
|
|
||||||
export * from './url.decorator';
|
|
||||||
export * from './text-link.decorator';
|
|
||||||
export * from './text-mention.decorator';
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mention handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=mention
|
|
||||||
*/
|
|
||||||
export const Mention = createListenerDecorator('mention');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Phone number handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=phone
|
|
||||||
*/
|
|
||||||
export const Phone = createListenerDecorator('phone');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for /settings command.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=settings
|
|
||||||
*/
|
|
||||||
export const Settings = createListenerDecorator('settings');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for /start command.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=start
|
|
||||||
*/
|
|
||||||
export const Start = createListenerDecorator('start');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling messages with text_link entity.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=telegraf-textlink
|
|
||||||
*/
|
|
||||||
export const TextLink = createListenerDecorator('textLink');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling messages with text_mention entity.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=telegraf-textlink
|
|
||||||
*/
|
|
||||||
export const TextMention = createListenerDecorator('textMention');
|
|
@ -1,8 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling messages with url entity.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=telegraf-url
|
|
||||||
*/
|
|
||||||
export const Url = createListenerDecorator('url');
|
|
@ -1,3 +0,0 @@
|
|||||||
export * from './scene-enter.decorator';
|
|
||||||
export * from './scene-leave.decorator';
|
|
||||||
export * from './wizard-step.decorator';
|
|
@ -1,5 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
import { Scenes } from 'telegraf';
|
|
||||||
|
|
||||||
export const SceneEnter =
|
|
||||||
createListenerDecorator<Scenes.BaseScene<never>>('enter');
|
|
@ -1,5 +0,0 @@
|
|||||||
import { createListenerDecorator } from '../../utils';
|
|
||||||
import { Scenes } from 'telegraf';
|
|
||||||
|
|
||||||
export const SceneLeave =
|
|
||||||
createListenerDecorator<Scenes.BaseScene<never>>('leave');
|
|
@ -1,6 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { WizardStepMetadata } from '../../interfaces';
|
|
||||||
import { WIZARD_STEP_METADATA } from '../../telegraf.constants';
|
|
||||||
|
|
||||||
export const WizardStep = (step: number) =>
|
|
||||||
SetMetadata<string, WizardStepMetadata>(WIZARD_STEP_METADATA, { step });
|
|
@ -1,11 +0,0 @@
|
|||||||
import { SceneOptions } from 'telegraf/typings/scenes/base';
|
|
||||||
|
|
||||||
export interface SceneMetadata {
|
|
||||||
sceneId: string;
|
|
||||||
type: 'base' | 'wizard';
|
|
||||||
options?: SceneOptions<any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WizardStepMetadata {
|
|
||||||
step: number;
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { Reflector } from '@nestjs/core';
|
|
||||||
import {
|
|
||||||
SCENE_METADATA,
|
|
||||||
LISTENERS_METADATA,
|
|
||||||
UPDATE_METADATA,
|
|
||||||
WIZARD_STEP_METADATA,
|
|
||||||
} from '../telegraf.constants';
|
|
||||||
import {
|
|
||||||
ListenerMetadata,
|
|
||||||
SceneMetadata,
|
|
||||||
WizardStepMetadata,
|
|
||||||
} from '../interfaces';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MetadataAccessorService {
|
|
||||||
constructor(private readonly reflector: Reflector) {}
|
|
||||||
|
|
||||||
isUpdate(target: Function): boolean {
|
|
||||||
if (!target) return false;
|
|
||||||
return !!this.reflector.get(UPDATE_METADATA, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isScene(target: Function): boolean {
|
|
||||||
if (!target) return false;
|
|
||||||
return !!this.reflector.get(SCENE_METADATA, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getListenerMetadata(target: Function): ListenerMetadata[] | undefined {
|
|
||||||
return this.reflector.get(LISTENERS_METADATA, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getSceneMetadata(target: Function): SceneMetadata | undefined {
|
|
||||||
return this.reflector.get(SCENE_METADATA, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getWizardStepMetadata(target: Function): WizardStepMetadata | undefined {
|
|
||||||
return this.reflector.get(WIZARD_STEP_METADATA, target);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { Provider } from '@nestjs/common';
|
|
||||||
import { Scenes } from 'telegraf';
|
|
||||||
import { TELEGRAF_STAGE } from './telegraf.constants';
|
|
||||||
|
|
||||||
export const telegrafStageProvider: Provider = {
|
|
||||||
provide: TELEGRAF_STAGE,
|
|
||||||
useClass: Scenes.Stage,
|
|
||||||
};
|
|
@ -1,16 +0,0 @@
|
|||||||
import { Telegraf } from 'telegraf';
|
|
||||||
import { TelegrafModuleOptions } from '../interfaces';
|
|
||||||
|
|
||||||
export async function createBotFactory(
|
|
||||||
options: TelegrafModuleOptions,
|
|
||||||
): Promise<Telegraf<any>> {
|
|
||||||
const bot = new Telegraf<any>(options.token, options.options);
|
|
||||||
|
|
||||||
bot.use(...(options.middlewares ?? []));
|
|
||||||
|
|
||||||
if (options.launchOptions !== false) {
|
|
||||||
await bot.launch(options.launchOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return bot;
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
ECHO_BOT_TOKEN=
|
|
||||||
GREETER_BOT_TOKEN=
|
|
@ -1,24 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
|
||||||
project: 'tsconfig.json',
|
|
||||||
sourceType: 'module',
|
|
||||||
},
|
|
||||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
|
||||||
extends: [
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'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
398
sample/01-complete-app/.gitignore
vendored
@ -1,398 +0,0 @@
|
|||||||
# 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
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"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"]
|
|
||||||
}
|
|
15862
sample/01-complete-app/package-lock.json
generated
15862
sample/01-complete-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,71 +0,0 @@
|
|||||||
{
|
|
||||||
"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": "8.0.9",
|
|
||||||
"@nestjs/core": "8.0.9",
|
|
||||||
"@nestjs/platform-express": "8.0.9",
|
|
||||||
"dotenv": "10.0.0",
|
|
||||||
"nestjs-telegraf": "2.4.0",
|
|
||||||
"reflect-metadata": "0.1.13",
|
|
||||||
"rimraf": "3.0.2",
|
|
||||||
"telegraf": "4.4.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@nestjs/cli": "8.2.8",
|
|
||||||
"@nestjs/schematics": "8.0.5",
|
|
||||||
"@nestjs/testing": "8.0.9",
|
|
||||||
"@types/express": "4.17.13",
|
|
||||||
"@types/jest": "27.4.0",
|
|
||||||
"@types/node": "16.11.22",
|
|
||||||
"@types/supertest": "2.0.11",
|
|
||||||
"@typescript-eslint/eslint-plugin": "5.11.0",
|
|
||||||
"@typescript-eslint/parser": "5.11.0",
|
|
||||||
"eslint": "8.8.0",
|
|
||||||
"eslint-config-prettier": "8.3.0",
|
|
||||||
"eslint-plugin-prettier": "4.0.0",
|
|
||||||
"jest": "27.5.1",
|
|
||||||
"prettier": "2.5.1",
|
|
||||||
"supertest": "6.2.2",
|
|
||||||
"ts-jest": "27.1.3",
|
|
||||||
"ts-loader": "9.2.6",
|
|
||||||
"ts-node": "10.5.0",
|
|
||||||
"tsconfig-paths": "3.12.0",
|
|
||||||
"typescript": "4.4.4"
|
|
||||||
},
|
|
||||||
"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,3 +0,0 @@
|
|||||||
export const HELLO_SCENE_ID = 'HELLO_SCENE_ID';
|
|
||||||
|
|
||||||
export const GreeterBotName = 'greeter';
|
|
@ -1,26 +0,0 @@
|
|||||||
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,
|
|
||||||
include: [EchoModule],
|
|
||||||
}),
|
|
||||||
TelegrafModule.forRootAsync({
|
|
||||||
botName: GreeterBotName,
|
|
||||||
useFactory: () => ({
|
|
||||||
token: process.env.GREETER_BOT_TOKEN,
|
|
||||||
middlewares: [sessionMiddleware],
|
|
||||||
include: [GreeterModule],
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
EchoModule,
|
|
||||||
GreeterModule,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class AppModule {}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
|
||||||
import { TelegrafExecutionContext } from 'nestjs-telegraf';
|
|
||||||
|
|
||||||
export const UpdateType = createParamDecorator(
|
|
||||||
(_, ctx: ExecutionContext) =>
|
|
||||||
TelegrafExecutionContext.create(ctx).getContext().updateType,
|
|
||||||
);
|
|
@ -1,13 +0,0 @@
|
|||||||
import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
|
|
||||||
import { TelegrafArgumentsHost } from 'nestjs-telegraf';
|
|
||||||
import { Context } from '../../interfaces/context.interface';
|
|
||||||
|
|
||||||
@Catch()
|
|
||||||
export class TelegrafExceptionFilter implements ExceptionFilter {
|
|
||||||
async catch(exception: Error, host: ArgumentsHost): Promise<void> {
|
|
||||||
const telegrafHost = TelegrafArgumentsHost.create(host);
|
|
||||||
const ctx = telegrafHost.getContext<Context>();
|
|
||||||
|
|
||||||
await ctx.replyWithHTML(`<b>Error</b>: ${exception.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
|
|
||||||
import { TelegrafExecutionContext, TelegrafException } from 'nestjs-telegraf';
|
|
||||||
import { Context } from '../../interfaces/context.interface';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AdminGuard implements CanActivate {
|
|
||||||
private readonly ADMIN_IDS = [];
|
|
||||||
|
|
||||||
canActivate(context: ExecutionContext): boolean {
|
|
||||||
const ctx = TelegrafExecutionContext.create(context);
|
|
||||||
const { from } = ctx.getContext<Context>();
|
|
||||||
|
|
||||||
const isAdmin = this.ADMIN_IDS.includes(from.id);
|
|
||||||
if (!isAdmin) {
|
|
||||||
throw new TelegrafException('You are not admin 😡');
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import {
|
|
||||||
CallHandler,
|
|
||||||
ExecutionContext,
|
|
||||||
Injectable,
|
|
||||||
NestInterceptor,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { tap } from 'rxjs/operators';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ResponseTimeInterceptor implements NestInterceptor {
|
|
||||||
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
|
|
||||||
console.log('Before...');
|
|
||||||
|
|
||||||
const start = Date.now();
|
|
||||||
return next
|
|
||||||
.handle()
|
|
||||||
.pipe(tap(() => console.log(`Response time: ${Date.now() - start}ms`)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { Injectable, PipeTransform } from '@nestjs/common';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ReverseTextPipe implements PipeTransform {
|
|
||||||
transform(value: string): string {
|
|
||||||
return value.split('').reverse().join('');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { EchoUpdate } from './echo.update';
|
|
||||||
import { EchoService } from './echo.service';
|
|
||||||
import { RandomNumberScene } from '../greeter/scenes/random-number.scene';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
providers: [EchoUpdate, EchoService, RandomNumberScene],
|
|
||||||
})
|
|
||||||
export class EchoModule {}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class EchoService {
|
|
||||||
echo(text: string): string {
|
|
||||||
return `Echo: ${text}`;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
import { UseFilters, UseGuards, UseInterceptors } from '@nestjs/common';
|
|
||||||
import {
|
|
||||||
Help,
|
|
||||||
InjectBot,
|
|
||||||
On,
|
|
||||||
Message,
|
|
||||||
Start,
|
|
||||||
Update,
|
|
||||||
Command,
|
|
||||||
} from 'nestjs-telegraf';
|
|
||||||
import { Telegraf } from 'telegraf';
|
|
||||||
import { EchoService } from './echo.service';
|
|
||||||
import { GreeterBotName } from '../app.constants';
|
|
||||||
import { Context } from '../interfaces/context.interface';
|
|
||||||
import { ReverseTextPipe } from '../common/pipes/reverse-text.pipe';
|
|
||||||
import { ResponseTimeInterceptor } from '../common/interceptors/response-time.interceptor';
|
|
||||||
import { AdminGuard } from '../common/guards/admin.guard';
|
|
||||||
import { TelegrafExceptionFilter } from '../common/filters/telegraf-exception.filter';
|
|
||||||
|
|
||||||
@Update()
|
|
||||||
@UseInterceptors(ResponseTimeInterceptor)
|
|
||||||
@UseFilters(TelegrafExceptionFilter)
|
|
||||||
export class EchoUpdate {
|
|
||||||
constructor(
|
|
||||||
@InjectBot(GreeterBotName)
|
|
||||||
private readonly bot: Telegraf<Context>,
|
|
||||||
private readonly echoService: EchoService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
@Start()
|
|
||||||
async onStart(): Promise<string> {
|
|
||||||
const me = await this.bot.telegram.getMe();
|
|
||||||
return `Hey, I'm ${me.first_name}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Help()
|
|
||||||
async onHelp(): Promise<string> {
|
|
||||||
return 'Send me any text';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command('admin')
|
|
||||||
@UseGuards(AdminGuard)
|
|
||||||
onAdminCommand(): string {
|
|
||||||
return 'Welcome judge';
|
|
||||||
}
|
|
||||||
|
|
||||||
@On('text')
|
|
||||||
onMessage(
|
|
||||||
@Message('text', new ReverseTextPipe()) reversedText: string,
|
|
||||||
): string {
|
|
||||||
return this.echoService.echo(reversedText);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { GreeterUpdate } from './greeter.update';
|
|
||||||
import { RandomNumberScene } from './scenes/random-number.scene';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
providers: [GreeterUpdate, RandomNumberScene],
|
|
||||||
})
|
|
||||||
export class GreeterModule {}
|
|
@ -1,26 +0,0 @@
|
|||||||
import { Command, Ctx, Hears, Start, Update, Sender } from 'nestjs-telegraf';
|
|
||||||
import { UpdateType as TelegrafUpdateType } from 'telegraf/typings/telegram-types';
|
|
||||||
import { Context } from '../interfaces/context.interface';
|
|
||||||
import { HELLO_SCENE_ID } from '../app.constants';
|
|
||||||
import { UpdateType } from '../common/decorators/update-type.decorator';
|
|
||||||
|
|
||||||
@Update()
|
|
||||||
export class GreeterUpdate {
|
|
||||||
@Start()
|
|
||||||
onStart(): string {
|
|
||||||
return 'Say hello to me';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Hears(['hi', 'hello', 'hey', 'qq'])
|
|
||||||
onGreetings(
|
|
||||||
@UpdateType() updateType: TelegrafUpdateType,
|
|
||||||
@Sender('first_name') firstName: string,
|
|
||||||
): string {
|
|
||||||
return `Hey ${firstName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command('scene')
|
|
||||||
async onSceneCommand(@Ctx() ctx: Context): Promise<void> {
|
|
||||||
await ctx.scene.enter(HELLO_SCENE_ID);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
import { Scene, SceneEnter, SceneLeave, Command } from 'nestjs-telegraf';
|
|
||||||
import { HELLO_SCENE_ID } from '../../app.constants';
|
|
||||||
import { Context } from '../../interfaces/context.interface';
|
|
||||||
|
|
||||||
@Scene(HELLO_SCENE_ID)
|
|
||||||
export class RandomNumberScene {
|
|
||||||
@SceneEnter()
|
|
||||||
onSceneEnter(): string {
|
|
||||||
console.log('Enter to scene');
|
|
||||||
return 'Welcome on scene ✋';
|
|
||||||
}
|
|
||||||
|
|
||||||
@SceneLeave()
|
|
||||||
onSceneLeave(): string {
|
|
||||||
console.log('Leave from scene');
|
|
||||||
return 'Bye Bye 👋';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command(['rng', 'random'])
|
|
||||||
onRandomCommand(): number {
|
|
||||||
console.log('Use "random" command');
|
|
||||||
return Math.floor(Math.random() * 11);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command('leave')
|
|
||||||
async onLeaveCommand(ctx: Context): Promise<void> {
|
|
||||||
await ctx.scene.leave();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
import { Scenes } from 'telegraf';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
||||||
export interface Context extends Scenes.SceneContext {}
|
|
@ -1,8 +0,0 @@
|
|||||||
import 'dotenv/config';
|
|
||||||
import { NestFactory } from '@nestjs/core';
|
|
||||||
import { AppModule } from './app.module';
|
|
||||||
|
|
||||||
async function bootstrap() {
|
|
||||||
await NestFactory.createApplicationContext(AppModule);
|
|
||||||
}
|
|
||||||
bootstrap();
|
|
@ -1,3 +0,0 @@
|
|||||||
import { session } from 'telegraf';
|
|
||||||
|
|
||||||
export const sessionMiddleware = session();
|
|
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "./tsconfig.json",
|
|
||||||
"exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"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,5 +1,3 @@
|
|||||||
export * from './update.decorator';
|
export * from './update.decorator';
|
||||||
export * from './scene.decorator';
|
|
||||||
export * from './wizard.decorator';
|
|
||||||
export * from './inject-bot.decorator';
|
export * from './inject-bot.decorator';
|
||||||
export * from './inject-all-bots.decorator';
|
export * from './inject-all-bots.decorator';
|
@ -1,9 +1,9 @@
|
|||||||
import { Inject } from '@nestjs/common';
|
import { Inject } from '@nestjs/common';
|
||||||
import { Telegraf } from 'telegraf';
|
import { Bot } from 'grammy';
|
||||||
|
|
||||||
import { getAllBotsToken } from '../../utils/get-all-bots-token.util';
|
import { getAllBotsToken } from '../../utils/get-all-bots-token.util';
|
||||||
|
|
||||||
export type AllBotsMap = Map<string, Telegraf<any>>;
|
export type AllBotsMap = Map<string, Bot<any>>;
|
||||||
|
|
||||||
export const InjectAllBots = (): ParameterDecorator =>
|
export const InjectAllBots = (): ParameterDecorator =>
|
||||||
Inject(getAllBotsToken());
|
Inject(getAllBotsToken());
|
@ -1,4 +1,3 @@
|
|||||||
export * from './core';
|
export * from './core';
|
||||||
export * from './listeners';
|
export * from './listeners';
|
||||||
export * from './scene';
|
|
||||||
export * from './params';
|
export * from './params';
|
6
src/decorators/listeners/index.ts
Normal file
6
src/decorators/listeners/index.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export * from './on.decorator';
|
||||||
|
export * from './use.decorator';
|
||||||
|
export * from './command.decorator';
|
||||||
|
export * from './game-query.decorator';
|
||||||
|
export * from './hears.decorator';
|
||||||
|
export * from './inline-query.decorator';
|
@ -1,6 +1,6 @@
|
|||||||
import { ParamData } from '@nestjs/common';
|
import { ParamData } from '@nestjs/common';
|
||||||
import { ParamsFactory } from '@nestjs/core/helpers/external-context-creator';
|
import { ParamsFactory } from '@nestjs/core/helpers/external-context-creator';
|
||||||
import { Context } from 'telegraf';
|
import { Context } from 'grammy';
|
||||||
import { TelegrafParamtype } from '../enums/telegraf-paramtype.enum';
|
import { TelegrafParamtype } from '../enums/telegraf-paramtype.enum';
|
||||||
|
|
||||||
export class TelegrafParamsFactory implements ParamsFactory {
|
export class TelegrafParamsFactory implements ParamsFactory {
|
@ -1,4 +1,3 @@
|
|||||||
export * from './telegraf-options.interface';
|
export * from './telegraf-options.interface';
|
||||||
export * from './listener-metadata.interface';
|
export * from './listener-metadata.interface';
|
||||||
export * from './scene-metadata.interface';
|
|
||||||
export * from './telegraf-exception-filter.interface';
|
export * from './telegraf-exception-filter.interface';
|
@ -1,11 +1,11 @@
|
|||||||
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';
|
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';
|
||||||
import { Middleware, Telegraf } from 'telegraf';
|
import { Middleware, PollingOptions, BotConfig } from 'grammy';
|
||||||
|
|
||||||
export interface TelegrafModuleOptions {
|
export interface TelegrafModuleOptions {
|
||||||
token: string;
|
token: string;
|
||||||
|
config?: BotConfig<any>;
|
||||||
|
pollingOptions?: PollingOptions | false;
|
||||||
botName?: string;
|
botName?: string;
|
||||||
options?: Partial<Telegraf.Options<any>>;
|
|
||||||
launchOptions?: Telegraf.LaunchOptions | false;
|
|
||||||
include?: Function[];
|
include?: Function[];
|
||||||
middlewares?: ReadonlyArray<Middleware<any>>;
|
middlewares?: ReadonlyArray<Middleware<any>>;
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
|||||||
import { Module } from '@nestjs/core/injector/module';
|
import { Module } from '@nestjs/core/injector/module';
|
||||||
import { ParamMetadata } from '@nestjs/core/helpers/interfaces';
|
import { ParamMetadata } from '@nestjs/core/helpers/interfaces';
|
||||||
import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator';
|
import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator';
|
||||||
import { Composer, Context, Scenes, Telegraf } from 'telegraf';
|
import { Composer, Context, Bot } from 'grammy';
|
||||||
|
|
||||||
import { MetadataAccessorService } from './metadata-accessor.service';
|
import { MetadataAccessorService } from './metadata-accessor.service';
|
||||||
import {
|
import {
|
||||||
@ -25,11 +25,9 @@ export class ListenersExplorerService
|
|||||||
implements OnModuleInit
|
implements OnModuleInit
|
||||||
{
|
{
|
||||||
private readonly telegrafParamsFactory = new TelegrafParamsFactory();
|
private readonly telegrafParamsFactory = new TelegrafParamsFactory();
|
||||||
private bot: Telegraf<any>;
|
private bot: Bot;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(TELEGRAF_STAGE)
|
|
||||||
private readonly stage: Scenes.Stage<any>,
|
|
||||||
@Inject(TELEGRAF_MODULE_OPTIONS)
|
@Inject(TELEGRAF_MODULE_OPTIONS)
|
||||||
private readonly telegrafOptions: TelegrafModuleOptions,
|
private readonly telegrafOptions: TelegrafModuleOptions,
|
||||||
@Inject(TELEGRAF_BOT_NAME)
|
@Inject(TELEGRAF_BOT_NAME)
|
||||||
@ -45,10 +43,9 @@ export class ListenersExplorerService
|
|||||||
}
|
}
|
||||||
|
|
||||||
onModuleInit(): void {
|
onModuleInit(): void {
|
||||||
this.bot = this.moduleRef.get<Telegraf<any>>(this.botName, {
|
this.bot = this.moduleRef.get<Bot>(this.botName, {
|
||||||
strict: false,
|
strict: false,
|
||||||
});
|
});
|
||||||
this.bot.use(this.stage.middleware());
|
|
||||||
|
|
||||||
this.explore();
|
this.explore();
|
||||||
}
|
}
|
||||||
@ -60,7 +57,6 @@ export class ListenersExplorerService
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.registerUpdates(modules);
|
this.registerUpdates(modules);
|
||||||
this.registerScenes(modules);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerUpdates(modules: Module[]): void {
|
private registerUpdates(modules: Module[]): void {
|
||||||
@ -70,28 +66,6 @@ export class ListenersExplorerService
|
|||||||
updates.forEach((wrapper) => this.registerListeners(this.bot, wrapper));
|
updates.forEach((wrapper) => this.registerListeners(this.bot, wrapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerScenes(modules: Module[]): void {
|
|
||||||
const scenes = this.flatMap<InstanceWrapper>(modules, (wrapper) =>
|
|
||||||
this.filterScenes(wrapper),
|
|
||||||
);
|
|
||||||
scenes.forEach((wrapper) => {
|
|
||||||
const { sceneId, type, options } = this.metadataAccessor.getSceneMetadata(
|
|
||||||
wrapper.instance.constructor,
|
|
||||||
);
|
|
||||||
const scene =
|
|
||||||
type === 'base'
|
|
||||||
? new Scenes.BaseScene<any>(sceneId, options || ({} as any))
|
|
||||||
: new Scenes.WizardScene<any>(sceneId, options || ({} as any));
|
|
||||||
this.stage.register(scene);
|
|
||||||
|
|
||||||
if (type === 'base') {
|
|
||||||
this.registerListeners(scene, wrapper);
|
|
||||||
} else {
|
|
||||||
this.registerWizardListeners(scene as Scenes.WizardScene<any>, wrapper);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private filterUpdates(wrapper: InstanceWrapper): InstanceWrapper<unknown> {
|
private filterUpdates(wrapper: InstanceWrapper): InstanceWrapper<unknown> {
|
||||||
const { instance } = wrapper;
|
const { instance } = wrapper;
|
||||||
if (!instance) return undefined;
|
if (!instance) return undefined;
|
||||||
@ -102,16 +76,6 @@ export class ListenersExplorerService
|
|||||||
return wrapper;
|
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 registerListeners(
|
private registerListeners(
|
||||||
composer: Composer<any>,
|
composer: Composer<any>,
|
||||||
wrapper: InstanceWrapper<unknown>,
|
wrapper: InstanceWrapper<unknown>,
|
||||||
@ -123,60 +87,6 @@ export class ListenersExplorerService
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerWizardListeners(
|
|
||||||
wizard: Scenes.WizardScene<any>,
|
|
||||||
wrapper: InstanceWrapper<unknown>,
|
|
||||||
): void {
|
|
||||||
const { instance } = wrapper;
|
|
||||||
const prototype = Object.getPrototypeOf(instance);
|
|
||||||
|
|
||||||
type WizardMetadata = { step: number; methodName: string };
|
|
||||||
const wizardSteps: WizardMetadata[] = [];
|
|
||||||
const basicListeners = [];
|
|
||||||
|
|
||||||
this.metadataScanner.scanFromPrototype(
|
|
||||||
instance,
|
|
||||||
prototype,
|
|
||||||
(methodName) => {
|
|
||||||
const methodRef = prototype[methodName];
|
|
||||||
const metadata = this.metadataAccessor.getWizardStepMetadata(methodRef);
|
|
||||||
if (!metadata) {
|
|
||||||
basicListeners.push(methodName);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
wizardSteps.push({ step: metadata.step, methodName });
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const methodName of basicListeners) {
|
|
||||||
this.registerIfListener(wizard, instance, prototype, methodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
const group = wizardSteps
|
|
||||||
.sort((a, b) => a.step - b.step)
|
|
||||||
.reduce<{ [key: number]: WizardMetadata[] }>(
|
|
||||||
(prev, cur) => ({
|
|
||||||
...prev,
|
|
||||||
[cur.step]: [...(prev[cur.step] || []), cur],
|
|
||||||
}),
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
|
|
||||||
wizard.steps = Object.values(group).map((stepsMetadata) => {
|
|
||||||
const composer = new Composer();
|
|
||||||
stepsMetadata.forEach((stepMethod) => {
|
|
||||||
this.registerIfListener(
|
|
||||||
composer,
|
|
||||||
instance,
|
|
||||||
prototype,
|
|
||||||
stepMethod.methodName,
|
|
||||||
[{ method: 'use', args: [] }],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return composer.middleware();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private registerIfListener(
|
private registerIfListener(
|
||||||
composer: Composer<any>,
|
composer: Composer<any>,
|
||||||
instance: any,
|
instance: any,
|
18
src/services/metadata-accessor.service.ts
Normal file
18
src/services/metadata-accessor.service.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Reflector } from '@nestjs/core';
|
||||||
|
import { LISTENERS_METADATA, UPDATE_METADATA } from '../telegraf.constants';
|
||||||
|
import { ListenerMetadata } from '../interfaces';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MetadataAccessorService {
|
||||||
|
constructor(private readonly reflector: Reflector) {}
|
||||||
|
|
||||||
|
isUpdate(target: Function): boolean {
|
||||||
|
if (!target) return false;
|
||||||
|
return !!this.reflector.get(UPDATE_METADATA, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
getListenerMetadata(target: Function): ListenerMetadata[] | undefined {
|
||||||
|
return this.reflector.get(LISTENERS_METADATA, target);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
import { Provider } from '@nestjs/common';
|
import { Provider } from '@nestjs/common';
|
||||||
import { Telegraf } from 'telegraf';
|
import { Bot } from 'grammy';
|
||||||
import { TELEGRAF_ALL_BOTS } from './telegraf.constants';
|
import { TELEGRAF_ALL_BOTS } from './telegraf.constants';
|
||||||
|
|
||||||
export const allBotsMap = new Map<string, Telegraf<any>>();
|
export const allBotsMap = new Map<string, Bot<any>>();
|
||||||
|
|
||||||
export const telegrafAllBotsProvider: Provider = {
|
export const telegrafAllBotsProvider: Provider = {
|
||||||
provide: TELEGRAF_ALL_BOTS,
|
provide: TELEGRAF_ALL_BOTS,
|
@ -18,7 +18,6 @@ import {
|
|||||||
TELEGRAF_MODULE_OPTIONS,
|
TELEGRAF_MODULE_OPTIONS,
|
||||||
} from './telegraf.constants';
|
} from './telegraf.constants';
|
||||||
import { ListenersExplorerService, MetadataAccessorService } from './services';
|
import { ListenersExplorerService, MetadataAccessorService } from './services';
|
||||||
import { telegrafStageProvider } from './stage.provider';
|
|
||||||
import {
|
import {
|
||||||
allBotsMap,
|
allBotsMap,
|
||||||
telegrafAllBotsProvider,
|
telegrafAllBotsProvider,
|
||||||
@ -61,13 +60,11 @@ export class TelegrafCoreModule implements OnApplicationShutdown {
|
|||||||
provide: TELEGRAF_MODULE_OPTIONS,
|
provide: TELEGRAF_MODULE_OPTIONS,
|
||||||
useValue: options,
|
useValue: options,
|
||||||
},
|
},
|
||||||
telegrafStageProvider,
|
|
||||||
telegrafBotNameProvider,
|
telegrafBotNameProvider,
|
||||||
telegrafBotProvider,
|
telegrafBotProvider,
|
||||||
telegrafAllBotsProvider,
|
telegrafAllBotsProvider,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
telegrafStageProvider,
|
|
||||||
telegrafBotNameProvider,
|
telegrafBotNameProvider,
|
||||||
telegrafBotProvider,
|
telegrafBotProvider,
|
||||||
telegrafAllBotsProvider,
|
telegrafAllBotsProvider,
|
||||||
@ -101,13 +98,11 @@ export class TelegrafCoreModule implements OnApplicationShutdown {
|
|||||||
imports: options.imports,
|
imports: options.imports,
|
||||||
providers: [
|
providers: [
|
||||||
...asyncProviders,
|
...asyncProviders,
|
||||||
telegrafStageProvider,
|
|
||||||
telegrafBotNameProvider,
|
telegrafBotNameProvider,
|
||||||
telegrafBotProvider,
|
telegrafBotProvider,
|
||||||
telegrafAllBotsProvider,
|
telegrafAllBotsProvider,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
telegrafStageProvider,
|
|
||||||
telegrafBotNameProvider,
|
telegrafBotNameProvider,
|
||||||
telegrafBotProvider,
|
telegrafBotProvider,
|
||||||
telegrafAllBotsProvider,
|
telegrafAllBotsProvider,
|
@ -6,10 +6,10 @@ import {
|
|||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
|
|
||||||
@Module({})
|
@Module({})
|
||||||
export class TelegrafModule {
|
export class GrammyModule {
|
||||||
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
||||||
return {
|
return {
|
||||||
module: TelegrafModule,
|
module: GrammyModule,
|
||||||
imports: [TelegrafCoreModule.forRoot(options)],
|
imports: [TelegrafCoreModule.forRoot(options)],
|
||||||
exports: [TelegrafCoreModule],
|
exports: [TelegrafCoreModule],
|
||||||
};
|
};
|
||||||
@ -19,7 +19,7 @@ export class TelegrafModule {
|
|||||||
options: TelegrafModuleAsyncOptions,
|
options: TelegrafModuleAsyncOptions,
|
||||||
): DynamicModule {
|
): DynamicModule {
|
||||||
return {
|
return {
|
||||||
module: TelegrafModule,
|
module: GrammyModule,
|
||||||
imports: [TelegrafCoreModule.forRootAsync(options)],
|
imports: [TelegrafCoreModule.forRootAsync(options)],
|
||||||
exports: [TelegrafCoreModule],
|
exports: [TelegrafCoreModule],
|
||||||
};
|
};
|
@ -1,4 +1,4 @@
|
|||||||
import { Composer, Middleware } from 'telegraf';
|
import { Composer, Middleware } from 'grammy';
|
||||||
|
|
||||||
export type Filter<T extends any[], F> = T extends []
|
export type Filter<T extends any[], F> = T extends []
|
||||||
? []
|
? []
|
16
src/utils/create-bot-factory.util.ts
Normal file
16
src/utils/create-bot-factory.util.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Bot } from 'grammy';
|
||||||
|
import { TelegrafModuleOptions } from '../interfaces';
|
||||||
|
|
||||||
|
export async function createBotFactory(
|
||||||
|
options: TelegrafModuleOptions,
|
||||||
|
): Promise<Bot> {
|
||||||
|
const bot = new Bot(options.token, options.config);
|
||||||
|
|
||||||
|
bot.use(...(options.middlewares ?? []));
|
||||||
|
|
||||||
|
if (options.pollingOptions !== false) {
|
||||||
|
bot.start(options.pollingOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { Composer } from 'telegraf';
|
import { Composer } from 'grammy';
|
||||||
import { ComposerMethodArgs, OnlyFunctionPropertyNames } from '../types';
|
import { ComposerMethodArgs, OnlyFunctionPropertyNames } from '../types';
|
||||||
import { LISTENERS_METADATA } from '../telegraf.constants';
|
import { LISTENERS_METADATA } from '../telegraf.constants';
|
||||||
import { ListenerMetadata } from '../interfaces';
|
import { ListenerMetadata } from '../interfaces';
|
9
tsconfig.lib.json
Normal file
9
tsconfig.lib.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "../../dist/libs/grammy"
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user