0

I am implementing a Twitter bot for fun purposes using Tweepy.

What I am trying to code is a bot that tracks a certain keyword and based in it the bot replies the user that tweeted with the given string.

I considered storing the Twitter's Stream on a .json file and looping the Tweet object for every user but it seems impractical as receiving the stream locks the program on a loop.

So, how could I track the tweets with the Twitter's Stream API based on a certain keyword and reply the users that tweeted it?

Current code:

    from tweepy import OAuthHandler
    from tweepy import Stream
    from tweepy.streaming import StreamListener

class MyListener(StreamListener):
    def on_data(self, data):
        try:
            with open("caguei.json", 'a+') as f:
                f.write(data)
                data = f.readline()
                    tweet = json.loads(data)
                    text = str("@%s acabou de. %s " % (tweet['user']['screen_name'], random.choice(exp)))
                    tweepy.API.update_status(status=text, in_reply_to_status_id=tweet['user']['id'])
                #time.sleep(300)
                return True
        except BaseException as e:
            print("Error on_data: %s" % str(e))
        return True
    def on_error(self, status):
        print(status)
        return True

    api = tweepy.API(auth)
    twitter_stream = Stream(auth, MyListener())

    twitter_stream.filter(track=['dengue']) #Executing it the program locks on a loop
ovrwngtvity
  • 4,261
  • 3
  • 15
  • 20
  • 1
    Can't you simply do that in the *on_data* function of you *MyListener* ? – SpiXel Sep 16 '16 at 17:01
  • @SpiXel not sure how to use the API correctly. I do not have much experience in API's – ovrwngtvity Sep 16 '16 at 17:10
  • @SpiXel Oh, I think I managed to understand. The method on_data runs while receiving the Twitter's stream. I thought it was just a random name. I think I can accomplish what I am intended. – ovrwngtvity Sep 16 '16 at 17:14
  • @SpiXel Not yet! I understood the logic but I am facing another problem. While writing the data received and trying to read it immediately from the json file I receive the error "No JSON object could be decoded". What is wrong? I can read the same json file in another script but on the on_data method it seems I can't. I updated the code. – ovrwngtvity Sep 16 '16 at 17:53
  • 1
    Check that caguei.json does not already contain anything. Since you're opening the file with "a+", you might be reading something totally different than what you intend to read with *f.readline()*. Also it's probably wrong and not what you want. Since on each input, you're a opening the file, appending the new data to the end of it (a+ mode), But reading the same old first line again and again. It's probably not what you intend. – SpiXel Sep 16 '16 at 18:06
  • @SpiXel Managed. I think it was empty, not sure. It is know working. I just need to verify how to reply a tweet. I used the parameter in_reply_to_status_id=tweet['user']['id'] that is the id of the tweet but it is nit replying.. – ovrwngtvity Sep 16 '16 at 18:11
  • 1
    For that, check this question out: http://stackoverflow.com/questions/9322465/reply-to-tweet-with-tweepy-python – SpiXel Sep 16 '16 at 18:15
  • @SpiXel Done. Everything working perfectly. Thanks! – ovrwngtvity Sep 16 '16 at 18:21
  • Sure, Glad it helped. – SpiXel Sep 16 '16 at 18:22

1 Answers1

1

Tweepy StreamListener class allows you to override it's on_data method. That's where you should be doing your logic.

As per the code

class StreamListener(object):

    ... 

    def on_data(self, raw_data):
        """Called when raw data is received from connection.

        Override this method if you wish to manually handle
        the stream data. Return False to stop stream and close connection.
        """
        ...

So in your listener, you can override this method and do your custom logic.

class MyListener(StreamListener):

    def on_data(self, data):

         do_whatever_with_data(data)

You can also override several other methods (on_direct_message, etc) and I encourage you to take a look at the code of StreamListener.

Update

Okay, you can do what you intent to do with the following:

class MyListener(StreamListener):

    def __init__(self, *args, **kwargs):
        super(MyListener, self).__init__(*args, **kwargs)
        self.file = open("whatever.json", "a+")

    def _persist_to_file(self, data):
        try:
            self.file.write(data)
        except BaseException:
            pass

    def on_data(self, data):
        try:
            tweet = json.loads(data)
            text = str("@%s acabou de. %s " % (tweet['user']['screen_name'], random.choice(exp)))
            tweepy.API.update_status(status=text, in_reply_to_status_id=tweet['user']['id'])
            self._persist_to_file(data)
            return True
        except BaseException as e:
            print("Error on_data: %s" % str(e))
        return True

    def on_error(self, status):
        print(status)
        return True
SpiXel
  • 4,338
  • 1
  • 29
  • 45