def getClient(user_id=None, account_id=None, client_customer_id=None): """Returns the adwords client Manager level if a user_id is provided Client (account) level if account_id and client_customer_id are provided """ helpers = Helpers() settings = Settings() if user_id is not None: refresh_token = helpers.getRefreshTokenFromUserId(user_id) else: refresh_token = helpers.getRefreshToken(account_id) if not refresh_token: Log("info", "Can't determine refresh_token for user %s " % (user_id), '', account_id) return yaml_data = helpers.getYamlData()["adwords"] client_id = yaml_data["client_id"] client_secret = yaml_data["client_secret"] developer_token = yaml_data["developer_token"] oauth_client = oauth2.GoogleRefreshTokenClient( client_id=client_id, client_secret=client_secret, refresh_token=refresh_token) if client_customer_id is not None: adwords_client = adwords.AdWordsClient( developer_token, oauth_client, client_customer_id=client_customer_id) else: adwords_client = adwords.AdWordsClient(developer_token, oauth_client) return adwords_client
class Update: def __init__(self, account_id, service_type, operations=None): self.settings = Settings() self.helpers = Helpers() self.debug_mode = self.settings.envvars["APP_DEBUG"] == "true" self.account_id = account_id self.service_type = service_type self.operations = operations self.refresh_token = self.helpers.getRefreshToken(account_id) self.client_customer_id = self.helpers.getClientCustomerID( self.settings, account_id) def getClient(self): return GoogleAdsApi.getClient(None, self.account_id, self.client_customer_id) def getService(self): client = self.getClient() service = client.GetService(self.service_type, version=Settings.api_version()) return service def send_request(self): if self.debug_mode: Log( "debug", "Mutations will not run in debug mode.", "There are {0} attempted operations".format( len(self.operations))) return "debug mode" # IMPORTANT: needs to be this exact text if self.settings.is_batch_job_processing: if self.settings.is_processing_batch_job_async: return self.send_batch_job_request_async() else: return self.send_batch_job_request_sync() return self.send_mutation_request() def check_batch_job_result(self, batch_job_id): download_url = self.check_batch_job(batch_job_id) response = None if download_url: batch_job_helper = self.getClient().GetBatchJobHelper( version=Settings.api_version()) response = batch_job_helper.ParseResponse( urlopen(download_url).read()) return response def send_mutation_request(self): criteria = self.getService().mutate(self.operations) return criteria def send_batch_job_request_sync(self): batch_job_helper = self.getClient().GetBatchJobHelper( version=Settings.api_version()) batch_job = self.add_batch_job() print('Created BatchJob with ID "{0}", status "{1}"'.format( batch_job['id'], batch_job['status'])) upload_url = batch_job['uploadUrl']['url'] batch_job_helper.UploadOperations( upload_url, self.operations, ) download_url = self.get_batch_job_download_url_when_ready( batch_job['id']) response = batch_job_helper.ParseResponse(urlopen(download_url).read()) self.helpers.print_batch_job_response(response) return response def send_batch_job_request_async(self): batch_job_helper = self.getClient().GetBatchJobHelper( version=Settings.api_version()) batch_job = self.add_batch_job() print('Created BatchJob with ID "{0}", status "{1}"'.format( batch_job['id'], batch_job['status'])) upload_url = batch_job['uploadUrl']['url'] batch_job_helper.UploadOperations( upload_url, self.operations, ) return { 'batch_job_id': batch_job['id'], 'batch_job_status': batch_job['status'] } def add_batch_job(self): """ Add a new BatchJob to upload operations to. :return: The new BatchJob created by the request. """ # Initialize appropriate service. client = self.getClient() batch_job_service = client.GetService('BatchJobService', version=Settings.api_version()) # Create a BatchJob. batch_job_operations = [{'operand': {}, 'operator': 'ADD'}] return batch_job_service.mutate(batch_job_operations)['value'][0] def get_batch_job(self, client, batch_job_id): """ Retrieves the BatchJob with the given id. :param client: an instantiated AdWordsClient used to retrieve the BatchJob. :param batch_job_id: a long identifying the BatchJob to be retrieved. :return: The BatchJob associated with the given id. """ batch_job_service = client.GetService('BatchJobService', Settings.api_version()) selector = { 'fields': ['Id', 'Status', 'DownloadUrl'], 'predicates': [{ 'field': 'Id', 'operator': 'EQUALS', 'values': [batch_job_id] }] } return batch_job_service.get(selector)['entries'][0] def check_batch_job(self, batch_job_id): batch_job = self.get_batch_job(self.getClient(), batch_job_id) if batch_job['status'] in PENDING_STATUSES: return None elif 'downloadUrl' in batch_job and batch_job[ 'downloadUrl'] is not None: return batch_job['downloadUrl']['url'] def get_batch_job_download_url_when_ready( self, batch_job_id, max_poll_attempts=MAX_POLL_ATTEMPTS): """ Retrieves the downloadUrl when the BatchJob is complete. :param batch_job_id: a long identifying the BatchJob to be polled. :param max_poll_attempts: an int defining the number of times the BatchJob will be checked to determine whether it has completed. :return: A str containing the downloadUrl of the completed BatchJob. :rtype: str :raise: Exception: If the BatchJob hasn't finished after the maximum poll attempts have been made. """ batch_job = self.get_batch_job(self.getClient(), batch_job_id) poll_attempt = 0 while poll_attempt in range( max_poll_attempts) and batch_job['status'] in PENDING_STATUSES: sleep_interval = (30 * (2**poll_attempt) + (random.randint(0, 10000) / 1000)) print('Batch Job not ready, sleeping for %s seconds.' % sleep_interval) time.sleep(sleep_interval) batch_job = self.get_batch_job(self.getClient(), batch_job_id) poll_attempt += 1 if 'downloadUrl' in batch_job and batch_job[ 'downloadUrl'] is not None: url = batch_job['downloadUrl']['url'] print('Batch Job with Id "{0}", Status "{1}" ready.'.format( batch_job['id'], batch_job['status'])) return url raise Exception( 'Batch Job not finished downloading. Try checking later.')