def send_email(sender: str, recipient: str, subject: str, body_text: str) -> bool: charset = "UTF-8" client = boto3.client('ses', region_name=CONFIG.get('aws-region')) try: response = client.send_email(Destination={ 'ToAddresses': [recipient], }, Message={ 'Body': { 'Text': { 'Charset': charset, 'Data': body_text }, }, 'Subject': { 'Charset': charset, 'Data': subject }, }, Source=sender) except ClientError as e: logger.error(e.response['Error']['Message']) return False else: logger.debug("Email sent! Message ID : {}".format( response['MessageId'])) return True
def fetch_usa_rt_estimate(fips: str) -> RtEstimate: rdb: RDBManager = RDBManager(reader=True) rt_estimates_data, err = rdb.execute(sql_query=""" SELECT `date`, `rt_estimate`, `rt_low`, `rt_high` FROM `rt_estimates` WHERE `country_code` = 'USA' AND `region_code` = '{}' ORDER BY `date` ASC """.format(fips)) if err is not None: logger.error(err) if len(rt_estimates_data) > 0: rt_estimate = RtEstimate( _date=[item['date'] for item in rt_estimates_data], rt_estimate=[ float(item['rt_estimate']) for item in rt_estimates_data ], rt_low=[float(item['rt_low']) for item in rt_estimates_data], rt_high=[float(item['rt_high']) for item in rt_estimates_data]) return rt_estimate return RtEstimate()
def unsubscribed(self) -> bool: unsub_status = False try: unsub_status = bool(self.get_human_attribute(attribute_name=HumanProperties.UNSUBSCRIBED.value)) except Exception as e: logger.error(e) return unsub_status
def get_most_recent_location(self) -> (float, float): rdb = RDBManager(True) err = None try: most_recent_location, err = rdb.execute( sql_query=""" SELECT `latitude` AS `{}`, `longitude` AS `{}` FROM `geolocations` WHERE `human_id` = {} AND `latitude` IS NOT NULL AND `longitude` IS NOT NULL ORDER BY `created` DESC LIMIT 1 """.format( CoordinateType.LATITUDE.value, CoordinateType.LONGITUDE.value, mysql_db_format_value(value=self.id) ) ) except Exception as e: logger.error(e) if len(most_recent_location) == 1: return float(most_recent_location[0][CoordinateType.LATITUDE.value]), \ float(most_recent_location[0][CoordinateType.LONGITUDE.value]) else: return None, None
def get_all_humans_for_telegram_notifications(hours_of_day: list) -> list: if not isinstance(hours_of_day, list) or len(hours_of_day) == 0: return [] for hour_of_day in hours_of_day: if not isinstance(hour_of_day, int) or (hour_of_day < 0 or hour_of_day > 23): return [] hours_of_day = list(set(hours_of_day)) rdb = RDBManager(True) audience = [] try: audience, err = rdb.execute( sql_query=""" SELECT `id`, `telegram_human_id` FROM `humans` WHERE HOUR(CONVERT_TZ(UTC_TIMESTAMP(),'UTC',`current_tz`)) IN ({}) AND `telegram_human_id` is not null AND `unsubscribed` = 0 """.format( ", ".join([str(hour_of_day) for hour_of_day in hours_of_day]) ) ) except Exception as e: logger.error(e) return audience
def verify_telegram_id_exists(telegram_human_id: int) -> (bool, str): if not isinstance(telegram_human_id, int): return TypeError('`telegram_human_id` of type {}. Expected [int]'.format(type(telegram_human_id))) rdb = RDBManager(True) err = None try: telegram_human_id_search_results, err = rdb.execute( sql_query=""" SELECT `{}` FROM `humans` WHERE `{}` = {} """.format( HumanProperties.ID.value, HumanProperties.TELEGRAM_HUMAN_ID.value, telegram_human_id ) ) except Exception as e: logger.error(e) if len(telegram_human_id_search_results) == 1: return True, telegram_human_id_search_results[0][HumanProperties.ID.value] else: return False, None
def clean_data(data: pd.DataFrame) -> pd.DataFrame: logger.debug("Cleaning dataset...") data: pd.DataFrame = data[~pd.isna(data['ID'])] data: pd.DataFrame = data[~pd.isna(data['date_confirmation'])] data['date_confirmation'] = pd.to_datetime( data['date_confirmation'].apply(lambda x: x[:10])) data['created'] = data['date_confirmation'] data['modified'] = data['date_confirmation'] data['latitude'] = pd.to_numeric(data['latitude']) data['longitude'] = pd.to_numeric(data['longitude']) data['biological_sex'] = data['sex'].apply( lambda x: 'F' if x == 'female' else ('M' if x == 'male' else np.nan)) data['symptom'] = 'verified_covid19' data['source'] = 'beoutbreakprepared' data['source_id'] = data['ID'] data['id'] = data['source_id'].apply(lambda x: str(uuid.uuid4())) data['human_id'] = data['id'] try: source_ids_to_remove = get_existing_source_ids() except Exception as e: logger.error(e) else: data: pd.DataFrame = data[~data['source_id'].isin(source_ids_to_remove )] return data
def update_tz(self, lat: float, lng: float) -> bool: rdb = RDBManager() err = None try: _, err = rdb.execute( sql_query=""" UPDATE `humans` SET `current_tz` = ( SELECT `timezone_name` FROM `timezones` WHERE mbrcontains(area, point({}, {})) LIMIT 1 ) WHERE `id` = {} """.format( mysql_db_format_value(value=lng), mysql_db_format_value(value=lat), mysql_db_format_value(value=self.id) ) ) except Exception as e: logger.error(e) return err is None
def log_location(self, latitude: float, longitude: float, send_alert: bool = True) -> bool: if not isinstance(latitude, float) or not isinstance(longitude, float): return False rdb = RDBManager() err = None try: _, err = rdb.execute( sql_query=""" INSERT IGNORE INTO `geolocations`( `human_id`, `created`, `modified`, `latitude`, `longitude`, `latitude_noise`, `longitude_noise` ) VALUES ({}, UTC_TIMESTAMP(), UTC_TIMESTAMP(), {}, {}, ROUND(gauss(0,0.001), 10), ROUND(gauss(0,0.001), 10)) """.format( mysql_db_format_value(value=self.id), mysql_db_format_value(value=round(latitude, 10)), mysql_db_format_value(value=round(longitude, 10)) ) ) except Exception as e: logger.error(e) if send_alert: self.send_proximity_alert(lat=latitude, lng=longitude) self.update_tz(lat=latitude, lng=longitude) return err is None
def return_response(cls, data={}, status=200, message="", headers={}, error_code=200): try: logger.debug('Return status %s %s', status, message) except: app.logger.error(traceback.format_exc()) try: filters = request.args.get('filters') if filters: fd = BaseDict(data).filter(*filters.split(',')) data = fd except: app.logger.error(traceback.format_exc()) data = data try: if isinstance(data, db.Model): data = data.format() elif isinstance(data, list) and data and \ isinstance(data[0], db.Model): data = [o.format() for o in data] except: logger.error(traceback.format_exc()) data = data res = cls( data=data, status=status, message=message, error_code=error_code ).to_dict() return make_response(jsonify(res), status, headers)
def update_rt_estimates_usa(): counties_full: DataFrame = get_us_county_data() all_fips: List[str] = counties_full.index.get_level_values( 'fips').unique().to_list() all_estimates: List[DataFrame] = [] for fips in all_fips: try: county_data = counties_full.xs(fips) except KeyError as ke: logger.error(ke) if len(county_data) <= 1: continue county_name = county_data.iloc[0]['county'] state_name = county_data.iloc[0]['state'] country_code = 'USA' cases = county_data['cases'] _, smoothed, index_dates = prepare_cases(cases=cases) try: rt, low, high = compute_rt(smoothed_new_cases=smoothed) except TimeSeriesDimensionError as e: logger.error(e) continue rt_region_estimate = DataFrame({ 'rt_estimate': rt, 'rt_low': low, 'rt_high': high, 'date': index_dates, 'country_code': country_code, 'first_administrative_division_name': state_name, 'region_code': fips, 'region_name': county_name }) all_estimates.append(rt_region_estimate) all_estimates_df = pd.concat(all_estimates) all_estimates_df.reset_index(inplace=True, drop=True) database_connection = sqlalchemy.create_engine(generate_db_uri()) all_estimates_tbl_name: str = 'rt_estimates' all_estimates_tmp_tbl_name: str = 'rt_estimates_tmp' all_estimates_df.to_sql(name=all_estimates_tmp_tbl_name, con=database_connection, if_exists='replace', index=False) with database_connection.begin() as cnx: insert_sql: str = """ INSERT IGNORE INTO {}({}, `modified`) SELECT {}, UTC_TIMESTAMP() FROM {} as t ON DUPLICATE KEY UPDATE `rt_estimate` = t.`rt_estimate`, `rt_low` = t.`rt_low`, `rt_high` = t.`rt_high`, `modified` = UTC_TIMESTAMP() """.format(all_estimates_tbl_name, ', '.join(list(all_estimates_df.columns)), ', '.join(list(all_estimates_df.columns)), all_estimates_tmp_tbl_name) cnx.execute(insert_sql) delete_tmp_table_sql: str = "DROP TABLE IF EXISTS {}".format( all_estimates_tmp_tbl_name) cnx.execute(delete_tmp_table_sql)
def get_weather(lat, lng, key='d122fe39de94bf2c6c2ea443e9fef496'): """ 获取天气预报 DOC:https://darksky.net/dev/docs/forecast """ # key1 = 'd122fe39de94bf2c6c2ea443e9fef496' # key2 = 'ca5680b002774a7cba5cad57df33c20e' # keys = ['04a0ab1e89d625503ad4d53c31622b04', # 'd122fe39de94bf2c6c2ea443e9fef496', # 'ca5680b002774a7cba5cad57df33c20e'] def _f2c(f): """华氏度转变成摄氏度""" return float('{:0.2f}'.format((float(f) - 32) / 1.8)) def _format_hour(h): """格式化小时内天气""" h['temperature'] = _f2c(h['temperature']) h['apparentTemperature'] = _f2c(h['apparentTemperature']) h['dewPoint'] = _f2c(h['dewPoint']) return h def _format_day(d): """格式化每天天气""" d['temperatureMin'] = _f2c(d['temperatureMin']) d['temperatureMax'] = _f2c(d['temperatureMax']) d['apparentTemperatureMin'] = _f2c(d['apparentTemperatureMin']) d['apparentTemperatureMax'] = _f2c(d['apparentTemperatureMax']) d['dewPoint'] = _f2c(d['dewPoint']) return d def _format(d): """格式化天气""" d['scale'] = '°F' if d.get('timezone') and 'America' not in d.get('timezone'): d['currently'] = _format_hour(d['currently']) d['hourly']['data'] = [ _format_hour(o) for o in d['hourly']['data'] ] d['daily']['data'] = [_format_day(o) for o in d['daily']['data']] d['scale'] = '°C' return d try: url = 'https://api.darksky.net/forecast/{}/{},{}' res = requests.get(url.format(key, lat, lng)) if res.status_code != 200: logger.error('weather error %s', res.content) # res = requests.get(url.format(key2, lat, lng)) # if res.status_code != 200: # logger.error('weather error %s', res.content) return _format(res.json()) except Exception: logger.error(traceback.format_exc()) return {}
def run(self): addr = ("", self.port) try: adapter_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) adapter_sock.bind(addr) logger.info("IPv4 UDP服务器已经启动,服务器绑定地址%s" % str(addr)) except Exception, e: logger.error("启动IPv4 UDP服务器失败,错误原因%s" % str(e)) exit(0)
def get(self, name): res = self.client.get(name) try: res = utils.unsequence(res) return res except: logger.error(res) logger.error(traceback.format_exc()) return None
def pre_execute(self, sql_query: str) -> Exception: err = None try: with self.connection.cursor() as cursor: cursor.execute(sql_query) self.connection.commit() except BaseException as e: logger.error(e) err = e return err
def run(self): addr = ("", self.port) try: self.adapter_sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) self.adapter_sock.bind(addr) self.adapter_sock.listen(10) logger.info("IPv6 TCP服务器已经启动,服务器绑定地址%s" % str(addr)) except Exception, e: logger.error("启动IPv6 TCP服务器失败,错误原因%s" % str(e)) exit(0)
def georadius(self, name, longitude, latitude, radius, unit='km', withdist=True, withcoord=False, withhash=False, count=11, sort='ASC', store=None, store_dist=None): try: kw = locals() kw.pop('self') return self.client.georadius(**kw) except Exception as e: logger.error(e) return []
def fulfill_help_request(human: Human) -> bool: bot = get_telegram_bot_instance() try: log_sent_message(bot.send_message( chat_id=human.telegram_human_id, text="Click here to talk to us: @OpendemicTeam" ), human_id=human.id) except Exception as e: logger.error(e) return False return True
def fulfill_report_telegram_command(human: Human) -> bool: bot = get_telegram_bot_instance() try: log_sent_message(bot.send_message( chat_id=human.telegram_human_id, text="See options below 👇", reply_markup=get_telegram_menu() ), human_id=human.id) except Exception as e: logger.error(e) return False return True
def fulfill_invalid_telegram_command(human: Human) -> bool: bot = get_telegram_bot_instance() try: log_sent_message(bot.send_message( chat_id=human.telegram_human_id, text="Oops... This command is not valid. Type `/` to see valid commands.", reply_markup=get_telegram_menu() ), human_id=human.id) except Exception as e: logger.error(e) return False return True
def get_exception_message(e, language): """ Logs traceback message and get appropriate exception message from config file. :param exception e: exception to be handled :param str language: _language code :rtype: str :return: an exception message that will be delivered to the user """ logger.warning("An exception occurred.") exception_type = convert_instance_type_to_str(type(e)) message = EXCEPTION_MESSAGES.get(exception_type, "exception")[language] traceback_message = traceback.format_exc() logger.error(traceback_message) return message
def fulfill_log_symptom(human: Human, symptom_name: str) -> bool: bot = get_telegram_bot_instance() try: human.log_symptom(symptom_name=symptom_name) log_sent_message(bot.send_message( chat_id=human.telegram_human_id, text="Noted!" ), human_id=human.id) except Exception as e: logger.error(e) return False return True
def location(): # Fetch or create human, log its location, and return nearby risky humans params = create_parameters() validation_error_response = validate_location_url_params(params=params) if len(validation_error_response) > 0: return_invalid_response(validation_error_response) human = model.get_human_from_fingerprint(fingerprint=params[LocationResourceFields.FINGERPRINT.value]) if human is None: human, err = model.create_human(fingerprint=params[LocationResourceFields.FINGERPRINT.value]) if err is not None: logger.error(err) response = Response( response=json.dumps({ "error": "Error creating human with fingerprint {}".format(params[LocationResourceFields.FINGERPRINT.value]) }), status=403, mimetype='application/json' ) response.headers.add('Access-Control-Allow-Origin', '*') return response human.log_location( latitude=float(params[LocationResourceFields.LATITUDE.value]), longitude=float(params[LocationResourceFields.LONGITUDE.value]), send_alert=False) self_lat_lng = [params[LocationResourceFields.LONGITUDE.value], params[LocationResourceFields.LATITUDE.value]] self_geojson_feature = { 'type': "Point", 'coordinates': self_lat_lng } risky_humans_geojson = model.get_risky_humans_geojson( lat=params[LocationResourceFields.LATITUDE.value], lng=params[LocationResourceFields.LONGITUDE.value], days_window=int(CONFIG.get('days_window')), km_radius=int(CONFIG.get('km_radius')) ) return render_template( 'map.html', self_geojson_feature=self_geojson_feature, self_lat_lng=self_lat_lng, risky_humans_geojson=risky_humans_geojson, km_radius=int(CONFIG.get('km_radius')), include_legend=params[LocationResourceFields.INCLUDE_LEGEND.value], zoom_level=9 )
def execute(self, sql_query: str) -> (list, Exception): err = None result = [] starting_time = time() try: with self.connection.cursor() as cursor: cursor.execute(sql_query) result = cursor.fetchall() QUERY_DURATION.labels('opendemic', sql_query).observe( round(time() - starting_time, 2)) self.connection.commit() except BaseException as e: logger.error(e) err = e return result, err
def fulfill_my_map_request(human: Human) -> bool: bot = get_telegram_bot_instance() try: bot.send_message( chat_id=human.telegram_human_id, text="See who's around you 👇", parse_mode='markdown', reply_markup=make_reply_keyboard_markup(markup_map=[ {'text': "🌍 See Map", 'url': CONFIG.get('client-url')}, ]) ) except Exception as e: logger.error(e) return False return True
def get_human_attribute(self, attribute_name: str) -> str: rdb = RDBManager(True) try: human_id_search_results, err = rdb.execute( sql_query=""" SELECT * FROM `humans` WHERE `id` = '{}' """.format(self._human_id) ) except Exception as e: logger.error(e) if len(human_id_search_results) == 1: if attribute_name in human_id_search_results[0]: return human_id_search_results[0][attribute_name] return None
def create_parameters() -> dict: # Create parameters from a request params = dict() params[LocationResourceFields.FINGERPRINT.value] = request.args.get(LocationResourceFields.FINGERPRINT.value) params[LocationResourceFields.LATITUDE.value] = request.args.get(LocationResourceFields.LATITUDE.value) params[LocationResourceFields.LONGITUDE.value] = request.args.get(LocationResourceFields.LONGITUDE.value) params[LocationResourceFields.INCLUDE_LEGEND.value] = request.args.get(LocationResourceFields.INCLUDE_LEGEND.value) if params[LocationResourceFields.INCLUDE_LEGEND.value] is None: params[LocationResourceFields.INCLUDE_LEGEND.value] = True else: try: include_legend = bool(eval(str(params[LocationResourceFields.INCLUDE_LEGEND.value]).capitalize())) except NameError as e: logger.error(e) include_legend = True params[LocationResourceFields.INCLUDE_LEGEND.value] = include_legend return params
def unsubscribe(self) -> bool: rdb = RDBManager() err = None try: _, err = rdb.execute( sql_query=""" UPDATE `humans` SET `unsubscribed` = 1 WHERE `id` = {} """.format( mysql_db_format_value(value=self.id) ) ) except Exception as e: logger.error(e) return err is None
def get_human_from_fingerprint(fingerprint: str) -> Human: rdb = RDBManager(True) err = None try: records, err = rdb.execute( sql_query=""" SELECT `{}` FROM `humans` WHERE `{}` = {} """.format( HumanProperties.ID.value, HumanProperties.FINGERPRINT.value, mysql_db_format_value(fingerprint) ) ) except Exception as e: logger.error(e) return Human(human_id=records[0][HumanProperties.ID.value]) if len(records) == 1 else None
def init_request_data(): g.request_start_time = time.time() g.api_id = int(g.request_start_time * 1000) if app.config['DEBUG']: try: data = request.data args = request.args or {} # json_data = request.json or {} # form_data = request.form or {} h_data = request.headers or {} logger.debug('{} Request Begin ID'.format('-' * 10)) logger.debug('{} {}'.format(request.method, request.url)) logger.debug('Header %s', dict(h_data)) logger.debug('Data %s', data) except Exception as e: logger.error('params %s', e) logger.error(traceback.format_exc())