How to simulate an input or store a future response

Asked

Viewed 182 times

2

I’m making a Telegram chatbot via Python, through some lessons I’m doing, and in the middle of the process I came across a problem: I can’t in any way store the customer’s response in a variable.

class TelegramBot:
    def __init__(self):
        token = ''
        self.url_base = f'https://api.telegram.org/bot{token}/'

    def Iniciar(self):
        update_id = None
        while True:

            ##obtem novas msgs
            update = self.getMessages(update_id)

            ##define dados como a response da api
            dados = update["result"]
            
            ##se receber dados
            if dados:
                for dado in dados:
                    ##obtem o id da atual conversa
                    update_id = dado['update_id']

                    ## obtem o conteudo da msg
                    mensagem = str(dado["message"]["text"])
                    ## infos basicas
                    sobrenome = str(dado["message"]["from"]["last_name"])
                    nome = str(dado["message"]["from"]["first_name"])

                    ## obtem o chat id
                    chat_id = dado["message"]["from"]["id"]

                    ##verifica se foi a primeira msg
                    primeiraMsg = int(dado["message"]["message_id"]) == 1

                    ##verifica ql msg é
                    msgNumber = int(dado["message"]["message_id"])      

                
                    ## a cada mensagem gera uma resposta 
                    # resposta = self.criar_resposta(saldo, mensagem, primeiraMsg, nome, sobrenome)
                    # self.responder(resposta, chat_id)
            
            if mensagem == '1':
                opcao = msgNumber
                self.responder(f'''Digite o sinal para aposta única no seguinte formato: (exemplo) EURUSD|15:00|M5|PUT|20{os.linesep}Ou seja: ATIVO|HORA|MINUTAGEM|PUT OU CALL|VALOR''', chat_id)
            
            if mensagem == '2':
                opcao = msgNumber
                self.responder(f'''Carregue sua lista formatada''', chat_id)
            
            if opcao == msgNumber + 2:
                apostaResposta = mensagem 
                print(f'''{apostaResposta} essa é a aposta''')

    def getMessages(self, update_id):
      ##link da api pra obter novas atualizações
        link_requisicao = f'{self.url_base}getUpdates?timeout=100'
        ##se tiver algo novo
        if update_id:
          ##seta link requisição pra pegar o ultimo update id
            link_requisicao = f'{link_requisicao}&offset={update_id + 1}'
        resultado = requests.get(link_requisicao)
        return json.loads(resultado.content)

    # Responder
    def responder(self, resposta, chat_id):
        link_requisicao = f'{self.url_base}sendMessage?chat_id={chat_id}&text={resposta}'
        requests.get(link_requisicao)

bot = TelegramBot()
bot.Iniciar()

What I’m trying to say is that after the customer selects option 1, I’d like to store the next answer in a variable. A solution to this would be an input, if the answers were via python interpreter, I could just put something like:

if mensagem == "1":
   teste = input("INSIRA O ATIVO, SEGUIDO DO VALOR")
   apostar(teste)

Would you have a solution for that? I can simulate an input or store the next answer in a variable?

1 answer

0


The solution I found was to store all user messages in a dictionary, being each message an object.

I changed the structure of your code a little bit, but it’s basically the same thing

It’s done in class Extractdata, it stores in a dictionary Message and User objects, representing Message and User types of Telegram, for each received message will be marked with update_id of each update that occurs.

class ExtractData:
    ...

    def getData(self, update_result, lastMsg=False):
        update = self.getCurrentUpdate(update_result)
        if self.previous_update_id != self.current_update_id:
            _message_obj = self.getMessage(update)
            _message_obj.m_from = self.getUser(update)
            self.getInitialTime(_message_obj)
            data = {self.current_update_id: _message_obj}
            del _message_obj

            if lastMsg:
                self.datas = {}     # Guardará somente a última mensagem enviada ao Bot

            self.datas.update(data)
        return

Thus, in addition to being able to get the user’s answer will be possible also obtain the data that represent the user, from the update_id of updates, which will be the Message and User objects.

The method betting is where it handles user options and responses contained in self.extract_data.datas.

You can see the full code here.

Other points

From what I understand of what you wanted to do, so the attempt here is correct, but the logic is not

if opcao == msgNumber + 2:
    ...

You want to check if the message sent by the user is the answer for the option selected, then it must be checked if the id of the new message (message_id) sent by user matches the sequence.

Where message_id = id_date_message previous + 2

So it should be:

if msgNumber == opcao + 2:
    ...

And in those checks

if mensagem == '1':
    ...

if mensagem == '2':
    ...

if opcao == msgNumber + 2:
    ...

data are needed that may not be found. For documentation the Telegram bots api, some of the data are optional depending on the message.

How is the case of

mensagem = str(dado["message"]["text"])

So I put a check into this case

if "text" not in mensagem.getAttribsList(): # Verifica se a mensagem tem o atributo text
    return 

Since the extracted data will have what you found, which may be the type photo instead of text.

  • Man, thank you so much! You explained clearly and organized the code in a simple way, I was able to understand most even not having much experience in Python. I could understand the logic of how you did, was exceptional! Congratulations!

  • I know it’s too much to ask, but a new question has arisen. The ways in which the answers to option 1 and 2 will be dealt with are different. Regarding the post treatment of options, I have everything ready, what left me in doubt is how to reference two different answers. I thought I’d try something like: if mensagem.message_id == self.opcao + 2 and mensagem.text == 1: treat answer 1 if mensagem.message_id == self.opcao + 2 and mensagem.text == 2: treat answer 1

  • @Dashadelas You can try to store the options numbers and the message_id in a dictionary. Then, check if the user is choosing an option or sending his reply. If he is choosing an option, fill in the dictionary, e.g.: {opc_1:message_id, opc_2:message_id}, if not, checks if it is an answer (as before) and also if it matches the expected type (ex formatted list) for the option, then does something and then reset the message_id of the dictionary. It is better to do a function for each case.

  • I understand what you mean, but the ways of treating different are not between an option vs response, but option number 1 vs option number 2.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.