94 lines
3.4 KiB
Python
94 lines
3.4 KiB
Python
#
|
|
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
|
|
#
|
|
|
|
from abc import ABC
|
|
from datetime import datetime
|
|
from typing import Any, Iterable, List, Mapping, MutableMapping, Optional, Tuple
|
|
from urllib.parse import parse_qs, urlparse
|
|
|
|
import requests
|
|
from airbyte_cdk.sources import AbstractSource
|
|
from airbyte_cdk.sources.streams import Stream
|
|
from airbyte_cdk.sources.streams.http import HttpStream
|
|
|
|
|
|
# Basic full refresh stream
|
|
class TimelyIntegrationStream(HttpStream, ABC):
|
|
FIRST_PAGE = 1
|
|
primary_key = "id"
|
|
url_base = "https://api.timelyapp.com/1.1/"
|
|
|
|
def __init__(self, account_id: str, start_date: str, bearer_token: str, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.account_id = account_id
|
|
self.start_date = start_date
|
|
self.bearer_token = bearer_token
|
|
|
|
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]:
|
|
|
|
if next_page_token is None:
|
|
return {"page": self.FIRST_PAGE, "per_page": "1000", "account_id": self.account_id}
|
|
|
|
return next_page_token
|
|
|
|
def request_headers(self, **kwargs) -> Mapping[str, Any]:
|
|
bearer_token = self.bearer_token
|
|
event_headers = {"Authorization": f"Bearer {bearer_token}", "Content-Type": "application/json"}
|
|
return event_headers
|
|
|
|
def parse_response(
|
|
self,
|
|
response: requests.Response,
|
|
stream_state: Mapping[str, Any],
|
|
stream_slice: Mapping[str, Any] = None,
|
|
next_page_token: Mapping[str, Any] = None,
|
|
) -> Iterable[Mapping]:
|
|
return response.json()
|
|
|
|
def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]:
|
|
results = response.json()
|
|
if results:
|
|
if len(results) > 0:
|
|
url_query = urlparse(response.url).query
|
|
query_params = parse_qs(url_query)
|
|
|
|
new_params = {param_name: param_value[0] for param_name, param_value in query_params.items()}
|
|
if "page" in new_params:
|
|
new_params["page"] = int(new_params["page"]) + 1
|
|
return new_params
|
|
|
|
|
|
class Events(TimelyIntegrationStream):
|
|
# https://dev.timelyapp.com/#list-all-events
|
|
primary_key = "id"
|
|
|
|
def path(self, **kwargs) -> str:
|
|
account_id = self.account_id
|
|
start_date = self.start_date
|
|
upto = datetime.today().strftime("%Y-%m-%d")
|
|
return f"{account_id}/events?since={start_date}&upto={upto}"
|
|
|
|
|
|
class SourceTimely(AbstractSource):
|
|
def check_connection(self, logger, config) -> Tuple[bool, any]:
|
|
account_id = config["account_id"]
|
|
start_date = config["start_date"]
|
|
bearer_token = config["bearer_token"]
|
|
|
|
headers = {"Authorization": f"Bearer {bearer_token}", "Content-Type": "application/json"}
|
|
url = f"https://api.timelyapp.com/1.1/{account_id}/events?since={start_date}&upto=2022-05-01"
|
|
|
|
try:
|
|
session = requests.get(url, headers=headers)
|
|
session.raise_for_status()
|
|
return True, None
|
|
except requests.exceptions.RequestException as e:
|
|
return False, e
|
|
|
|
def streams(self, config: Mapping[str, Any]) -> List[Stream]:
|
|
args = {"bearer_token": config["bearer_token"], "account_id": config["account_id"], "start_date": config["start_date"]}
|
|
return [Events(**args)]
|