skip to Main Content

I’m writing a Twitter bot using Tweepy to retweet the tweets that have specific keywords.

Using the method is_not_a_reply, I tried to retweet only the tweets that are not a reply to another tweet. It works correctly almost 99% of the time, but rarely are some replies still retweeted.

I really don’t know what’s wrong with my code!!!

import os
import tweepy
from dotenv import load_dotenv

# take environment variables from .env.
load_dotenv()

# get environment variables for Twitter API
consumer_key = os.environ.get("CONSUMER_KEY")
consumer_secret = os.environ.get("CONSUMER_SECRET")
access_token = os.environ.get("ACCESS_TOKEN")
access_token_secret = os.environ.get("ACCESS_TOKEN_SECRET")


def twitter_api_authenticate():
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)
    return tweepy.API(auth, wait_on_rate_limit=True)


class MyStream(tweepy.Stream):
    def __init__(
        self, consumer_key, consumer_secret, access_token, access_token_secret
    ):
        super().__init__(
            consumer_key, consumer_secret, access_token, access_token_secret
        )
        self.twitterApi = twitter_api_authenticate()

    # when a new tweet is posted on Twitter with my filtered keywords
    def on_status(self, status):

        # If the found tweet is not a reply to another tweet
        if self.is_not_a_reply(status):

            # Retweet the found tweet (status)
            self.retweet(status)
            # Like the found tweet (status)
            self.like(status)

    def retweet(self, status):
        # Retweet the tweet
        self.twitterApi.retweet(status.id)

    def like(self, status):
        # Like the tweet
        self.twitterApi.create_favorite(status.id)

    def is_not_a_reply(self, status):
        if status.in_reply_to_status_id == None:
            return True
        else:
            return False


if __name__ == "__main__":

    trackList = ["Keyword1", "Keyword2"]

    stream = MyStream(
        consumer_key, consumer_secret, access_token, access_token_secret
    )
    stream.filter(track=trackList, languages=["fa"])

Tweepy version: 4.1.0
Python version: 3.8.10

2

Answers


  1. Chosen as BEST ANSWER

    I found my mistake. The unwanted tweets are not replies themselves but retweets of a reply!

    This was due to my poor understanding of the tweet object in Twitter API. In the Twitter API the retweet of a reply is not considered a reply itself.

    So I must first check whether the filtered tweet is a "retweet" or not and then check whether it is a "reply" or not.

    According to the point rv.kvetch mentioned in his answer, I modified the is_not_a_reply method as follows:

        def is_not_a_reply(self, status):
            if hasattr(status, "retweeted_status"):
                # Check the original tweet if it was a retweet
                originalStatus = self.twitterApi.get_status(id=status.retweeted_status.id)
                return not originalStatus.in_reply_to_status_id
            else:
                # Check the tweet itself
                return not status.in_reply_to_status_id
    

  2. I’m not entirely sure what the problem is, but you can always try to simplify the logic in the is_not_a_reply method. For debugging, I’d also suggest logging the status object and the in_reply_to_status_id attribute for example.

    def is_not_a_reply(self, status):
        return not status.in_reply_to_status_id
    

    Note that in the original version, you were doing a == comparison with None, but if you use an IDE it’ll suggest having it like is and is not, because that’s the ideal way to do comparisons with None or a boolean. In this case I’ve just updated it to handle any "falsy" value like a 0 value or an empty list – again, it all depends on what the type of
    in_reply_to_status_id is here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search