예제 #1
0
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
예제 #2
0
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