示例#1
0
def main(path):
    """
    Main function called when starting weatherBot. The path is to the configuration file.
    :type path: str
    :param path: path to configuration file
    """
    # pylint: disable=broad-except,no-member
    global CACHE
    load_config(os.path.abspath(path))
    initialize_logger(CONFIG['log']['enabled'], CONFIG['log']['log_path'])
    logging.debug(CONFIG)
    keys.set_twitter_env_vars()
    keys.set_darksky_env_vars()
    CACHE['throttles']['default'] = pytz.utc.localize(datetime.utcnow()).astimezone(pytz.utc)
    with open(CONFIG['basic']['strings'], 'r') as file_stream:
        try:
            weatherbot_strings = yaml.safe_load(file_stream)
            logging.debug(weatherbot_strings)
            wb_string = models.WeatherBotString(weatherbot_strings)
        except yaml.YAMLError as err:
            logging.error(err, exc_info=True)
            logging.error('Could not read YAML file, please correct, run yamllint, and try again.')
            exit()

    location = CONFIG['default_location']
    updated_time = utils.datetime_to_utc('UTC', datetime.utcnow()) - timedelta(minutes=30)
    try:
        while True:
            # check for new location every 30 minutes
            now_utc = utils.datetime_to_utc('UTC', datetime.utcnow())
            if CONFIG['variable_location']['enabled'] and updated_time + timedelta(minutes=30) < now_utc:
                location = get_location_from_user_timeline(CONFIG['variable_location']['user'], location)
                updated_time = now_utc
            forecast = get_forecast_object(location.lat, location.lng, CONFIG['basic']['units'],
                                           wb_string.language)
            if forecast is not None:
                weather_data = models.WeatherData(forecast, location)
                if weather_data.valid:
                    CACHE = get_cache()
                    tweet_logic(weather_data, wb_string)
                CACHE['throttles'] = cleanse_throttles(CACHE['throttles'], now_utc)
                set_cache(CACHE)
                time.sleep(CONFIG['basic']['refresh'] * 60)
            else:
                time.sleep(60)
    except Exception as err:
        logging.error(err)
        logging.error('We got an exception!', exc_info=True)
        if CONFIG['basic']['dm_errors']:
            api = get_tweepy_api()
            api.send_direct_message(screen_name=api.me().screen_name,
                                    text=str(random.randint(0, 9999)) + traceback.format_exc())
示例#2
0
def main(path):
    """
    Main function called when starting weatherBot. The path is to the configuration file.
    :type path: str
    :param path: path to configuration file
    """
    # pylint: disable=broad-except,no-member
    global CACHE
    load_config(os.path.abspath(path))
    initialize_logger(CONFIG['log']['enabled'], CONFIG['log']['log_path'])
    logging.debug(CONFIG)
    keys.set_twitter_env_vars()
    keys.set_darksky_env_vars()
    CACHE['throttles']['default'] = pytz.utc.localize(datetime.utcnow()).astimezone(pytz.utc)
    with open(CONFIG['basic']['strings'], 'r') as file_stream:
        try:
            weatherbot_strings = yaml.safe_load(file_stream)
            logging.debug(weatherbot_strings)
            wb_string = models.WeatherBotString(weatherbot_strings)
        except yaml.YAMLError as err:
            logging.error(err, exc_info=True)
            logging.error('Could not read YAML file, please correct, run yamllint, and try again.')
            exit()

    location = CONFIG['default_location']
    updated_time = utils.datetime_to_utc('UTC', datetime.utcnow()) - timedelta(minutes=30)
    try:
        while True:
            # check for new location every 30 minutes
            now_utc = utils.datetime_to_utc('UTC', datetime.utcnow())
            if CONFIG['variable_location']['enabled'] and updated_time + timedelta(minutes=30) < now_utc:
                location = get_location_from_user_timeline(CONFIG['variable_location']['user'], location)
                updated_time = now_utc
            forecast = get_forecast_object(location.lat, location.lng, CONFIG['basic']['units'],
                                           wb_string.language)
            if forecast is not None:
                weather_data = models.WeatherData(forecast, location)
                if weather_data.valid:
                    CACHE = get_cache()
                    tweet_logic(weather_data, wb_string)
                CACHE['throttles'] = cleanse_throttles(CACHE['throttles'], now_utc)
                set_cache(CACHE)
                time.sleep(CONFIG['basic']['refresh'] * 60)
            else:
                time.sleep(60)
    except Exception as err:
        logging.error(err)
        logging.error('We got an exception!', exc_info=True)
        if CONFIG['basic']['dm_errors']:
            api = get_tweepy_api()
            api.send_direct_message(screen_name=api.me().screen_name,
                                    text=str(random.randint(0, 9999)) + traceback.format_exc())
 def test_datetime_to_utc(self):
     """Testing localize a normal datetime object to timezone id, then convert to UTC"""
     dt = datetime.datetime.fromtimestamp(1461738535)  # datetime.datetime(2016, 4, 27, 1, 28, 55)
     timezone_id = 'Europe/Copenhagen'
     utc_dt = utils.datetime_to_utc(timezone_id, dt)
     correct_dt = pytz.timezone('Europe/Copenhagen').localize(dt).astimezone(pytz.utc)
     self.assertEqual(utc_dt, correct_dt)
示例#4
0
def tweet_logic(weather_data, wb_string):
    """
    Core logic for tweets once initialization and configuration has been set and weather data fetched.
    :type weather_data: models.WeatherData
    :type wb_string: models.WeatherBotString
    """
    # pylint: disable=global-variable-not-assigned
    # CACHE is being modified here, pylint doesn't see that
    global CACHE
    wb_string.set_weather(weather_data)
    special = wb_string.special()
    normal_text = wb_string.normal()

    now = datetime.utcnow()
    now_utc = utils.datetime_to_utc('UTC', now)
    now_local = utils.localize_utc_datetime(weather_data.timezone, now)

    # weather alerts
    for alert in weather_data.alerts:
        if alert.sha() not in CACHE['throttles'] and not alert.expired(now_utc):
            try:
                CACHE['throttles'][alert.sha()] = alert.expires
            except AttributeError:
                # most alerts are probably done after 3 days
                CACHE['throttles'][alert.sha()] = alert.time + timedelta(days=3)
            do_tweet(wb_string.alert(alert, weather_data.timezone),
                     weather_data.location,
                     CONFIG['basic']['tweet_location'],
                     CONFIG['variable_location']['enabled'],
                     hashtag=CONFIG['basic']['hashtag'])

    # forecast
    forecast_dt = now_local.replace(hour=CONFIG['scheduled_times']['forecast'].hour,
                                    minute=CONFIG['scheduled_times']['forecast'].minute,
                                    second=0, microsecond=0).astimezone(pytz.utc)
    timed_tweet(forecast_dt, now_utc, wb_string.forecast(), weather_data.location)

    # scheduled tweet
    for scheduled_time in CONFIG['scheduled_times']['conditions']:
        scheduled_dt = now_local.replace(hour=scheduled_time.hour,
                                         minute=scheduled_time.minute,
                                         second=0, microsecond=0).astimezone(pytz.utc)
        timed_tweet(scheduled_dt, now_utc, normal_text, weather_data.location)

    # special condition
    if special.type != 'normal':
        logging.debug('Special event')
        try:
            next_allowed = CACHE['throttles'][special.type]
        except KeyError:
            next_allowed = CACHE['throttles']['default']

        if now_utc >= next_allowed:
            try:
                minutes = CONFIG['throttles'][special.type]
            except KeyError:
                minutes = CONFIG['throttles']['default']
            do_tweet(special.text,
                     weather_data.location,
                     CONFIG['basic']['tweet_location'],
                     CONFIG['variable_location']['enabled'],
                     hashtag=CONFIG['basic']['hashtag'])
            CACHE['throttles'][special.type] = now_utc + timedelta(minutes=minutes)
        logging.debug(CACHE)
示例#5
0
def tweet_logic(weather_data, wb_string):
    """
    Core logic for tweets once initialization and configuration has been set and weather data fetched.
    :type weather_data: models.WeatherData
    :type wb_string: models.WeatherBotString
    """
    # pylint: disable=global-variable-not-assigned
    # CACHE is being modified here, pylint doesn't see that
    global CACHE
    wb_string.set_weather(weather_data)
    logging.debug(wb_string.__dict__())
    special = wb_string.special()
    normal_text = wb_string.normal()

    now = datetime.utcnow()
    now_utc = utils.datetime_to_utc('UTC', now)
    now_local = utils.localize_utc_datetime(weather_data.timezone, now)

    # weather alerts
    for alert in weather_data.alerts:
        if alert.sha() not in CACHE['throttles'] and not alert.expired(now_utc):
            local_expires_time = alert.expires.astimezone(pytz.timezone(weather_data.timezone))
            CACHE['throttles'][alert.sha()] = alert.expires
            do_tweet(wb_string.alert(alert.title, local_expires_time, alert.uri),
                     weather_data.location,
                     CONFIG['basic']['tweet_location'],
                     CONFIG['variable_location']['enabled'],
                     hashtag=CONFIG['basic']['hashtag'])

    # forecast
    forecast_dt = now_local.replace(hour=CONFIG['scheduled_times']['forecast'].hour,
                                    minute=CONFIG['scheduled_times']['forecast'].minute,
                                    second=0, microsecond=0).astimezone(pytz.utc)
    timed_tweet(forecast_dt, now_utc, wb_string.forecast(), weather_data.location)

    # scheduled tweet
    for scheduled_time in CONFIG['scheduled_times']['conditions']:
        scheduled_dt = now_local.replace(hour=scheduled_time.hour,
                                         minute=scheduled_time.minute,
                                         second=0, microsecond=0).astimezone(pytz.utc)
        timed_tweet(scheduled_dt, now_utc, normal_text, weather_data.location)

    # special condition
    if special.type != 'normal':
        logging.debug('Special event')
        try:
            next_allowed = CACHE['throttles'][special.type]
        except KeyError:
            next_allowed = CACHE['throttles']['default']

        if now_utc >= next_allowed:
            try:
                minutes = CONFIG['throttles'][special.type]
            except KeyError:
                minutes = CONFIG['throttles']['default']
            do_tweet(special.text,
                     weather_data.location,
                     CONFIG['basic']['tweet_location'],
                     CONFIG['variable_location']['enabled'],
                     hashtag=CONFIG['basic']['hashtag'])
            CACHE['throttles'][special.type] = now_utc + timedelta(minutes=minutes)
        logging.debug(CACHE)