diff --git a/src/catchup.py b/src/catchup.py index af8635a..b096493 100644 --- a/src/catchup.py +++ b/src/catchup.py @@ -145,10 +145,13 @@ async def get_cross_talent_tweets(queue_path): return ttweets_dict -# Return number of TalentTweets successfully posted -async def process_queue(ttweets_dict: dict) -> int: +# return False = errored or we posted at least one ttweet +# return True = we didn't post a single ttweet +async def process_queue(ttweets_dict: dict) -> bool: global PROGRAM_ARGS + WAIT_TIME = 30 ttweets_posted = 0 + errored = False if len(ttweets_dict) == 0: return ttweets_posted @@ -161,12 +164,13 @@ async def process_queue(ttweets_dict: dict) -> int: ttweet = ttweets_dict[key] if await TwAPI.instance.post_ttweet(ttweet, is_catchup=True): ttweets_posted += 1 - print('resting for 60s...') - await asyncio.sleep(60) + print(f'resting for {WAIT_TIME}s...') + await asyncio.sleep(WAIT_TIME) ttweets_dict.pop(key) # TODO: add ttweet.tweet_id to some success list except: print('Unhandled error occurred while posting tweets from queue.') + errored = True traceback.print_exc() else: if PROGRAM_ARGS.announce_catchup: @@ -180,7 +184,9 @@ async def process_queue(ttweets_dict: dict) -> int: for ttweet in ttweets_dict.values(): f.write(f'{ttweet.serialize()}\n') - return ttweets_posted + if errored or ttweets_posted > 0: + return False + return True # return True = no problems # return False = issue occurred where we couldn't post all past tweets properly @@ -195,8 +201,10 @@ async def run(program_args): queue_path = get_queue_path() if os.path.exists(queue_backup): + print('Found old backup queue! We errored in the previous run.') shutil.copyfile(queue_backup, queue_path) else: + print('Creating backup queue...') shutil.copyfile(queue_path, queue_backup) ret = None @@ -204,12 +212,17 @@ async def run(program_args): while True: ttweets_dict = await get_cross_talent_tweets(queue_path) print(f'found {len(ttweets_dict)} cross-company tweets') - if safe_to_post_tweets: - if await process_queue(ttweets_dict) == 0: - print('Posted no new tweets; we\'re caught up!') - os.remove(queue_backup) # keep updated queue - return True - else: - print('Tweets were not retrieved cleanly.') - os.remove(queue_path) # keep backup queue + try: + if safe_to_post_tweets: + os.remove(queue_backup) # keep updated queue + if await process_queue(ttweets_dict): + print('Posted no new tweets; we\'re caught up!') + return True + else: + print('Tweets were not retrieved cleanly.') + # os.remove(queue_path) # keep backup queue + return False + except: + print('Unhandled error occurred while running catch up in posting phase.') + traceback.print_exc() return False \ No newline at end of file diff --git a/src/listen.py b/src/listen.py index 667246e..fcec95f 100644 --- a/src/listen.py +++ b/src/listen.py @@ -1,6 +1,7 @@ ## The bot's listen mode # Continuously listen for cross-company interactions. +import asyncio import tweepy from talenttweet import TalentTweet @@ -8,11 +9,11 @@ from twapi import TwAPI import api_secrets import talent_lists as tl -async def on_response(resp): +def on_response(resp): print(resp) print(resp.data) ttweet = TalentTweet.create_from_v2api_response(resp) - await TwAPI.instance.post_ttweet(ttweet) + asyncio.run(TwAPI.instance.post_ttweet(ttweet)) def run(): sc = tweepy.StreamingClient(api_secrets.bearer_token()) diff --git a/src/twapi.py b/src/twapi.py index 60198ce..1d3810d 100644 --- a/src/twapi.py +++ b/src/twapi.py @@ -150,15 +150,15 @@ class TwAPI: await asyncio.sleep(wait_for) return await self.get_tweet_response(id, attempt=attempt+1) - async def post_tweet(self, text='', media_id=None, reply_to_tweet: int=None): + async def post_tweet(self, text='', media_ids: list=None, reply_to_tweet: int=None): try: - tweet = self.client.create_tweet(text=text, media_ids=None if media_id == None else [media_id], in_reply_to_tweet_id=reply_to_tweet) + tweet = self.client.create_tweet(text=text, media_ids=None if media_ids == None else media_ids, in_reply_to_tweet_id=reply_to_tweet) return tweet except tweepy.TooManyRequests as e: wait_for = float(e.response.headers["x-rate-limit-reset"]) - datetime.datetime.now().timestamp() + 1 print(f'\thit rate limit -- attempting to create Tweet again in {wait_for} seconds...') await asyncio.sleep(wait_for) - return await self.post_tweet(text=text, media_id=media_id, reply_to_tweet=reply_to_tweet) + return await self.post_tweet(text=text, media_ids=media_ids, reply_to_tweet=reply_to_tweet) async def get_ttweet_image_media_id(self, ttweet): img = await util.create_ttweet_image(ttweet) @@ -218,9 +218,12 @@ class TwAPI: twt_resp = await self.post_tweet(text) twt_id = twt_resp.data['id'] print('creating reply img') - media_id = await self.get_ttweet_image_media_id(ttweet) + media_ids = [await self.get_ttweet_image_media_id(ttweet)] + # if ttweet.reply_to is not None: + # re_ttweet = tt.TalentTweet(tweet_id=ttweet.reply_to, author_id=) + # media_ids.insert(0, await self.get_ttweet_image_media_id()) print('posting reply tweet') - await self.post_tweet(reply_to_tweet=twt_id, media_id=media_id,) + await self.post_tweet(reply_to_tweet=twt_id, media_ids=media_ids,) print('successfully posted ttweet!') return True except tweepy.Forbidden as e: diff --git a/src/util.py b/src/util.py index cb0108a..9e4ac63 100644 --- a/src/util.py +++ b/src/util.py @@ -59,9 +59,12 @@ async def create_ttweet_image(ttweet): print(f'successfully saved {img}') return img +def get_tweet_url(id, username): + return f'https://twitter.com/{username}/status/{id}' + def ttweet_to_url(ttweet): - username = get_username_online(ttweet.author_id) - return f'https://twitter.com/{username}/status/{ttweet.tweet_id}' + username = get_username(ttweet.author_id) + return get_tweet_url(ttweet.tweet_id, username) def get_username_local(id): return talent_lists.talents.get(id, f'{id}') @@ -90,13 +93,14 @@ def get_username_online(id, default=None): except: print(f'Unhandled error retrieving username for {id}!') traceback.print_exc() - return str(default) if default is not None else f'{id}' + return str(default) if default is not None else f'id:{id}' ## Attempt to pull username from local; pull from online if doesn't exist. def get_username(id): ret = talent_lists.talents.get(id, None) if ret == None: return get_username_online(id) + return ret def get_user_id_local(username) -> int: talent_usernames = list(talent_lists.talents.values())