"""LINE API Wrapper module.""" import requests from requests import Request from requests import Session class LineAPI(object): """Wrapper class to abstract loading data from LINE API.""" _token = None _oauth_url = 'https://api-music.line.me/v1/token' _resource_url = 'https://api-music.line.me/v1/reports/daily-reports?date' \ '={date}' def __init__(self, client_id, client_secret): """Class constructor. Args: client_id (str): The account name. client_secret (str): The secret password. """ self.client_id = client_id self.client_secret = client_secret @property def token(self): """LINE API oauth token. Requests oauth token from Spotify and caches it for the future uses. Returns: str: oauth token. """ if self._token is None: self._token = self._request_token() return self._token def _request_token(self): """Request oauth token from Spotify. Returns: str: oauth token. """ post_fields = { 'grant_type': 'client_credentials'} res = requests.post( self._oauth_url, data=post_fields, auth=(self._get_auth_header_for_token())) if res.status_code != 201: raise requests.RequestException(response=res) return res.json()['access_token'] def _get_auth_header_for_token(self): """Return oauth header for requesting token. Returns: tuple: (client_id, client_secret)}. """ return self.client_id, self.client_secret def _get_auth_header_for_request(self): """Return oauth header for requesting data. Returns: dict: The dict {'Authorization': 'Bearer {token}'}. """ return {'Authorization': 'Bearer {}'.format(self.token)} def request_to_file_url(self, date): """Request data from LINE API and write raw zipped response into fd. Args: date (date or str): date instance or `YYYY-MM-DD` formatted string. Returns: res: jsonified response from LINE API containing the file url """ res = requests.get( self._resource_url.format(date=date), headers=self._get_auth_header_for_request()) if res.status_code != 200: raise requests.RequestException(response=res) return res.json() def _extract_file_url_from_json(self, obj): """Recursively search for value of url in a JSON response. Args: obj: jsonified response containing the file download url. Returns: url: the url for downloading the monthly file. """ if isinstance(obj, dict): for key, value in obj.items(): if isinstance(value, (dict, list)): return self._extract_file_url_from_json(value) elif key == 'url': return value elif isinstance(obj, list): for item in obj: return self._extract_file_url_from_json(item) def _prepare_request(self, date): """Prepare LINE API request for loading the file. Args: date (date or str): date instance or `YYYY-MM-DD` formatted string. Returns: PreparedRequest: Prepared Request. """ file_url = self._extract_file_url_from_json( self.request_to_file_url(date)) req = Request('GET', file_url) return req.prepare() def request_to_file(self, fd, date): """Request data from LINE API and write raw zipped response into fd. Args: date (date or str): date instance or `YYYY-MM-DD` formatted string. """ req = self._prepare_request(date) res = Session().send(req, stream=True) res.raise_for_status() for chunk in res.iter_content(chunk_size=1024 * 1024): fd.write(chunk) fd.flush()