""" API Client Connector ==================== Handles client setup and auth for the YouTube API. Requires the following environment variables to be set up and valid: * GOOGLE_API_KEY_FILE Source based on https://github.com/theorchard/ows-label-audit.git repo file ows-label-audit/labelaudit/connectors/youtube_api.py """ import os from googleapiclient.discovery import build import httplib2 from oauth2client.service_account import ServiceAccountCredentials from ioda.misc import retry, rate_limited, is_gapi_rate_limit from ioda import config OWNER_ORCHARD = 'theorchardmusic' class ServiceMapping: """ Google API Service Mapping ========================== Thin wrapper around the Google client library. Lazily handles oauth setup and builds the service client for the partner API. """ PARTNER_API_VERSION = 'v1' PARTNER_API_NAME = 'youtubePartner' def __init__(self, key_file): """Initialize ServiceMapping object. Args: key_file (str): file name of google api key file. Raises: ValueError in case of Missing Google API key file name or wrong access rights on it. """ if not key_file: raise ValueError('Missing Google API key file name') if not os.access(key_file, os.R_OK): raise ValueError('Cannot read Google API key file ' + key_file) self.key_file = key_file self._client = None self._youtube_partner = None def authorize(self): """Create and authorize a Google API client. To be called when the client has not been initialized or its access token has expired. """ credentials = ServiceAccountCredentials.from_json_keyfile_name( self.key_file, scopes=['https://www.googleapis.com/auth/youtubepartner']) self._client = credentials.authorize(httplib2.Http()) @property def client(self): """Create and authorize a Google API client. Returns: httplib2.Http: httlib2 client object. """ if not self._client: self.authorize() return self._client @property def youtube_partner(self): """Lazily initialize the YouTube API. Initialized object discovery resource for the partner API. Returns: googleapiclient.discovery.Resource: partner API resource. """ if not self._youtube_partner: self._youtube_partner = build( self.PARTNER_API_NAME, self.PARTNER_API_VERSION, http=self.client) return self._youtube_partner @rate_limited(max_per_second=config.API_RATE_LIMIT) def call_youtube_api(api_call_request): """Execute api_call_request. Execute given query to Youtube API. Args: api_call_request (Service request): Composed query to Youtube API. Returns: dict: result of request to Youtube API. """ return api_call_request.execute() @retry(is_gapi_rate_limit) def get_assets(youtube_client, asset_ids): """Seek for ownerships by assetIds list. Args: youtube_client (ServerMapping): Youtube API wrapper object. asset_id (list): assetId of seeking Ownership. Returns: list(dict): list of object of ownership. """ query = youtube_client.assets().list( id=asset_ids, onBehalfOfContentOwner=OWNER_ORCHARD, fetchMetadata='mine') asset_call = call_youtube_api(query) return asset_call.get('items', [])