googleads / googleads-bidmanager-examples

Apache License 2.0
43 stars 58 forks source link

Google Double Click Bid Manager API Giving 403 Error in Linux VM #15

Closed dharmen001 closed 4 years ago

dharmen001 commented 4 years ago

Hello,

I'm creating a python DV_360 function to get the data from the DV 360 API. These functions are working well in windows 10 machine though they are not working in the Ubuntu machine and giving 403 forbidden errors.

Traceback (most recent call last):
  File "DV360_1.py", line 134, in <module>
    main(util.setup(args), args.output_directory, QUERY_ID, args.report_window)
  File "DV360_1.py", line 63, in main
    doubleclick_bid_manager.queries().getquery(queryId="670966565").execute())
  File "/home/samsunguk/venv/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/home/samsunguk/venv/lib/python3.7/site-packages/googleapiclient/http.py", line 907, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/doubleclickbidmanager/v1.1/query/670966565?alt=json returned "Insufficient Permission: Request had insufficient authentication scopes.">

main.py:

import argparse
from contextlib import closing
from datetime import datetime
from datetime import timedelta
import os
import sys
from six.moves.urllib.request import urlopen
import util

# Optional filtering arguments.
parser = argparse.ArgumentParser(
    add_help=False,
    description='Downloads a report if it has been created in '
    'the given timeframe.')
parser.add_argument(
    '--output_directory',
    default=(os.path.dirname(os.path.realpath(__file__))),
    help=('Path to the directory you want to '
          'save the report to.'))
parser.add_argument(
    '--query_id',
    default=0,
    type=int,
    help=('The id of a query used to generate a report.'))
parser.add_argument(
    '--report_window',
    default=12,
    type=int,
    help=('The age a report must be in hours at a maximum to '
          'be considered fresh.'))

def main(doubleclick_bid_manager, output_dir, query_id, report_window):
  if query_id:
    # Call the API, getting the latest status for the passed queryId.
    query = (
        doubleclick_bid_manager.queries().getquery(queryId=query_id).execute())
    try:
      # If it is recent enough...
      if (is_in_report_window(query['metadata']['latestReportRunTimeMs'],
                              report_window)):
        if not os.path.isabs(output_dir):
          output_dir = os.path.expanduser(output_dir)

        # Grab the report and write contents to a file.
        report_url = query['metadata']['googleCloudStoragePathForLatestReport']
        output_file = '%s/%s.csv' % (output_dir, query['queryId'])
        with open(output_file, 'wb') as output:
          with closing(urlopen(report_url)) as url:
            output.write(url.read())
        print('Download complete.')
      else:
        print('No reports for queryId "%s" in the last %s hours.' %
              (query['queryId'], report_window))
    except KeyError:
      print('No report found for queryId "%s".' % query_id)
  else:
    # Call the API, getting a list of queries.
    response = doubleclick_bid_manager.queries().listqueries().execute()

    # Print queries out.
    print('Id\t\tName')
    if 'queries' in response:
      # Starting with the first page.
      print_queries(response)
      # Then everything else
      while 'nextPageToken' in response and response['nextPageToken']:
        response = doubleclick_bid_manager.queries().listqueries(
            pageToken=response['nextPageToken']).execute()
        print_queries(response)
    else:
      print('No queries exist.')

def print_queries(response):
  for q in response['queries']:
    print('%s\t%s' % (q['queryId'], q['metadata']['title']))

def is_in_report_window(run_time_ms, report_window):
  """Determines if the given time in milliseconds is in the report window.

  Args:
    run_time_ms: str containing a time in milliseconds.
    report_window: int identifying the range of the report window in hours.

  Returns:
    A boolean indicating whether the given query's report run time is within
    the report window.
  """
  report_time = datetime.fromtimestamp(int((run_time_ms)) / 1000)
  earliest_time_in_range = datetime.now() - timedelta(hours=report_window)
  return report_time > earliest_time_in_range

if __name__ == '__main__':
  args = util.get_arguments(sys.argv, __doc__, parents=[parser])
  # Retrieve the query id of the report we're downloading, or set to 0.
  QUERY_ID = 670966565
  if not QUERY_ID:
    try:
      QUERY_ID = int(
          raw_input('Enter the query id or press enter to '
                    'list queries: '))
    except ValueError:
      QUERY_ID = 0

  main(util.setup(args), args.output_directory, QUERY_ID, args.report_window)`

util.py

import argparse
import os

from googleapiclient import discovery
import httplib2
from oauth2client import client
from oauth2client import file as oauthFile
from oauth2client import tools

API_NAME = 'doubleclickbidmanager'
API_VERSION = 'v1.1'
API_SCOPES = ['https://www.googleapis.com/auth/doubleclickbidmanager']

# Filename used for the credential store.
CREDENTIAL_STORE_FILE = API_NAME + '.dat'

def get_arguments(argv, desc, parents=None):
  """Validates and parses command line arguments.

  Args:
    argv: list of strings, the command-line parameters of the application.
    desc: string, a description of the sample being executed.
    parents: list of argparse.ArgumentParser, additional command-line parsers.

  Returns:
    The parsed command-line arguments.
  """
  # Include the default oauth2client argparser
  parent_parsers = [tools.argparser]

  if parents:
    parent_parsers.extend(parents)

  parser = argparse.ArgumentParser(
      description=desc,
      formatter_class=argparse.RawDescriptionHelpFormatter,
      parents=parent_parsers)
  return parser.parse_args(argv[1:])

def load_application_default_credentials():
  """Attempts to load application default credentials.

  Returns:
    A credential object initialized with application default credentials or None
    if none were found.
  """
  try:
    credentials = client.GoogleCredentials.get_application_default()
    return credentials.create_scoped(API_SCOPES)
  except client.ApplicationDefaultCredentialsError:
    # No application default credentials, continue to try other options.
    pass

def load_user_credentials(client_secrets, storage, flags):
  """Attempts to load user credentials from the provided client secrets file.

  Args:
    client_secrets: path to the file containing client secrets.
    storage: the data store to use for caching credential information.
    flags: command-line flags.

  Returns:
    A credential object initialized with user account credentials.
  """
  # Set up a Flow object to be used if we need to authenticate.
  flow = client.flow_from_clientsecrets(
      client_secrets,
      scope=API_SCOPES,
      message=tools.message_if_missing(client_secrets))

  # Retrieve credentials from storage.
  # If the credentials don't exist or are invalid run through the installed
  # client flow. The storage object will ensure that if successful the good
  # credentials will get written back to file.
  credentials = storage.get()
  if credentials is None or credentials.invalid:
    credentials = tools.run_flow(flow, storage, flags)

  return credentials

def setup(flags):
  """Handles authentication and loading of the API.

  Args:
    flags: command-line flags obtained by calling ''get_arguments()''.

  Returns:
    An initialized service object.
  """
  # Load application default credentials if they're available.
  credentials = load_application_default_credentials()

  # Otherwise, load credentials from the provided client secrets file.
  if credentials is None:
    # Name of a file containing the OAuth 2.0 information for this
    # application, including client_id and client_secret, which are found
    # on the Credentials tab on the Google Developers Console.
    client_secrets = os.path.join(os.path.dirname(__file__),
                                  'client_secrets.json')
    storage = oauthFile.Storage(CREDENTIAL_STORE_FILE)
    credentials = load_user_credentials(client_secrets, storage, flags)

  # Authorize HTTP object with the prepared credentials.
  http = credentials.authorize(http=httplib2.Http())

  # Construct and return a service object via the discovery service.
  return discovery.build(API_NAME, API_VERSION, http=http)
dharmen001 commented 4 years ago

its solved by passing: export GOOGLE_APPLICATION_CREDENTIALS='./client_secrets.json'