1
0
mirror of synced 2026-01-08 21:05:13 -05:00
Files
airbyte/airbyte-integrations/connectors/source-strava/source_strava/streams.py
Cole Snodgrass 2e099acc52 update headers from 2022 -> 2023 (#22594)
* It's 2023!

* 2022 -> 2023

---------

Co-authored-by: evantahler <evan@airbyte.io>
2023-02-08 13:01:16 -08:00

92 lines
3.2 KiB
Python

#
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
#
from abc import ABC
from typing import Any, Iterable, Mapping, MutableMapping, Optional
import requests
from airbyte_cdk.sources.streams.http import HttpStream
from dateutil import parser
# Basic full refresh stream
class StravaStream(HttpStream, ABC):
url_base = "https://www.strava.com/api/v3/"
def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]:
return None
def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]:
yield response.json()
# Basic incremental stream
class IncrementalStravaStream(StravaStream, ABC):
def __init__(self, after, **kwargs):
super().__init__(**kwargs)
self.after = parser.parse(after).timestamp()
per_page = 30 # default strava value
curr_page = 1
@property
def cursor_field(self) -> str:
return "start_date"
def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]:
return {self.cursor_field: max(latest_record.get(self.cursor_field, ""), current_stream_state.get(self.cursor_field, ""))}
def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]:
if len(response.json()) != 0:
self.curr_page += 1
return {"page": self.curr_page}
def request_params(
self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, any] = None, next_page_token: Mapping[str, Any] = None
) -> MutableMapping[str, Any]:
return {"per_page": self.per_page, "page": self.curr_page, "after": self.after}
def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]:
yield from response.json()
def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, any]]]:
if stream_state:
self.after = parser.parse(stream_state.get(self.cursor_field)).timestamp()
return [{"after": self.after}]
class AthleteStats(StravaStream):
"""
Returns the activity stats of an athlete. Only includes data from activities set to Everyone visibilty.
API Docs: https://developers.strava.com/docs/reference/#api-Athletes-getStats
Endpoint: https://www.strava.com/api/v3/<id>/stats
"""
primary_key = ""
def __init__(self, athlete_id: int, **kwargs):
super().__init__(**kwargs)
self.athlete_id = athlete_id
def path(
self, stream_state: Mapping[str, Any] = None, stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None
) -> str:
athlete_id = self.athlete_id
return f"athletes/{athlete_id}/stats"
class Activities(IncrementalStravaStream):
"""
Returns the activities of an athlete.
API Docs: https://developers.strava.com/docs/reference/#api-Activities-getLoggedInAthleteActivities
Endpoint: https://www.strava.com/api/v3/athlete/activities
"""
primary_key = "id"
def path(
self, stream_state: Mapping[str, Any] = None, stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None
) -> str:
return "athlete/activities"