Skip to content
Advertisement

Twitter reply-to-mentions bot programmed in Python works once and then crashes with error 400: what is the problem?

I´ve been building a bot and it works exactly as intended, but only for one Tweet. Then, it waits 60 seconds, and, if it doesn´t find a new Tweet to reply to (since it´s configured to reply to the most recent Tweet), it throws an error (it´s 400 as in “400: Bad Authentication Data”, but I think the issue is not that, since the bot posts on Twitter once without any issues. However, I do think it´s possibly some kind of Bad Request error). Whenever it crashes, I can just run in my command “python (botname).py” and it works once if there is now a new Tweet, but then, it crashes again. I want the bot to run properly by itself, so I would really appreciate some help! This is the code in my file:

#!/usr/bin/env python
# tweepy-bots/bots/autoreply.py


import tweepy
import logging
from config import create_api
import time
import re
from googlesearch import search
import sys
import io


logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()


def check_mentions(api, since_id):

    logger.info("Collecting info")

    new_since_id = since_id

    for tweet in tweepy.Cursor(api.mentions_timeline,
        since_id=since_id).items():

        new_since_id = max(tweet.id, new_since_id)


        if tweet.in_reply_to_status_id is not None:
            in_reply_to_status_id = tweet.id
            status_id = tweet.in_reply_to_status_id
            tweet_u = api.get_status(status_id,tweet_mode='extended')

        logger.info(f"Answering to {tweet.user.name}")
        

        # remove words between 1 and 3
        shortword = re.compile(r'W*bw{1,3}b')

        keywords_search = str(shortword.sub('', tweet_u.full_text))

        print(keywords_search)

        if keywords_search is not None:

                mystring = search(keywords_search, num_results=500)
        else:
                mystring = search("error", num_results=1)

        print(mystring)

        output_info=[]
        for word in mystring:
                if "harvard" in word or "cornell" in word or "researchgate" in word or "yale" in word or "rutgers" in word or "caltech" in word or "upenn" in word or "princeton" in word or "columbia" in word or "journal" in word or "mit" in word or "stanford" in word or "gov" in word or "pubmed" in word or "theguardian" in word or "aaas" in word or "bbc" in word or "rice" in word or "ams" in word or "sciencemag" in word or "research" in word or "article" in word or "publication" in word or "nationalgeographic" in word or "ngenes" in word:
                                output_info.append(word)
                                infostringa = ' '.join(output_info)


        if output_info:
                output_info4 = output_info[:5]
                infostring = ' '.join(output_info4)
                print(infostring)
                status = "Hi there! This may be what you're looking for " + infostring
                len(status) <= 280
                api.update_status(status, in_reply_to_status_id=tweet.id, auto_populate_reply_metadata=True)

        else:
                status = "Sorry, I cannot help you with that :(. You might want to try again with a distinctly sourced Tweet"
                api.update_status(status, in_reply_to_status_id=tweet.id, auto_populate_reply_metadata=True)

        print(status)

        return new_since_id
    return check_mentions





def main():
    api = create_api()
    since_id = 1 #the last mention you have.
    while True:
        since_id = check_mentions(api, since_id)
        logger.info("Waiting...")
        time.sleep(60)

main()

My config module:

# tweepy-bots/bots/config.py
import tweepy
import logging
import os

logger = logging.getLogger()

def create_api():
    consumer_key = os.getenv("CONSUMER_KEY")
    consumer_secret = os.getenv("CONSUMER_SECRET")
    access_token = os.getenv("ACCESS_TOKEN")
    access_token_secret = os.getenv("ACCESS_TOKEN_SECRET")

    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)
    api = tweepy.API(auth, wait_on_rate_limit=True, 
        wait_on_rate_limit_notify=True)
    try:
        api.verify_credentials()
    except Exception as e:
        logger.error("Error creating API", exc_info=True)
        raise e
    logger.info("API created")
    return api

The error raised:

Traceback (most recent call last):
  File "C:UsersmariaOneDriveDocumentosLaraPythonFactualbotbotstring32.py", line 92, in <module>
    main()
  File "C:UsersmariaOneDriveDocumentosLaraPythonFactualbotbotstring32.py", line 87, in main
    since_id = check_mentions(api, since_id)
  File "C:UsersmariaOneDriveDocumentosLaraPythonFactualbotbotstring32.py", line 26, in check_mentions
    for tweet in tweepy.Cursor(api.mentions_timeline, since_id=since_id).items():
  File "C:UsersmariaAppDataLocalPackagesPythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0LocalCachelocal-packagesPython39site-packagestweepycursor.py", line 51, in __next__
    return self.next()
  File "C:UsersmariaAppDataLocalPackagesPythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0LocalCachelocal-packagesPython39site-packagestweepycursor.py", line 243, in next
    self.current_page = self.page_iterator.next()
  File "C:UsersmariaAppDataLocalPackagesPythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0LocalCachelocal-packagesPython39site-packagestweepycursor.py", line 132, in next
    data = self.method(max_id=self.max_id, parser=RawParser(), *self.args, **self.kwargs)
  File "C:UsersmariaAppDataLocalPackagesPythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0LocalCachelocal-packagesPython39site-packagestweepybinder.py", line 253, in _call
    return method.execute()
  File "C:UsersmariaAppDataLocalPackagesPythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0LocalCachelocal-packagesPython39site-packagestweepybinder.py", line 234, in execute
    raise TweepError(error_msg, resp, api_code=api_error_code)
tweepy.error.TweepError: Twitter error response: status code = 400

Thank you really much!

Advertisement

Answer

A 400 HTTP error status code usually means Bad Request, which is likely the case here. When there’s not a new Tweet to reply to, the for loop isn’t entered, and check_mentions, the function itself, is returned. You then set it as since_id when its returned and use it as an ID the next time check_mentions is called. This probably ends up passing something like "<function check_mentions at 0x0000028E6C729040>" to the API as since_id.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement