def __init__(self): self.parameter_manager = ParameterManager() self.config = self._get_config() if not all(k in self.config for k in ("email", "password")): raise ConfigError("""Please put the following paths and their values in the aws parameter store /endomondo/email /endomondo/password """) self._authenticate()
# 'https://www.googleapis.com/fitness/v1/users/me/dataSources/derived:com.google.weight:com.google.android.gms:merge_weight/datasets/0-1443194884000000000' import os import time import rollbar from managers.parameter import ParameterManager from managers.s3 import S3Manager from managers.google_fit import GoogleFitManager from models.body import WeightEntry, Weights HEALTH_DATA_BUCKET_NAME = os.environ.get('HEALTH_DATA_BUCKET_NAME') MINIMUM_NANOS = os.environ.get('MINIMUM_NANOS', '1528917191000000000') PARAMETER_MANAGER = ParameterManager() rollbar_key = PARAMETER_MANAGER.get('/rollbar/key') rollbar.init(rollbar_key, __file__) @rollbar.lambda_function def handler(event, context): s3_manager = S3Manager(HEALTH_DATA_BUCKET_NAME, 'weights.csv', WeightEntry) min_nanos = int(MINIMUM_NANOS) if s3_manager.has_entries_online(): min_nanos = s3_manager.get_max_int(column_name='startTimeNanos') google_fit_manager = GoogleFitManager() google_fit_manager.authenticate()
class EndomondoService(): def __init__(self): self.parameter_manager = ParameterManager() self.config = self._get_config() if not all(k in self.config for k in ("email", "password")): raise ConfigError("""Please put the following paths and their values in the aws parameter store /endomondo/email /endomondo/password """) self._authenticate() def _get_config(self): return self.parameter_manager.get_multiple('/endomondo/') def _authenticate(self): auth_key = self.config.get("auth_key") if not auth_key: auth_key = self._get_key() self.parameter_manager.store('/endomondo/auth_key', auth_key) def _get_key(self) -> str: url = 'https://api.mobile.endomondo.com/mobile/auth' # taken from https://github.com/isoteemu/sports-tracker-liberator/blob/master/endomondo/endomondo.py params = { 'os': platform.system(), 'model': platform.python_implementation(), 'osVersion': platform.release(), 'vendor': 'github/kreusen', 'appVariant': 'endomondo-api', 'country': 'GB', 'v': '2.4', 'appVersion': '0.1', 'deviceId': str(uuid.uuid5(uuid.NAMESPACE_DNS, socket.gethostname())), "action": "pair", "email": self.config.get("email"), "password": self.config.get("password") } r = requests.get(url, params=params) lines = r.text.split("\n") if lines[0] != "OK": raise AuthenticationError( f"Could not authenticate with Endomondo, Expected 'OK', got '{lines[0]}'" ) for line in lines[1:]: key, value = line.split("=") if key == "authToken": return value def get_runs(self, maxresults: int = 25) -> List[Run]: url = f"https://api.mobile.endomondo.com/mobile/api/workouts?authToken={self.config.get('auth_key')}&maxResults={maxresults}&fields=basic" r = requests.get(url) response = r.json() runs = [] for workout in response["data"]: # only get runs if workout["sport"] == 0 and workout["live"] == False: run = create_model_from_dict(Run, workout) runs.append(run) return runs
def __init__(self): self.parameter_manager = ParameterManager() self.access_token = None
class GoogleFitManager(): def __init__(self): self.parameter_manager = ParameterManager() self.access_token = None def authenticate(self): if self.access_token is None: credentials = self._get_credentials() self.access_token = credentials.get("access_token") def _get_credentials(self) -> dict: """ Authenticates with google fit and returns a dictionary with the most recent valid credentials """ online_credentials = self.parameter_manager.get_multiple('/google_fit/') credentials = GoogleCredentials(**online_credentials, token_expiry=None, user_agent=None) http = credentials.authorize(httplib2.Http()) credentials.refresh(http) credentials_dict = json.loads(credentials.to_json()) self.access_token = credentials_dict.get("access_token") self._store_credentials_online(credentials_dict) return credentials_dict def _store_credentials_online(self, credentials_dict: dict): keys_to_store = ["access_token", "client_secret", "client_id", "refresh_token", "token_uri"] for key in keys_to_store: if key in credentials_dict: path = f'/google_fit/{key}' value = credentials_dict.get(key) self.parameter_manager.store(path, value) def get_weights(self, min_nanos: int, max_nanos: Optional[int] = None) -> Optional[List[WeightEntry]]: if max_nanos is None: max_nanos = get_current_nanos() base_url = 'https://www.googleapis.com/fitness/v1/users/me/dataSources/derived:com.google.weight:com.google.android.gms:merge_weight/datasets' # batch requests pe def batch_requests(self, base_url: str, min_nanos: int, max_nanos: int, batch_per_n_nanos: int = 8640000000): pass def build_url(self, base_url: str, min_nanos: int, max_nanos: int) -> str: return os.path.join(base_url, f'{min_nanos}-{max_nanos}') def make_request(self, url: str): headers = { "Authorization": f"Bearer {self.access_token}" } r = requests.get(url, headers=headers) response = r.json() if "error" in response: raise GoogleFitError(response) return response def extract_values(self, response: dict) -> List[dict]: point = response.get("point") extracted_values = [] if point: for p in point: extracted_value = { "startTimeNanos": p.get("startTimeNanos"), "value": p["value"][0]["fpVal"] } extracted_values.append(extracted_value) return extracted_values
def __init__(self): self.parameter_manager = ParameterManager()
class BunqService(): def __init__(self): self.parameter_manager = ParameterManager() def authenticate(self): if self.parameter_manager.exists("/bunq/api_context"): self.api_context = self._get_api_context_from_aws() self._ensure_active_session() else: self.api_context = self._create_api_context() BunqContext.load_api_context(self.api_context) def _get_api_context_from_aws(self) -> ApiContext: json_string = self.parameter_manager.get("/bunq/api_context") return ApiContext.from_json(json_string) def _create_api_context(self) -> ApiContext: api_key = self.parameter_manager.get('/bunq/api_key') api_context = ApiContext(ApiEnvironmentType.PRODUCTION, api_key, 'runs-to-gadgetfund') self._update_remote_api_context(api_context) return api_context def _ensure_active_session(self): if not self.api_context.is_session_active(): self.api_context.reset_session() self._update_remote_api_context(self.api_context) def _update_remote_api_context(self, api_context: object): self.parameter_manager.store("/bunq/api_context", api_context.to_json()) def make_payment(self, PaymentInfo: object): recipient = Pointer('IBAN', PaymentInfo.to_iban, "bunq") endpoint.Payment.create( amount=Amount(PaymentInfo.amount_string, 'EUR'), counterparty_alias=recipient, description=PaymentInfo.description, monetary_account_id=self._get_monetary_account_id_from_iban( PaymentInfo.from_iban)) def _get_monetary_account_id_from_iban(self, from_iban: str) -> Optional[int]: all_accounts = self._get_all_active_monetary_accounts() account_ids_by_iban = {} for account in all_accounts: for alias in account["alias"]: if alias["type"] == "IBAN": iban = alias["value"] continue account_id = account["id"] account_ids_by_iban[iban] = account_id return account_ids_by_iban.get(from_iban) def _get_all_active_monetary_accounts(self): pagination = Pagination() pagination.count = 100 all_monetary_account_bank = endpoint.MonetaryAccountBank.list( pagination.url_params_count_only).value all_monetary_account_bank_active = [] for monetary_account_bank in all_monetary_account_bank: if monetary_account_bank.status == "ACTIVE": account_to_append = json.loads(monetary_account_bank.to_json()) all_monetary_account_bank_active.append(account_to_append) return all_monetary_account_bank_active