Телеграм бот на Python - как реализовать одновременное общение с разными пользователями

Создаю бот с такой логикой:

  • бот задает пользователю несколько вопросов
  • записывает ответ в единое текстовое сообщение
  • пересылает мне сообщение в отдельный чат в телеграм

Проблема: при одновременных ответах нескольких пользователей, информация перемешивается. Те может быть ответ на вопрос 1 пользователя, потом сразу другого, ответ на вопрос 2 первого и тд.

bot = telebot.TeleBot(TOKEN)  
def klava(kuda, n_knopok, name_knopok, name_calldata, opisanie):  
        keyboard = types.InlineKeyboardMarkup()            
        for i in range(n_knopok):    
           i_button = types.InlineKeyboardButton(text=name_knopok[i],  
 callback_data=name_calldata[i])  
           keyboard.add(i_button)  
        bot.send_message(kuda, opisanie,reply_markup=keyboard)  
infa = 'Анкета_'  
@bot.message_handler(commands=['start'])  
def send_welcome(message):          
    klava(message.chat.id, 2, ['Дальше', 'Не актуально'], ['next', 'stop'], 'текст вступление.')      
@bot.callback_query_handler(func=lambda call:call.data in ['next', 'stop'] )  
def callback_worker(call):        
      if call.data =='next':  
        bot.send_message(call.message.chat.id, 'Напиши, пожалуйста, свое имя и ник в телеграм')    
        bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='текст вступление')               
      elif call.data =='stop':              
        bot.send_message(call.message.chat.id, 'Мне очень жаль. Возвращайся, когда будет время. Мы будем очень рады. Отличного дня!')   
@bot.message_handler(content_types=['document'])  
def get_document_messages(message):  
    global TOKEN  
    forward_message (TOKEN, ссылка на канал, message.chat.id, message.id)  
i=1      
@bot.message_handler(content_types=['text'])   
def get_text_messages(message):  
       global infa   
       global  i    
       infa = infa + '_' +message.text  
       if message.text != 0 :      
          klava(message.chat.id, 1, ['Дальше'], [i], 'Убедись, что ответил/ла на вопрос и перейдем дальше')  
          return i  
@bot.callback_query_handler(func=lambda call: call.data in ['1', '2', '3','4'])  
def callback_worker(call):   
      global i  
      text =['вопрос 1', 'вопрос 2', 'вопрос 3']      
      bot.edit_message_text(chat_id=call.message.chat.id,  
 message_id=call.message.message_id, text='Убедись, что ответил/ла на вопрос и перейдем дальше')  
      if i<4:  
        bot.send_message(call.message.chat.id, text[i-1])   
      else:                  
        klava(call.message.chat.id, 3, ['вар1', 'вар2', 'вар3'], ['вар1', 'вар2', 'вар3'], 'вопрос 4')   
        i=0      
      i = i+1   

и тд. другие вопросы
последний вопрос:

def callback_worker(call):      
      if call.data == 'ответ1': 
            bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='Записал твой ответ')
            global infa           
            bot.send_message(call.message.chat.id,'ответ на анкету')   
            bot.send_message(ссылка на чат, infa)  
            infa = 'Анкета_'    
      elif call.data == 'ответ2':
             bot.send_message(call.message.chat.id,'негативный ответ')
             infa = infa + 'не подходит'
             bot.send_message(ссылка на чат, infa)
             infa = 'Анкета_'
bot.polling(none_stop=True)

Ответы (2 шт):

Автор решения: Vernadsky

Один из вариантов решения создать базу данных, где для каждого user'a будет своя запись и прогресс общения хранить в такой бд по user id. Рекомендую SQLAlchemy

→ Ссылка
Автор решения: DeNRuDi

Первое что нужно сделать - избавиться от глобальных переменных, да и считается их использование плохой практикой (особенно в огромных проектах).

По сути, результат одного пользователя просто перезаписывается другим потоком в одну и ту же переменную, и вот, собственно и такой результат. Решений 2:

  1. Как привел Vernadsky - использовать базу данных. Для простых проектов вполне будет достаточно и SQLite. Для каждого пользователя, скажем так, создается своя запись с колонками, куда и записывается результат. Достаточно будет познакомиться с базовыми CRUD (CREATE, READ, UPDATE, DELETE) операциями, то есть подключить базу проще, чем написать основную логику для бота:)
  2. Если не хотите вдаваться в использования баз данных, можно сделать чуть проще - использовать словарь. Ключом выступает идентификатор пользователя, а значение - то что хотите записать.

Пример:

users = {}
...
value = 'Ваше значение'
users.update({message.chat.id: value}) 

То есть у каждого пользователя есть скажем так, ячейка памяти, куда можно записать результат, и уже по надобности вами извлекать.

Или еще как вариант, можно использовать метод bot.register_next_step_handler, на просторах интернета и ruSO, полно примеров с этим методом.

→ Ссылка