Stage.enter无法启动向导

sfa*_*oso 6 javascript node.js telegram telegram-bot telegraf

我创建了一个向用户显示调查向导的应用程序。当用户启动/ start命令时,我将调用AddProject

const Telegraf = require('telegraf');
const bot = new Telegraf(process.env.BOT_TOKEN);
const session = require('telegraf/session');
bot.use(session());

const main = new TelegrafInlineMenu("Welcome.");
main.setCommand('start');
main.simpleButton('Start Survey', 'START_SURVEY', {
  doFunc: async ctx => surveyController.AddProject(ctx, bot)
});
Run Code Online (Sandbox Code Playgroud)

基本上,以上代码创建了一个菜单,其中显示了标签Welcome(欢迎)和一个按钮以启动调查。当用户单击按钮时,从SurveyController调用方法AddProject:

const Composer = require('telegraf/composer');
const stepHandler = new Composer();
const Stage = require('telegraf/stage');
const WizardScene = require('telegraf/scenes/wizard');
const userController = require('../controllers/user.controller');

module.exports = {

  AddProject: async function (ctx, bot) {

    const superWizard = new WizardScene('super-wizard',
      (ctx) => {
        ctx.reply('Step 1', Markup.inlineKeyboard([
          Markup.urlButton('??', 'http://telegraf.js.org'),
          Markup.callbackButton('?? Next', 'next'),
        ]).extra());
        return ctx.wizard.next();
      },
      (ctx) => {
        ctx.reply('Step 2');
        return ctx.wizard.next();
      },
      (ctx) => {
        ctx.reply('Done');
        return ctx.wizard.leave();
      },
    );

    const stage = new Stage([superWizard]);
    bot.use(stage.middleware());
    Stage.enter('super-wizard');
  },
};
Run Code Online (Sandbox Code Playgroud)

方法AddProject可以正确触发,但是没有显示向导,我做错了什么?

sfa*_*oso 6

经过大量的尝试,我终于实现了我的目标。我不是专家,TelegrafJS我发现文档真的很难理解,特别是如果您是新手(缺少示例,缺少WizardScene之类的概念等)。

创建一个场景

因此,基本上要实现我的目标,我必须使用SceneTelegrafJS提供不同类型Scene的。

我的目标是等待用户输入并进行验证。为此,我使用了WizardScene,这是我的实现:

const userWizard = new WizardScene('user-wizard',
    (ctx) => {
        ctx.reply("What is your name?");

        //Necessary for store the input
        ctx.scene.session.user = {};

        //Store the telegram user id
        ctx.scene.session.user.userId = ctx.update.callback_query.from.id;
        return ctx.wizard.next();
    },
    (ctx) => {

        //Validate the name
        if (ctx.message.text.length < 1 || ctx.message.text.length > 12) {
            return ctx.reply("Name entered has an invalid length!");
        }

        //Store the entered name
        ctx.scene.session.user.name = ctx.message.text;
        ctx.reply("What is your last name?");
        return ctx.wizard.next();
    },
    async (ctx) => {

        //Validate last name
        if (ctx.message.text.length > 30) {
            return ctx.reply("Last name has an invalid length");
        }

        ctx.scene.session.user.lastName = ctx.message.text;

        //Store the user in a separate controller
        await userController.StoreUser(ctx.scene.session.user);
        return ctx.scene.leave(); //<- Leaving a scene will clear the session automatically
    }
);
Run Code Online (Sandbox Code Playgroud)

注册场景

WizardScene上述需要在注册Stage,所以我们可以利用这Scene一个Middleware。这样,我们可以Scene在单独的类或模块中访问:

const stage = new Stage([userWizard]);
stage.command('cancel', (ctx) => {
    ctx.reply("Operation canceled");
    return ctx.scene.leave();
});
bot.use(stage.middleware())
Run Code Online (Sandbox Code Playgroud)

我也告诉给了Stage离开Scene,如果/cancel命令reiceved,因此如果用户想取消操作,打字/cancel是这样的。

开始一个场景

现在,在向导中输入您可以执行以下操作:

await ctx.scene.enter('user-wizard');
Run Code Online (Sandbox Code Playgroud)

因此,基本上,您已经在应用程序的中Scene注册了中间件context,并且您需要输入.enter您的ID Scene(在我的情况下)user-wizard

这将启动向导。

我希望通过更多示例来增强文档功能,因为我发现这很难实现和理解,特别是对我来说,我是新手TelegrafJS

亲切的问候。