Skip to content

Commit c8e98d8

Browse files
Update auth libraries, add options, documentation
The oauth2client library is deprecated. This update changes the sample to use the google-auth and google-auth-oauthlib libraries instead. The updated script has improved options, allowing the user to set a content owner ID, job ID, report URL, and/or local filename using command-line arguments. The logic also now bypasses certain functions depending on the command-line arguments set. For example, if you specify the URL of the report that you want to download, the script doesn't prompt you to select a job and a report (since you've already done that). The prerequisites section in the README file explains how to run this sample (and others in this directory).
1 parent dfd5cfd commit c8e98d8

File tree

1 file changed

+116
-87
lines changed

1 file changed

+116
-87
lines changed

python/retrieve_reports.py

Lines changed: 116 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,36 @@
11
#!/usr/bin/python
22

3-
# Usage example:
4-
# python retrieve_reports.py
5-
6-
import httplib2
3+
###
4+
#
5+
# This script retrieves YouTube Reporting API reports. Use cases:
6+
# 1. If you specify a report URL, the script downloads that report.
7+
# 2. Otherwise, if you specify a job ID, the script retrieves a list of
8+
# available reports for that job and prompts you to select a report.
9+
# Then it retrieves that report as in case 1.
10+
# 3. Otherwise, the list retrieves a list of jobs for the user or,
11+
# if specified, the content owner that the user is acting on behalf of.
12+
# Then it prompts the user to select a job, and then executes case 2 and
13+
# then case 1.
14+
# Usage examples:
15+
# python retrieve_reports.py --content_owner_id=<CONTENT_OWNER_ID> --local_file=<LOCAL_FILE>
16+
# python retrieve_reports.py --content_owner_id=<CONTENT_OWNER_ID> --job_id=<JOB_ID> --local_file=<LOCAL_FILE>
17+
# python retrieve_reports.py --content_owner_id=<CONTENT_OWNER_ID> --report_url=<REPORT_URL> --local_file=<LOCAL_FILE>
18+
#
19+
###
20+
21+
import argparse
722
import os
8-
import sys
923

10-
from apiclient.discovery import build
11-
from apiclient.errors import HttpError
12-
from apiclient.http import MediaIoBaseDownload
24+
import google.oauth2.credentials
25+
import google_auth_oauthlib.flow
26+
from googleapiclient.discovery import build
27+
from googleapiclient.errors import HttpError
28+
from googleapiclient.http import MediaIoBaseDownload
29+
from google_auth_oauthlib.flow import InstalledAppFlow
1330
from io import FileIO
14-
from oauth2client.client import flow_from_clientsecrets
15-
from oauth2client.file import Storage
16-
from oauth2client.tools import argparser, run_flow
1731

1832

1933
# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
20-
2134
# the OAuth 2.0 information for this application, including its client_id and
2235
# client_secret. You can acquire an OAuth 2.0 client ID and client secret from
2336
# the {{ Google Cloud Console }} at
@@ -27,117 +40,133 @@
2740
# https://developers.google.com/youtube/v3/guides/authentication
2841
# For more information about the client_secrets.json file format, see:
2942
# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
30-
CLIENT_SECRETS_FILE = "client_secrets.json"
31-
32-
# This OAuth 2.0 access scope allows for read access to the YouTube Analytics monetary reports for
33-
# authenticated user's account. Any request that retrieves earnings or ad performance metrics must
34-
# use this scope.
35-
YOUTUBE_ANALYTICS_MONETARY_READ_SCOPE = (
36-
"https://www.googleapis.com/auth/yt-analytics-monetary.readonly")
37-
YOUTUBE_REPORTING_API_SERVICE_NAME = "youtubereporting"
38-
YOUTUBE_REPORTING_API_VERSION = "v1"
39-
40-
# This variable defines a message to display if the CLIENT_SECRETS_FILE is
41-
# missing.
42-
MISSING_CLIENT_SECRETS_MESSAGE = """
43-
WARNING: Please configure OAuth 2.0
44-
45-
To make this sample run you will need to populate the client_secrets.json file
46-
found at:
47-
%s
48-
with information from the APIs Console
49-
https://console.developers.google.com
50-
51-
For more information about the client_secrets.json file format, please visit:
52-
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
53-
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),
54-
CLIENT_SECRETS_FILE))
55-
56-
# Authorize the request and store authorization credentials.
57-
def get_authenticated_service(args):
58-
flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=YOUTUBE_ANALYTICS_MONETARY_READ_SCOPE,
59-
message=MISSING_CLIENT_SECRETS_MESSAGE)
43+
CLIENT_SECRETS_FILE = 'client_secret.json'
6044

61-
storage = Storage("%s-oauth2.json" % sys.argv[0])
62-
credentials = storage.get()
63-
64-
if credentials is None or credentials.invalid:
65-
credentials = run_flow(flow, storage, args)
66-
67-
return build(YOUTUBE_REPORTING_API_SERVICE_NAME, YOUTUBE_REPORTING_API_VERSION,
68-
http=credentials.authorize(httplib2.Http()))
45+
# This OAuth 2.0 access scope allows for read access to YouTube Analytics
46+
# monetary reports for the authenticated user's account. Any request that
47+
# retrieves earnings or ad performance metrics must use this scope.
48+
SCOPES = ['https://www.googleapis.com/auth/yt-analytics-monetary.readonly']
49+
API_SERVICE_NAME = 'youtubereporting'
50+
API_VERSION = 'v1'
6951

52+
# Authorize the request and store authorization credentials.
53+
def get_authenticated_service():
54+
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
55+
credentials = flow.run_console()
56+
return build(API_SERVICE_NAME, API_VERSION, credentials = credentials)
57+
58+
# Remove keyword arguments that are not set.
59+
def remove_empty_kwargs(**kwargs):
60+
good_kwargs = {}
61+
if kwargs is not None:
62+
for key, value in kwargs.iteritems():
63+
if value:
64+
good_kwargs[key] = value
65+
return good_kwargs
7066

7167
# Call the YouTube Reporting API's jobs.list method to retrieve reporting jobs.
72-
def list_reporting_jobs(youtube_reporting):
73-
results = youtube_reporting.jobs().list(
74-
).execute()
68+
def list_reporting_jobs(youtube_reporting, **kwargs):
69+
# Only include the onBehalfOfContentOwner keyword argument if the user
70+
# set a value for the --content_owner argument.
71+
kwargs = remove_empty_kwargs(**kwargs)
72+
73+
# Retrieve the reporting jobs for the user (or content owner).
74+
results = youtube_reporting.jobs().list(**kwargs).execute()
7575

76-
if "jobs" in results and results["jobs"]:
77-
jobs = results["jobs"]
76+
if 'jobs' in results and results['jobs']:
77+
jobs = results['jobs']
7878
for job in jobs:
79-
print ("Reporting job id: %s\n name: %s\n for reporting type: %s\n"
80-
% (job["id"], job["name"], job["reportTypeId"]))
79+
print ('Reporting job id: %s\n name: %s\n for reporting type: %s\n'
80+
% (job['id'], job['name'], job['reportTypeId']))
8181
else:
82-
print "No jobs found"
82+
print 'No jobs found'
8383
return False
8484

8585
return True
8686

87-
8887
# Call the YouTube Reporting API's reports.list method to retrieve reports created by a job.
89-
def retrieve_reports(youtube_reporting, job_id):
88+
def retrieve_reports(youtube_reporting, **kwargs):
89+
# Only include the onBehalfOfContentOwner keyword argument if the user
90+
# set a value for the --content_owner argument.
91+
kwargs = remove_empty_kwargs(**kwargs)
92+
93+
# Retrieve available reports for the selected job.
9094
results = youtube_reporting.jobs().reports().list(
91-
jobId=job_id
95+
**kwargs
9296
).execute()
9397

94-
if "reports" in results and results["reports"]:
95-
reports = results["reports"]
98+
if 'reports' in results and results['reports']:
99+
reports = results['reports']
96100
for report in reports:
97-
print ("Report from '%s' to '%s' downloadable at '%s'"
98-
% (report["startTime"], report["endTime"], report["downloadUrl"]))
101+
print ('Report dates: %s to %s\n download URL: %s\n'
102+
% (report['startTime'], report['endTime'], report['downloadUrl']))
99103

100104

101105
# Call the YouTube Reporting API's media.download method to download the report.
102-
def download_report(youtube_reporting, report_url):
106+
def download_report(youtube_reporting, report_url, local_file):
103107
request = youtube_reporting.media().download(
104-
resourceName=""
108+
resourceName=' '
105109
)
106110
request.uri = report_url
107-
fh = FileIO('report', mode='wb')
111+
fh = FileIO(local_file, mode='wb')
108112
# Stream/download the report in a single request.
109113
downloader = MediaIoBaseDownload(fh, request, chunksize=-1)
110114

111115
done = False
112116
while done is False:
113117
status, done = downloader.next_chunk()
114118
if status:
115-
print "Download %d%%." % int(status.progress() * 100)
116-
print "Download Complete!"
119+
print 'Download %d%%.' % int(status.progress() * 100)
120+
print 'Download Complete!'
117121

118122

119-
# Prompt the user to enter a job id for report retrieval. Then return the id.
123+
# Prompt the user to select a job and return the specified ID.
120124
def get_job_id_from_user():
121-
job_id = raw_input("Please enter the job id for the report retrieval: ")
122-
print ("You chose '%s' as the job Id for the report retrieval." % job_id)
125+
job_id = raw_input('Please enter the job id for the report retrieval: ')
126+
print ('You chose "%s" as the job Id for the report retrieval.' % job_id)
123127
return job_id
124128

125-
126-
# Prompt the user to enter a report URL for download. Then return the URL.
129+
# Prompt the user to select a report URL and return the specified URL.
127130
def get_report_url_from_user():
128-
report_url = raw_input("Please enter the report URL to download: ")
129-
print ("You chose '%s' to download." % report_url)
131+
report_url = raw_input('Please enter the report URL to download: ')
132+
print ('You chose "%s" to download.' % report_url)
130133
return report_url
131134

132-
if __name__ == "__main__":
133-
args = argparser.parse_args()
134-
135-
youtube_reporting = get_authenticated_service(args)
135+
if __name__ == '__main__':
136+
parser = argparse.ArgumentParser()
137+
parser.add_argument('--content_owner', default='',
138+
help='ID of content owner for which you are retrieving jobs and reports')
139+
parser.add_argument('--job_id', default=None,
140+
help='ID of the job for which you are retrieving reports. If not ' +
141+
'provided AND report_url is also not provided, then the script ' +
142+
'calls jobs.list() to retrieve a list of jobs.')
143+
parser.add_argument('--report_url', default=None,
144+
help='URL of the report to retrieve. If not specified, the script ' +
145+
'calls reports.list() to retrieve a list of reports for the ' +
146+
'selected job.')
147+
parser.add_argument('--local_file', default='yt_report.txt',
148+
help='The name of the local file where the downloaded report will be written.')
149+
args = parser.parse_args()
150+
151+
youtube_reporting = get_authenticated_service()
136152
try:
137-
if list_reporting_jobs(youtube_reporting):
138-
retrieve_reports(youtube_reporting, get_job_id_from_user())
139-
download_report(youtube_reporting, get_report_url_from_user())
153+
# If the user has not specified a job ID or report URL, retrieve a list
154+
# of available jobs and prompt the user to select one.
155+
if not args.job_id and not args.report_url:
156+
if list_reporting_jobs(youtube_reporting,
157+
onBehalfOfContentOwner=args.content_owner):
158+
args.job_id = get_job_id_from_user()
159+
160+
# If the user has not specified a report URL, retrieve a list of reports
161+
# available for the specified job and prompt the user to select one.
162+
if args.job_id and not args.report_url:
163+
retrieve_reports(youtube_reporting,
164+
jobId=args.job_id,
165+
onBehalfOfContentOwner=args.content_owner)
166+
args.report_url = get_report_url_from_user()
167+
168+
# Download the selected report.
169+
if args.report_url:
170+
download_report(youtube_reporting, args.report_url, args.local_file)
140171
except HttpError, e:
141-
print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
142-
else:
143-
print "Retrieved reports."
172+
print 'An HTTP error %d occurred:\n%s' % (e.resp.status, e.content)

0 commit comments

Comments
 (0)