def stream_tweets(selected_tweets: PriorityQueue, api: tweepy.API, auth: tweepy.OAuthHandler) -> None: config = Config() if not config.TRACKS: config.TRACKS = {'twitter': 0.9} logging.warning('starting config:' + '\nretweet interval: ' + str(config.RETWEET_INTERVAL) + '\nsave_tweets: ' + str(config.SAVE_TWEETS) + '\nsave_tweets_path: ' + config.SAVE_TWEETS_PATH + '\ntracks: ' + " ".join(config.TRACKS.keys())) try: tweet_selector = GreedySelector(api, config.TRACKS, config.FILTER_WORDS, config.BLACK_LIST) storage_handler = None if config.SAVE_TWEETS: storage_handler = JsonStorageHandler(config.SAVE_TWEETS_PATH) listener = TweetListener(selected_tweets, tweet_selector, storage_handler) stream = tweepy.Stream(auth=auth, listener=listener) # starting stream tracks: list = list(config.TRACKS.keys()) stream.filter(track=tracks[config.START_INDEX:], languages=config.LANGUAGES) except Exception: logging.error("Unexpected error: " + str(sys.exc_info()) + "\n" + traceback.format_exc())
def main(): # load configs from file with open('config.json', 'r', encoding="utf-8") as file: config = Config(file) selected_tweets = PriorityQueue() auth = authenticate_1(config.CONSUMER_KEY, config.CONSUMER_SECRET, config.TOKEN_KEY, config.TOKEN_SECRET) api = tweepy.API(auth) stream_scheduler.add_job(stream_tweets, args=[selected_tweets, api, config, auth], coalesce=True, trigger='interval', minutes=30, misfire_grace_time=200, max_instances=1, name='stream_scheduler', next_run_time=datetime.now(), id='stream_scheduler') stream_scheduler.start() # scheduler to call retweet_function in intervals retweet_scheduler.add_job(retweet_function, args=[selected_tweets, api, config.TELEGRAM, config.TELEGRAM_BOT_TOKEN, config.TELEGRAM_CHANNEL_ID], trigger='interval', minutes=config.RETWEET_INTERVAL, misfire_grace_time=15, max_instances=1, name='retweet_scheduler', id='retweet_scheduler') retweet_scheduler.start() # registering interrupt handler signal.signal(signal.SIGINT, keyboard_interrupt_handler) # apscheduler mostly used in web server application, it can't start a job when the main thread is terminated # so this infinit loop will keep the main thread running # todo: find a better way(suggestion: port hole bot to flask or django and create an gui as well) while True: time.sleep(10)
def retweet_function(selected_tweets, api): succeeded = False config = Config() while True: try: if selected_tweets.qsize() == 0: break wrapper: StatusRateWrapper = selected_tweets.get(block=False) logging.info('retweeting message with rating(' + str(wrapper.rate * -1) + '): ' + str(wrapper.status.id)) api.retweet(wrapper.status.id) succeeded = True break except tweepy.error.TweepError: logging.info('You have already retweeted this Tweet.') if config.TELEGRAM and succeeded: try: Telegram.post_tweet_link(wrapper.status, config.TELEGRAM_BOT_TOKEN, config.TELEGRAM_CHANNEL_ID) except Exception: logging.error("Can't post on telegram")
def handle_tweets(self): status: tweepy.Status = self.fifo.get() rating: float = self.selector.rate_tweet( status) # get rating from selector # share tweet to voting channel config = Config() if config.TELEGRAM_BOT_TOKEN != '' and config.TELEGRAM_VOTE_CHANNEL_ID != '' and self.tweet_counter % config.VOTE_SKIP_FACTOR == 0: Telegram.post_tweet_link(status, config.TELEGRAM_BOT_TOKEN, config.TELEGRAM_VOTE_CHANNEL_ID) Telegram.send_poll(status.id_str, config.TELEGRAM_BOT_TOKEN, config.TELEGRAM_VOTE_CHANNEL_ID, ['funny', 'useful', 'offensive']) # put tweets on queue for main telegram channel and twitter if rating > 0.6: # only add tweets with rating above 0.6 wrapper = StatusRateWrapper() wrapper.status = status wrapper.rate = -1 * rating # (-1 * rating) because python PQ uses min-heap(min value will pop first) self.queue.put(wrapper) if self.storage_handler is not None: self.storage_handler.store_tweet(status) # save tweets
class RequestsHandler(logging.Handler): def __init__(self, telegram_token, telegram_chat_id): super().__init__() self.TELEGRAM_TOKEN = telegram_token self.TELEGRAM_CHAT_ID = telegram_chat_id def emit(self, record): log_entry = self.format(record) payload = { 'chat_id': self.TELEGRAM_CHAT_ID, 'text': log_entry, 'parse_mode': 'HTML' } return requests.post( "https://api.telegram.org/bot{token}/sendMessage".format( token=self.TELEGRAM_TOKEN), data=payload).content # load configs from file with open('config.json', 'r', encoding="utf-8") as file: config = Config(file) if config.TELEGRAM_BOT_TOKEN != '' and config.TELEGRAM_LOG_CHAT_ID != '': telegram = RequestsHandler(config.TELEGRAM_BOT_TOKEN, config.TELEGRAM_LOG_CHAT_ID) telegram.setFormatter(formatter) logging.root.addHandler(telegram) logging.root.setLevel(logging.WARNING)