NodeJS 在Telegraf.js中强制更改另一个用户的场景

s5a0g9ez  于 11个月前  发布在  Node.js
关注(0)|答案(2)|浏览(93)

我正在创建游戏机器人,用户应该回答一些问题,管理员应该批准或拒绝他们。我需要找到一种方法,当管理员接受答案时,强制改变用户的场景。
例如用户在场景“回答”。当用户发送消息时,它发送给管理员

const gameButtons = [
  [
    { text: `✅ approve`, callback_data: `gTo:appG/uId=${ctx.state.userId}` }, 
    { text: `❌ reject`, callback_data: `gTo:rejG/uId=${ctx.state.userId}` },
  ], 
];
await ctx.telegram.sendMessage(ctx.state.chatTo, `User answer is: ${ctx.message.text}`, {
  reply_markup: JSON.stringify({ inline_keyboard: gameButtons }),
});

字符串
所以管理员收到消息,或将接受或拒绝

const approveQuestion = async ({ ctx, text }) => {
  const [, user] = text.split("/");
  const [, userId] = user.split("=");

  //somehow change users scene to answered
  await changeUserScene("winner", userId); 
  await ctx.telegram.sendMessage(userId, "It is right answer");
};


有办法做到这一点吗?

j0pj023g

j0pj023g1#

  • 编辑 *:在阅读/尝试了很多之后,基于几个github issues。只有当你拥有用户的上下文(ctx)时,你才能改变用户的场景。

获取ctx的最简单方法是将其保存,以便在与用户进行交互时使用。
请看我的测试代码,解释如下:

const { Telegraf, Scenes, session } = require('telegraf');
const { BaseScene, Stage } = Scenes;

const botToken = '859163076:gfkjsdgkaslgflalsgflgsadhjg';
const user1id  = 123456;
const user2id  = 789456;

const ctxObj = { };

// Scene 1
const scene_1 = new BaseScene('scene_1');
scene_1.enter((ctx) => {

    // Save ctx
    ctxObj[ctx.message.from.id] = ctx;
    console.log('State: ', ctxObj)
    ctx.reply('You just enetered scene_1')
});
scene_1.on('text', async (ctx) => {
    console.log('Got message in scene_1', ctx.message.text, ctx.message.from.id)

    // When receiving form user-2, force user-1 scene
    if (ctx.message.from.id === user2id) {
        if (ctxObj[user1id]) {
            ctxObj[user1id].scene.enter('scene_2');
        }
    }
});

// Scene 2
const scene_2 = new BaseScene('scene_2');
scene_2.enter((ctx) => ctx.reply('You just enetered scene_2'));
scene_2.on('text', (ctx) => {
    console.log('Got message in scene_2', ctx.message.text);
    ctx.scene.leave();
});

// Stage
const stage = new Stage([ scene_1, scene_2 ]);

// Bot
const bot = new Telegraf(botToken);
bot.use(session());
bot.use(stage.middleware());
bot.command('start', (ctx) => ctx.scene.enter('scene_1'));
bot.launch();

字符串
这两个重要部分是:

scene_1.enter((ctx) => {

    // Save ctx
    ctxObj[ctx.message.from.id] = ctx;
    console.log('State: ', ctxObj)
    ctx.reply('You just enetered scene_1')
});


这里我们保存每个用户输入scene_1时的ctx

scene_1.on('text', async (ctx) => {
    console.log('Got message in scene_1', ctx.message.text, ctx.message.from.id)

    // When receiving form user-2, force user-1 scene
    if (ctx.message.from.id === user2id) {
        if (ctxObj[user1id]) {
            ctxObj[user1id].scene.enter('scene_2');
        }
    }
});


然后,当我们收到来自scene_2中的用户的消息时,我们检查(这纯粹是为了测试)消息是否来自user_2,如果是,我们使用user_1ctx并调用scene.enter来强制他进入新场景。
这与预期的一样,如果需要,我可以放置一些2个Telegram帐户与该机器人交谈的截图。
看起来你可以在运行中创建ctx,但是如果你有能力的话,我建议你保存它。

zdwk9cvp

zdwk9cvp2#

是的,运行以下命令。插入注解以帮助

const { session } = require('telegraf')
const RedisSession = require('telegraf-session-redis')

// initialize Redis session store
const redisSession = new RedisSession({
  store: {
    host: 'localhost',
    port: 6379,
    db: 0,
  },
})

// register Redis session middleware
bot.use(session(redisSession))

// define a function to change user's scene
const changeUserScene = async (scene, userId) => {
  // update the user's session data with the new scene
  await bot.telegram.setMyCommands(userId, [{ command: '/start', description: 'Start the game' }]);
  await bot.telegram.sendMessage(userId, `You have answered the question correctly! Moving to the next stage...`);
  await bot.telegram.sendMessage(userId, `You are now in the "${scene}" scene.`);
  await bot.telegram.sendMessage(userId, `Type /start to start the next question.`);
  await bot.session.set(userId, { scene })
  await bot.session.save()
}

const approveQuestion = async ({ ctx, text }) => {
  const [, user] = text.split("/")
  const [, userId] = user.split("=")

  // change user's scene to "answered"
  await changeUserScene("answered", userId)

  // send response to admin
  await ctx.answerCbQuery("Answer approved!")
}

字符串

相关问题