Search code examples
pythontwiliowatchdogpython-watchdog

Python Twilio/Watchguard script sending 2 messages rather than the 1 expected


I've written this script to send an SMS to myself when the file results.txt is modified. It sends the contents of the file in a text to my phone (i've changed the numbers in the question). It works, apart from the fact that I receive two identical SMS messages per modification and I can't for the life of me work out why.

import time
import sys, os
from twilio.rest import Client
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler


class MyHandler(PatternMatchingEventHandler):
        patterns = ["./results.txt"]

        def process(self, event):
                with open('results.txt', 'r') as myfile:
                        newtweet=myfile.read().replace('\n', '')
                        client = Client("ACac14lkjdchlkdhfdhb448d175335fbd8", "hduhdhdhddhidh39837382783232")
                        client.messages.create(from_="+44145698039",
                        to="+44778974188",
                        body=newtweet)


        def on_modified(self, event):
                self.process(event)



if __name__ == '__main__':
    args = sys.argv[1:]
    observer = Observer()
    observer.schedule(MyHandler(), path=args[0] if args else '.')
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()

    observer.join()

EDIT**

here is the file that's writing to results.txt:

class MyStreamListener(tweepy.StreamListener):

        def on_status(self, status):
                text = status.text
                name = status.user.screen_name
                uid = status.user.id
                print (text)
                print (uid, text, name, file=open("results.txt", "w"))

        def on_error(self, status_code):
                if status_code == 420:
                        return False

myStreamListener = MyStreamListener()
users = ['22776208', '2845678578']
stream = tweepy.Stream(auth = api.auth, listener=myStreamListener, include_entities=True)
stream.filter(follow=users, languages=["en"])
keywords = ["Trump"]
stream.filter(track=keywords, languages=["en"])

Solution

  • Twilio developer evangelist here.

    I believe, from reading this question, that when you call file.open you will cause a modified event and then when you write to the file you also cause the event to fire. Thus, you are sending two messages because the change event is fired twice.

    Rather than open the file every time you want to write to it, why not save a reference to the file that is ready to be written to and write to the same reference every time.

    Something like:

    class MyStreamListener(tweepy.StreamListener):
    
        def __init__(self, file):
                self.file = file
                super().__init__()
    
        def on_status(self, status):
                text = status.text
                name = status.user.screen_name
                uid = status.user.id
                print (text)
                print (uid, text, name, self.file)
    
        def on_error(self, status_code):
                if status_code == 420:
                        return False
    
    myStreamListener = MyStreamListener(file=open("results.txt", "w"))
    

    (Excuse me if that doesn't work exactly, my Python is not superb, but hopefully you get the idea, pass an open file object into your listener and use it, rather than opening the file each time.)