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
.