6

I'm programming a telegram bot in Python using the Telegram bot API. I'm facing the problem of managing questions that need an answer of the user. The problem arises when the program is waiting for an answer of one user and another user request information or ask another question before the first user responds.

The Telegram API uses a code to handle the request. When you ask for updates you include a code. If the code you send is higher than a request code, it is mark as handled and telegram delete it and no longer appears in the updates. This code is sequential, so if you mark update 3 as handled, updates 1 and 2 are erased as well.

The question is why is the best phytonic/elegant way to handle multiple requests that needs an answer for the users?

2 Answers 2

10

There is not a most pythonic way of doing this. It is a problem you have to program to solve.

Basically, you have to maintain some state variables concerning each user. When a new message arrives, the bot checks what state that user is in, and responds accordingly.

Suppose you have a function, handle(msg), that gets called for each arriving message:

user_states = {}

def handle(msg):
    chat_id = msg['chat']['id']

    if chat_id not in user_states:
        user_states[chat_id] = some initial state ...

    state = user_states[chat_id]

    # respond according to `state`

This will do for a simple program.

For more complicated situations, I recommend using telepot, a Python framework I have created for Telegram Bot API. It has features that specifically solve this kind of problems.

For example, below is a bot that counts how many messages have been sent by an individual user. If no message is received after 10 seconds, it starts over (timeout). The counting is done per chat - that's the important point.

import sys
import telepot
from telepot.delegate import per_chat_id, create_open

class MessageCounter(telepot.helper.ChatHandler):
    def __init__(self, seed_tuple, timeout):
        super(MessageCounter, self).__init__(seed_tuple, timeout)
        self._count = 0

    def on_message(self, msg):
        self._count += 1
        self.sender.sendMessage(self._count)

TOKEN = sys.argv[1]  # get token from command-line

bot = telepot.DelegatorBot(TOKEN, [
    (per_chat_id(), create_open(MessageCounter, timeout=10)),
])
bot.notifyOnMessage(run_forever=True)

Run the program by:

python messagecounter.py <token>

Go to the project page to learn more if you are interested. There are a lot of documentations and non-trivial examples.

Sign up to request clarification or add additional context in comments.

3 Comments

Wow, thank you so much! There is a chance to collaborate in your project? Things to do? Bugs and issues? Thank you in advance!
Thank you. The best way to help me is to let me know what you need that is not in the library, or any bugs. Another best way to help me is to spread the words about telepot. I truly believe it can ease the development of Telegram bots. The third best way is to use telepot in your own work. That is the whole point of publishing a library. Thank you, again.
The fourth way to help me is to make my answer your accepted answer, if you don't mind. Thank you.
1

In my bots I use webhooking. If you can to use web hooks - do it, it's more comfortable way to interactive with telegram bots.

If you can't webhooking (ssl problems, for example), there is workaround for you. Use ForceReply in order to get previous bot answer and write logic based on user replies.

Check if update contains reply (reply_to_message key), then make bot answer based on this reply. These actions must be asynchronous in order to get high bot performance.

If you are python programmer, I recommend Tornado for these purposes.

1 Comment

That's interesting. Although your method is suitable , I find a little messy when for example multiple user's must reply to a bot question. I think there is some work around to manage this problem without killing other user's question. But that's only my hope.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.