1 | import { isSessionContext, SessionContext } from '../session'
|
2 | import SceneContextScene, {
|
3 | SceneContextSceneOptions,
|
4 | SceneSession,
|
5 | SceneSessionData,
|
6 | } from './context'
|
7 | import { BaseScene } from './base'
|
8 | import { Composer } from '../composer'
|
9 | import { Context } from '../context'
|
10 |
|
11 | export class Stage<
|
12 | C extends SessionContext<SceneSession<D>> & {
|
13 | scene: SceneContextScene<C, D>
|
14 | },
|
15 | D extends SceneSessionData = SceneSessionData
|
16 | > extends Composer<C> {
|
17 | options: Partial<SceneContextSceneOptions<D>>
|
18 | scenes: Map<string, BaseScene<C>>
|
19 |
|
20 | constructor(
|
21 | scenes: ReadonlyArray<BaseScene<C>> = [],
|
22 | options?: Partial<SceneContextSceneOptions<D>>
|
23 | ) {
|
24 | super()
|
25 | this.options = { ...options }
|
26 | this.scenes = new Map<string, BaseScene<C>>()
|
27 | scenes.forEach((scene) => this.register(scene))
|
28 | }
|
29 |
|
30 | register(...scenes: ReadonlyArray<BaseScene<C>>) {
|
31 | scenes.forEach((scene) => {
|
32 | if (scene?.id == null || typeof scene.middleware !== 'function') {
|
33 | throw new Error('telegraf: Unsupported scene')
|
34 | }
|
35 | this.scenes.set(scene.id, scene)
|
36 | })
|
37 | return this
|
38 | }
|
39 |
|
40 | middleware() {
|
41 | const handler = Composer.compose<C>([
|
42 | (ctx, next) => {
|
43 | const scenes: Map<string, BaseScene<C>> = this.scenes
|
44 | const scene = new SceneContextScene<C, D>(ctx, scenes, this.options)
|
45 | ctx.scene = scene
|
46 | return next()
|
47 | },
|
48 | super.middleware(),
|
49 | Composer.lazy<C>((ctx) => ctx.scene.current ?? Composer.passThru()),
|
50 | ])
|
51 | return Composer.optional(isSessionContext, handler)
|
52 | }
|
53 |
|
54 | static enter<C extends Context & { scene: SceneContextScene<C> }>(
|
55 | ...args: Parameters<SceneContextScene<C>['enter']>
|
56 | ) {
|
57 | return (ctx: C) => ctx.scene.enter(...args)
|
58 | }
|
59 |
|
60 | static reenter<C extends Context & { scene: SceneContextScene<C> }>(
|
61 | ...args: Parameters<SceneContextScene<C>['reenter']>
|
62 | ) {
|
63 | return (ctx: C) => ctx.scene.reenter(...args)
|
64 | }
|
65 |
|
66 | static leave<C extends Context & { scene: SceneContextScene<C> }>(
|
67 | ...args: Parameters<SceneContextScene<C>['leave']>
|
68 | ) {
|
69 | return (ctx: C) => ctx.scene.leave(...args)
|
70 | }
|
71 | }
|