Closed meowlanguages closed 3 years ago
Hey @meowlanguages! I've never used the Wizard and probably can't help it, but you can do whatever you want with Telegraf
by injecting Telegraf
instance directly with @InjectBot()
decorator.
Also, @Morb0 may be you can help?
You can inject TELEGRAF_STAGE
provider, create a wizard scene as usual, and register it in Stage
.
Example:
constructor(
@Inject(TELEGRAF_STAGE) stage: Scenes.Stage<Context>,
) {
const scene = new Scenes.WizardScene<Context>(
'youSceneIdentifier',
this.createStepHandler1(),
this.createStepHandler2(),
// other steps...
);
stage.register(scene);
}
@meowlanguages problem solved?
Hey @bukhalo 👋
Thanks for helping the community!
I'm trying to use wizard scenes too and I'm facing a lot of difficulty due to the lack of documentation and practical examples.
It's not your fault of course, but to the extent of your time and availability, could you consider adding examples of this? Much appreciated.
You can inject
TELEGRAF_STAGE
provider, create a wizard scene as usual, and register it inStage
.Example:
constructor( @Inject(TELEGRAF_STAGE) stage: Scenes.Stage<Context>, ) { const scene = new Scenes.WizardScene<Context>( 'youSceneIdentifier', this.createStepHandler1(), this.createStepHandler2(), // other steps... ); stage.register(scene); }
My big question is how to create a "Wizard Scene" in "nest way" in a way that is scalable and using the decorators that this module offers. I'm sorry but I couldn't understand how it's possible to do this at first.
https://github.com/telegraf/telegraf/issues/705#issuecomment-549056045
I was checking some links about this and I'm facing the same difficulty posed in this example.
I need to request user data like Phone Number, Email, and Home address using Wizard Scene. I imagine this is a common use case so I think it would be very interesting for the community to have an example of this using Telegraf + Wizard Scenes.
Yes, agree. Missing wizard support and docs in nest way.
@Morb0 use wizard scene does not work because "TypeScript types". Could you help me?
import { Inject } from '@nestjs/common';
import { Scene, TELEGRAF_STAGE } from 'nestjs-telegraf';
import { Scenes } from 'telegraf';
import { Context } from '@/tg/common/interfaces';
@Scene('userPersonalDataWizard')
export class UserPersonalDataWizard {
constructor(@Inject(TELEGRAF_STAGE) stage: Scenes.Stage<Context>) {
const scene = new Scenes.WizardScene<Scenes.WizardContext>(
'userPersonalDataWizard',
this.hello(),
// this.createStepHandler2(),
// other steps...
);
stage.register(scene);
}
hello() {
return 'heyyyyyyyyy!';
}
}
No overload matches this call.
Overload 1 of 2, '(id: string, ...steps: Middleware<WizardContext<WizardSessionData>>[]): WizardScene<WizardContext<WizardSessionData>>', gave the following error.
Argument of type 'string' is not assignable to parameter of type 'Middleware<WizardContext<WizardSessionData>>'.
Overload 2 of 2, '(id: string, options: SceneOptions<WizardContext<WizardSessionData>>, ...steps: Middleware<WizardContext<WizardSessionData>>[]): WizardScene<...>', gave the following error.
Argument of type 'string' is not assignable to parameter of type 'SceneOptions<WizardContext<WizardSessionData>>'.ts(2769)
What TypeScript types should I use? Could you send a full example and not only a code snippet, please?
@felinto-dev As types says, you need return middleware function from hello
method.
Somthing like this:
hello() {
return (ctx) => {
ctx.reply('Hello World');
ctx.wizard.next();
}
}
I would like to say thank you so much for your help!
Once this example is working I will post the full code here to help the community. Unfortunately, I'm not getting into the scene.
I get the following error: "Cannot read property 'enter' of undefined"
Another question is that you notice that I commented "@Scene('userPersonalDataWizard')". Should I repeat the name of the scene twice?
I guess I need to use "stage middleware", however, this example does not works
https://github.com/bukhalo/nestjs-telegraf/issues/72#issuecomment-623085469
import { Stage } from 'nestjs-telegraf';
const stage = new Stage([superWizard], { default: 'super-wizard' });
this.bot.use(stage.middleware());
After hours of trying to find a solution, I saw what the error was, which is not obvious at first glance. Also, why session middleware is deprecated. https://github.com/telegraf/telegraf/issues/1372#issuecomment-782668499
It is necessary to activate the session middleware for the scene wizard to work.
https://github.com/telegraf/telegraf/issues/309#issuecomment-362870720
https://github.com/RealSpeaker/telegraf-session-local/issues/153
Hello
Thank you very much for integrating Scenes in Decorators. It works really awesome.
It will be also helpful to add Wizard functionality
Maybe in this way ?
@WizardScene()
class ProfileWizardScene {
Step('1')
ageStep() {
@Enter
ageStepEnter(ctx) {
ctx.reply('Age Step Enter')
}
@On('message')
ageMessageHandler(ctx) {
ctx.reply('Age Saved')
ctx.wizard.next();
}
}
Step('2')
nameStep() {
@Enter
nameStepEnter(ctx) {
ctx.reply('Name Step Enter')
}
@On('message')
nameMessageHandler(ctx) {
ctx.reply('Name Saved')
ctx.wizard.next();
}
}
}
Wizard support added in v2.4.0, see on @xTCry code for example.
Wizard support added in v2.4.0, see on @xTCry code for example.
Could you send the direct link for example please?
Wizard support added in v2.4.0, see on @xTCry code for example.
Could you send the direct link for example please?
Working example: https://github.com/bukhalo/nestjs-telegraf/pull/469#issuecomment-902583496
Simplified example:
import { Context, Wizard, WizardStep } from 'nestjs-telegraf'
import { Scenes } from 'telegraf'
@Wizard('test') export class TestWizard { @WizardStep(1) step1(@Context() ctx: Scenes.WizardContext) { ctx.reply('first scene') ctx.wizard.next() }
@WizardStep(2) async step2(@Context() ctx: Scenes.WizardContext) { ctx.reply('last scene') ctx.scene.leave() } }
2. Configure TelegrafModule and add TestWizard to your module providers.
import { session } from 'telegraf' @Module({ imports: [ TelegrafModule.forRoot({ token: 'YOUR_TELEGRAM_TOKEN', middlewares: [session()], }), ], providers: [TestWizard], }) export class MyTelegramModule {}
3. Enter wizard by calling ctx.scene.enter, e.g.:
@Start() start(ctx: Scenes.SceneContext) { ctx.scene.enter('test') }
is there an example with callback_data in a button. im not able to get any data from the callback buttons when i move between steps
is there an example with callback_data in a button. im not able to get any data from the callback buttons when i move between steps
If I understood you correctly, here is an example:
import { Context, Wizard, WizardStep } from 'nestjs-telegraf'
import { Scenes } from 'telegraf'
@Wizard('test')
export class TestWizard {
@WizardStep(1)
step1(@Context() ctx: Scenes.WizardContext) {
const randomData = Math.random()
ctx.reply('Press the button', {
reply_markup: {
inline_keyboard: [
[{ text: 'Press me', callback_data: `action:${randomData}` }],
],
},
reply_to_message_id: ctx.message.message_id,
})
}
@Action(/action:.+/)
button(@Context() ctx: any) {
const [, data] = ctx.callbackQuery.data.split(':')
ctx.answerCbQuery()
// save data for next step in ctx.wizard.state
ctx.wizard.state.data = data
ctx.wizard.next()
ctx.wizard.steps[ctx.wizard.cursor](ctx)
}
@WizardStep(2)
async step2(@Context() ctx: Scenes.WizardContext) {
// ctx.wizard.state contains stored data
console.log((ctx.wizard.state as any).data)
ctx.scene.leave()
}
}
Note that using ctx.wizard.steps[ctx.wizard.cursor](ctx)
is a little hack to call step 2 immediately after pressing the button. Without this user would need to send another message to call step 2.
I have no idea how to use wizard on my scene. Please add more examples.