Creating a multi-step conversation flow in a Telegram bot

Hey everyone! I’m working on a Telegram bot and I’ve got the basics down. I can make it respond to simple commands like this:

bot.onText(/\/hello/, (msg) => {
  bot.sendMessage(msg.chat.id, "Hi there! How can I help?");
});

But now I want to take it further. I’m trying to create a more complex conversation flow. For example, if a user types /shop, I want the bot to show a list of items. Then based on what they pick, show more options, and so on.

I’m not sure how to make the bot remember what step of the conversation we’re in. Should I use some kind of state management? Or do I need to store this info in a database?

Any tips on how to structure this kind of multi-step conversation would be super helpful. Thanks!

I’ve tackled similar challenges with my Telegram bots. For multi-step conversations, I found that using a simple state machine works wonders. Here’s what I did:

I created an object to track each user’s state, keyed by their chat ID. Something like:

const userStates = {};

Then, in my message handler, I’d check and update the state:

bot.on('message', (msg) => {
  const chatId = msg.chat.id;
  const currentState = userStates[chatId] || 'initial';

  if (currentState === 'initial' && msg.text === '/shop') {
    // Show item list
    userStates[chatId] = 'choosing_item';
  } else if (currentState === 'choosing_item') {
    // Handle item selection
    userStates[chatId] = 'checkout';
  }
  // ... and so on
});

This approach kept things simple and worked great for most of my use cases. Just remember to clear the state when the conversation ends or times out!

Implementing a state management system is essential for handling multi-step conversations. A database may be unnecessary for simple flows, so an in-memory store such as a JavaScript Map or a plain object (using the chat ID as the key) can be very effective. Begin by initializing the state for a new conversation, then update it as the user interacts with the bot. This approach maintains context without adding unwarranted complexity. Handling cases such as timeouts or unexpected input is also vital to ensure that the conversation remains robust and user-friendly.

yo, i’ve done smthing similar. u can use a simple object to track convo state. like this:

let convos = {}

bot.on('message', msg => {
  let state = convos[msg.chat.id] || 'start'
  if (state === 'start' && msg.text === '/shop') {
    // show items
    convos[msg.chat.id] = 'picking'
  }
  // handle other states
})

works great for me. good luck!