Пример #1
0
def ll2_api_call(data_dir: str, scheduler: BackgroundScheduler,
                 bot_username: str, bot: 'telegram.bot.Bot'):
    # debug everything but the API: "true" simply loads the previous .json
    DEBUG_API = False

    # debug print
    logging.debug('🔄 Running API call...')

    # what we're throwing at the API
    API_URL = 'https://ll.thespacedevs.com'
    API_VERSION = '2.1.0'
    API_REQUEST = 'launch/upcoming'
    PARAMS = {'mode': 'detailed', 'limit': 30}

    # construct the call URL
    API_CALL = f'{API_URL}/{API_VERSION}/{API_REQUEST}/{construct_params(PARAMS)}'

    # set headers
    headers = {'user-agent': f'telegram-{bot_username}'}

    # if debugging and the debug file exists, run this
    if DEBUG_API and os.path.isfile(os.path.join(data_dir, 'debug-json.json')):
        with open(os.path.join(data_dir, 'debug-json.json'), 'r') as json_file:
            api_json = json.load(json_file)

        rec_data = 0
        logging.warning('⚠️ API call skipped!')
        time.sleep(1.5)
    else:
        try:
            # create requests session
            session = requests.Session()
            session.headers = headers
            session.mount("https://",
                          HTTPAdapter(pool_connections=1, pool_maxsize=2))

            t0 = time.time()
            API_RESPONSE = session.get(API_CALL, timeout=5)
            rec_data = len(API_RESPONSE.content)

            tdelta = time.time() - t0
            logging.debug(
                f"✅ Received {rec_data/(1024*1000):.3f} MiB of data! Request took {tdelta:.3f} seconds"
            )
        except Exception as error:
            logging.warning(f'🛑 Error in LL API request: {error}')
            logging.warning('⚠️ Trying again after 3 seconds...')

            time.sleep(3)
            return ll2_api_call(data_dir=data_dir,
                                scheduler=scheduler,
                                bot_username=bot_username,
                                bot=bot)

        try:
            api_json = json.loads(API_RESPONSE.text)
            if DEBUG_API:
                with open(os.path.join(data_dir, 'debug-json.json'),
                          'w') as jsonf:
                    json.dump(api_json, jsonf, indent=4)
        except Exception as json_parse_error:
            logging.exception(f'⚠️ Error parsing json: {json_parse_error}')

            # dump api response for inspection / debugging use
            with open(
                    os.path.join(data_dir,
                                 f'error-json-{int(time.time())}.txt'),
                    'w') as ejson:
                ejson.write(API_RESPONSE.text)

            logging.warning('⚠️ Trying again after 60 seconds...')
            time.sleep(60)

            return ll2_api_call(data_dir=data_dir,
                                scheduler=scheduler,
                                bot_username=bot_username,
                                bot=bot)

    # store update time
    api_updated = int(time.time())

    # parse launches
    launch_obj_set = set()

    logging.debug("⏳ Parsing API data...")
    t0 = time.time()

    for launch in api_json['results']:
        try:
            launch_obj_set.add(LaunchLibrary2Launch(launch))
        except:
            logging.warning("Error parsing launch! Launch:", launch)

    tdelta = time.time() - t0
    logging.debug(
        f"✅ Parsed received data! Processing took {tdelta:.3f} seconds")

    # success?
    logging.debug(
        f'✅ Parsed {len(launch_obj_set)} launches into launch_obj_set.')

    # update database with the launch objects
    postponed_launches = update_launch_db(launch_set=launch_obj_set,
                                          db_path=data_dir,
                                          bot_username=bot_username,
                                          api_update=api_updated)

    # clean launches that have yet to launch and that weren't updated
    clean_launch_db(last_update=api_updated, db_path=data_dir)

    logging.debug('✅ DB update & cleaning complete!')

    # if a launch (or multiple) has been postponed, handle it here
    if len(postponed_launches) > 0:
        logging.info(f'Found {len(postponed_launches)} postponed launches!')
        ''' Handle each possibly postponed launch separately.
		tuple: (launch_object, postpone_message) '''
        for postpone_tuple in postponed_launches:
            # pull launch object from tuple
            launch_object = postpone_tuple[0]

            notify_list, sent_notification_ids = postpone_notification(
                db_path=data_dir, postpone_tuple=postpone_tuple, bot=bot)

            logging.info('Sent notifications!')
            logging.info(
                f'notify_list={notify_list}, sent_notification_ids={sent_notification_ids}'
            )

            # remove previous notification
            remove_previous_notification(db_path=data_dir,
                                         launch_id=launch_object.unique_id,
                                         notify_set=notify_list,
                                         bot=bot)

            logging.info('✉️ Previous notifications removed!')

            # notifications sent: store identifiers
            msg_id_str = ','.join(sent_notification_ids)
            store_notification_identifiers(db_path=data_dir,
                                           launch_id=launch_object.unique_id,
                                           identifiers=msg_id_str)
            logging.info(
                f'📃 Notification identifiers stored! identifiers="{msg_id_str}"'
            )

            # update stats
            update_stats_db(stats_update={'notifications': len(notify_list)},
                            db_path=data_dir)
            logging.info('📊 Stats updated!')

    # update statistics
    update_stats_db(stats_update={
        'api_requests': 1,
        'db_updates': 1,
        'data': rec_data,
        'last_api_update': api_updated
    },
                    db_path=data_dir)

    # schedule next API call
    next_api_update = api_call_scheduler(db_path=data_dir,
                                         scheduler=scheduler,
                                         ignore_60=True,
                                         bot_username=bot_username,
                                         bot=bot)

    # schedule notifications
    notification_send_scheduler(db_path=data_dir,
                                next_api_update_time=next_api_update,
                                scheduler=scheduler,
                                bot_username=bot_username,
                                bot=bot)
Пример #2
0
	def test_update_stats_db(self):
		notification_list = [1, 2, 3, 4]
		db_path = 'launchbot'

		update_stats_db(stats_update={'notifications': len(notification_list)},
			db_path=db_path)