Python Forum
Why does 'if' block run twice
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Why does 'if' block run twice
#1
Hello,

I am trying to understand why the if block in the code below is running twice. When the block based on pattern1 gets triggered, it sends the reply twice and sets two at jobs. When the block with pattern2 runs, it replies once, sets one at job, and then runs the else block, sending the "ooops" message.

It seems like it is somehow running like a loop, which I don't understand. I tried de-nesting the if block so that it was all one block, but that did not change the output behavior. And, it is especially confusing that the pattern1 if block runs twice, but the pattern2 if block runs once and then the else block runs. Where in the code am I passing two parameters???

The only hint I can think of is that, for some reason the match = pattern1.findall.... variable ends up as a tuple. My work around was to pull the tuple apart, and then pass the 0th member of the tuple to the message handler and at command. This was a workaround that...worked, but, I still don't get why the using the findall method on the string contained in message['content'] results in a tuple in the first place....so maybe the tuple thing is the reason why the if blocks run twice, once for each member of the tuple???

from typing import Any, Dict
import  re
from datetime import datetime
from crontab import CronTab
import os
import subprocess


# Current plan is to have the user send snoozebot a message
# containing the desired interval for a reminder (like 4 days).
# Then snoozebot sets a cron job. Cron then calls a python script,
# ping.py with parameters for the send_message function in the Rest
# API. This is a POST https: request to POST https://yourZulipDomain.zulipchat.com/api/v1/messages
# I am thinking the datetime module might be useful for calculating the required
# inputs for the chron job.  




#Todos: 
# 1) Figure out what the incoming web hook needs to be to have
#    snoozebot send the reminder.
# 2) figure out how to have snoozebot start the cron job
# 3) I'm thinking I am going to need a function in snoozebot
# to handle the incoming web hook from crontab





class SnoozeBotHandler:


    def usage(self) -> str:
        return '''
        Snoozebot is a reminder tool that will message you at your requested time in the future. Currently, Snoozebot
        accepts the format '# time', as in '2 minutes.' With this format, Snoozebot is using the 'now +# time' syntax
        for the At command. If that means nothing to you, no worries, here is an example of what you would type in a 
        zulip reply: @**snoozebot** 4 days
        What that means is, snoozebot, message/mention me in this thread 4 days from this moment.
        In the future, specific date + time formatting will be implemented, such as: @**snoozebot** 4:13PM on 12/01/2027.
        If you have any questions or feedback, please PM me on Zulip Community Chat. -- MLH 
        '''

    def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None:
        # setting up regex pattern here
        # hopefully this pattern object will work for any iteration of "snooze for x days/weeks/months...will have to test.
        pattern1 = re.compile(r'(\b\d+\s(minute|hour|day|week|month|year)s?)', re.IGNORECASE)
        pattern2 = re.compile(r'(\b\d{1,2}:\d{2}\s?(AM|PM|am|pm)\s?(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday|tomorrow))', re.IGNORECASE)
        #pattern3 will be specific date + time
        match = pattern1.findall(message['content'])
        match2 = pattern2.findall(message['content'])
        stream_id = message['stream_id']
        topic = message['subject']
        user = message['sender_full_name']
        heredoc = f"""END 
                   zulip-send --stream {stream_id} --subject {topic} --message 'Ping! @**{user}**' --config-file ~/python-zulip-api/zulip_bots/zulip_bots/bots/snoozebot/zuliprc 
                   END"""
        
        # Setting up At command (pipe method)
        # zulip_send_command = zulip-send %(stream name) %(message name) %(message)
        # at_command = " %(zulip_send) | at %(time_input)"
			
        
        #setting up the crontab variables here, but realized that At is the right tool, not crontab
        #cron = CronTab(user='root')
        
        
        # message handling
        if message['content'] == '':
            bot_response = "Please specify the **snooze interval**, such as '4 days'. For help, message me with 'help.'"
            bot_handler.send_reply(message, bot_response)
        elif message['content'] == 'help':
            bot_handler.send_reply(message, self.usage())
        else:
            if pattern1.search(message['content']) != None:
            
                x = match[0]
                y = str(x[0])
                z = "Ok, I'll remind you in " + y
                # print(message)
                # print(message['stream_id'])
                #print(x[0])
                #print(y)
                #print(match)
                #print(match[0])
                #print(pattern1.search(message[content])
                #y.join(x)
                #print(y)
                bot_handler.send_reply(message, z)
                # This is where the At job will be called.
                os.system("at now +%s << %s" %(y, heredoc))                
                # Decided to use At instead of cron. keeping just in case
                # job = cron.new(command='echo hello_word')
                # job.minute.every(5)
                # cron.write() 
                emoji_name = 'alarm clock'
                bot_handler.react(message, emoji_name)
            elif pattern2.search(message['content']) != None:
                # print(pattern2.search(message['content'])
                print(message['content'])
                l = match2[0]
                m = str(l[0])
                n = "Ok, I'll remind you at " + m
                bot_handler.send_reply(message, n)
                os.system("at %s << %s" %(m, heredoc))  

            else: 
                bot_handler.send_reply(message, "Oops, that won't work. Message me with 'help' for help on how to use me.")
        return 

handler_class = SnoozeBotHandler
Reply
#2
My first thought might be that
message['content']
contains two results for pattern1, where pattern2 does not. And for all i know bot_handler.send_reply and bot_handler.react could be interpreting it incorrectly. You are sending message to them but regex'ing message['content'] not message.

What is all of message in both cases? Because i know in IRC a message is a lot more content than just what the person wrote. These have to be parsed out. On rare occurrence if it is not parsed out properly, you can have a duplicate or false positive.
Recommended Tutorials:
Reply
#3
Thanks Metulburr,

First, it seems like I accidentally set up two usernames for this forum!!! I'll stick to this one from now on....

Anyhow, I think the answer may lie here: https://stackoverflow.com/questions/2459...ins-one-gr

It seems like the way I set up the findall method results in the creation of the tuple, which may be why my if statements are getting evaluated twice (and only twice). I'll try fixing those later today to see if it solves the output problem.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020