Skip to content

Commit f1b9f38

Browse files
Update auth libraries and make script improvements
The oauth2client library is deprecated. This update changes the sample to use the google-auth and google-auth-oauthlib libraries instead. In addition, the code now has more flexible support for command-line arguments. For example, it does not set a default language by default ... you need to specify that on the command line. In addition, you can now add a localization without setting a default language or set a default language without adding a localization. (You cannot add localizations if the playlist doesn't have a default language at all, but once it does have a default language, you do not need to set it every subsequent time you run the script.)
1 parent 2fa8d26 commit f1b9f38

File tree

1 file changed

+122
-111
lines changed

1 file changed

+122
-111
lines changed

python/playlist_localizations.py

Lines changed: 122 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
#!/usr/bin/python
22

33
# Usage example:
4-
# python playlist_localizations.py --action='<action>' --playlist_id='<playlist_id>' --defaultlanguage='<default_language>' --language='<language>' --title='<title>' --description='<description>'
4+
# python playlist_localizations.py --action='<action>' --playlist_id='<playlist_id>' --default_language='<default_language>' --language='<language>' --title='<title>' --description='<description>'
55

6-
import httplib2
6+
import argparse
77
import os
8-
import sys
98

10-
from apiclient.discovery import build
11-
from apiclient.errors import HttpError
12-
from oauth2client.client import flow_from_clientsecrets
13-
from oauth2client.file import Storage
14-
from oauth2client.tools import argparser, run_flow
9+
import google.oauth2.credentials
10+
import google_auth_oauthlib.flow
11+
from googleapiclient.discovery import build
12+
from googleapiclient.errors import HttpError
13+
from google_auth_oauthlib.flow import InstalledAppFlow
1514

1615

1716
# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
@@ -25,142 +24,154 @@
2524
# https://developers.google.com/youtube/v3/guides/authentication
2625
# For more information about the client_secrets.json file format, see:
2726
# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
28-
CLIENT_SECRETS_FILE = "client_secrets.json"
27+
CLIENT_SECRETS_FILE = 'client_secret.json'
2928

3029
# This OAuth 2.0 access scope allows for full read/write access to the
3130
# authenticated user's account.
32-
YOUTUBE_READ_WRITE_SCOPE = "https://www.googleapis.com/auth/youtube"
33-
YOUTUBE_API_SERVICE_NAME = "youtube"
34-
YOUTUBE_API_VERSION = "v3"
35-
36-
# This variable defines a message to display if the CLIENT_SECRETS_FILE is
37-
# missing.
38-
MISSING_CLIENT_SECRETS_MESSAGE = """
39-
WARNING: Please configure OAuth 2.0
40-
41-
To make this sample run you will need to populate the client_secrets.json file
42-
found at:
43-
%s
44-
with information from the APIs Console
45-
https://console.developers.google.com
46-
47-
For more information about the client_secrets.json file format, please visit:
48-
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
49-
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),
50-
CLIENT_SECRETS_FILE))
31+
SCOPES = ['https://www.googleapis.com/auth/youtube']
32+
API_SERVICE_NAME = 'youtube'
33+
API_VERSION = 'v3'
5134

52-
# Authorize the request and store authorization credentials.
53-
def get_authenticated_service(args):
54-
flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=YOUTUBE_READ_WRITE_SCOPE,
55-
message=MISSING_CLIENT_SECRETS_MESSAGE)
56-
57-
storage = Storage("%s-oauth2.json" % sys.argv[0])
58-
credentials = storage.get()
59-
60-
if credentials is None or credentials.invalid:
61-
credentials = run_flow(flow, storage, args)
62-
63-
return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
64-
http=credentials.authorize(httplib2.Http()))
35+
ACTIONS = ('get', 'list', 'set')
6536

37+
# Authorize the request and store authorization credentials.
38+
def get_authenticated_service():
39+
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
40+
credentials = flow.run_console()
41+
return build(API_SERVICE_NAME, API_VERSION, credentials = credentials)
6642

6743
# Call the API's playlists.update method to update an existing playlist's default language,
6844
# localized title and description in a specific language.
69-
def set_playlist_localization(youtube, playlist_id, default_language, language, title, description):
45+
def set_playlist_localization(youtube, args):
46+
7047
results = youtube.playlists().list(
71-
part="snippet,localizations",
72-
id=playlist_id
48+
part='snippet,localizations',
49+
id=args.playlist_id
7350
).execute()
7451

75-
playlist = results["items"][0]
76-
# Ensure that a value is set for the resource's snippet.defaultLanguage property.
77-
playlist["snippet"]["defaultLanguage"] = default_language
78-
if "localizations" not in playlist:
79-
playlist["localizations"] = {}
80-
playlist["localizations"][language] = {
81-
"title": title,
82-
"description": description
83-
}
84-
52+
playlist = results['items'][0]
53+
54+
# If the language argument is set, set the localized title and description
55+
# for that language. The "title" and "description" arguments have default
56+
# values to make the script simpler to run as a demo. In an actual app, you
57+
# would likely want to set those arguments also.
58+
if args.language and args.language != '':
59+
if 'localizations' not in playlist:
60+
playlist['localizations'] = {}
61+
62+
playlist['localizations'][args.language] = {
63+
'title': args.title,
64+
'description': args.description
65+
}
66+
67+
# If the default language is set AND there is localized metadata for that
68+
# language, set the video's title and description to match the localized
69+
# title and description for the newly set default language.
70+
if args.default_language:
71+
playlist['snippet']['defaultLanguage'] = args.default_language
72+
if args.default_language in playlist['localizations']:
73+
playlist['snippet']['title'] = (
74+
playlist['localizations'][args.default_language]['title'])
75+
playlist['snippet']['description'] = (
76+
playlist['localizations'][args.default_language]['description'])
77+
78+
print(playlist)
79+
80+
# Update the playlist resource
8581
update_result = youtube.playlists().update(
86-
part="snippet,localizations",
82+
part='snippet,localizations',
8783
body=playlist
8884
).execute()
8985

90-
localization = update_result["localizations"][language]
91-
92-
print ("Updated playlist '%s' default language to '%s', localized title to '%s'"
93-
" and description to '%s' in language '%s'"
94-
% (playlist_id, localization["title"], localization["description"], language))
95-
86+
# Print the actions taken by running the script.
87+
if args.language:
88+
for language in update_result['localizations']:
89+
# Languages with locales, like "pt-br" are returned as pt-BR in metadata.
90+
# This ensures that the language specified when running the script can be
91+
# matched to the language returned in the metadata.
92+
if language.lower() == args.language.lower():
93+
localization = update_result['localizations'][args.language]
94+
print ('Updated playlist \'%s\' localized title to \'%s\''
95+
' and description to \'%s\' in language \'%s\'' %
96+
(args.playlist_id,
97+
localization['title'],
98+
localization['description'],
99+
args.language))
100+
break
101+
102+
if (args.default_language and
103+
args.default_language == update_result['snippet']['defaultLanguage']):
104+
print 'Updated default language to %s' % args.default_language
96105

97106
# Call the API's playlists.list method to retrieve an existing playlist localization.
98107
# If the localized text is not available in the requested language,
99108
# this method will return text in the default language.
100-
def get_playlist_localization(youtube, playlist_id, language):
109+
def get_playlist_localization(youtube, args):
101110
results = youtube.playlists().list(
102-
part="snippet",
103-
id=playlist_id,
104-
hl=language
111+
part='snippet',
112+
id=args.playlist_id,
113+
hl=args.language
105114
).execute()
106115

107116
# The localized object contains localized text if the hl parameter specified
108117
# a language for which localized text is available. Otherwise, the localized
109118
# object will contain metadata in the default language.
110-
localized = results["items"][0]["snippet"]["localized"]
119+
localized = results['items'][0]['snippet']['localized']
111120

112-
print ("Playlist title is '%s' and description is '%s' in language '%s'"
113-
% (localized["title"], localized["description"], language))
121+
print ('Playlist title is "%s" and description is "%s" in language "%s"'
122+
% (localized['title'], localized['description'], args.language))
114123

115124

116-
# Call the API's playlists.list method to list the existing playlist localizations.
117-
def list_playlist_localizations(youtube, playlist_id):
125+
# Call the API's playlists.list method to list existing localizations
126+
# for the playlist.
127+
def list_playlist_localizations(youtube, args):
118128
results = youtube.playlists().list(
119-
part="snippet,localizations",
120-
id=playlist_id
129+
part='snippet,localizations',
130+
id=args.playlist_id
121131
).execute()
122132

123-
localizations = results["items"][0]["localizations"]
124-
125-
for language, localization in localizations.iteritems():
126-
print ("Playlist title is '%s' and description is '%s' in language '%s'"
127-
% (localization["title"], localization["description"], language))
128-
129-
130-
if __name__ == "__main__":
131-
# The "action" option specifies the action to be processed.
132-
argparser.add_argument("--action", help="Action")
133-
# The "playlist_id" option specifies the ID of the selected YouTube playlist.
134-
argparser.add_argument("--playlist_id",
135-
help="ID for playlist for which the localization will be applied.")
136-
# The "default_language" option specifies the language of the playlist's default metadata.
137-
argparser.add_argument("--default_language", help="Default language of the playlist to update.",
138-
default="en")
139-
# The "language" option specifies the language of the localization that is being processed.
140-
argparser.add_argument("--language", help="Language of the localization.", default="de")
141-
# The "title" option specifies the localized title of the playlist to be set.
142-
argparser.add_argument("--title", help="Localized title of the playlist to be set.",
143-
default="Localized Title")
144-
# The "description" option specifies the localized description of the playlist to be set.
145-
argparser.add_argument("--description", help="Localized description of the playlist to be set.",
146-
default="Localized Description")
147-
148-
args = argparser.parse_args()
149-
150-
if not args.playlist_id:
151-
exit("Please specify playlist id using the --playlist_id= parameter.")
152-
153-
youtube = get_authenticated_service(args)
133+
if 'localizations' in results['items'][0]:
134+
localizations = results['items'][0]['localizations']
135+
136+
for language, localization in localizations.iteritems():
137+
print ('Playlist title is "%s" and description is "%s" in language "%s"'
138+
% (localization['title'], localization['description'], language))
139+
else:
140+
print 'There aren\'t any localizations for this playlist yet.'
141+
142+
143+
if __name__ == '__main__':
144+
parser = argparse.ArgumentParser()
145+
# The action to be processed: 'get', 'list', and 'set' are supported.
146+
parser.add_argument('--action', required=True, help='Action', choices=ACTIONS)
147+
# The ID of the selected YouTube olaylist.
148+
parser.add_argument('--playlist_id',
149+
help='The playlist ID for which localizations are being set or retrieved.',
150+
required=True)
151+
# The langauge of the playlist's default metadata.
152+
parser.add_argument('--default_language',
153+
help='Default language to set for the playlist.')
154+
# The language of the localization that is being set or retrieved.
155+
parser.add_argument('--language', help='Language of the localization.')
156+
# The localized title to set in the specified language.
157+
parser.add_argument('--title',
158+
help='Localized title to be set for the playlist.',
159+
default='Localized Title')
160+
# The localized description to set in the specified language.
161+
parser.add_argument('--description',
162+
help='Localized description to be set for the playlist.',
163+
default='Localized Description')
164+
165+
args = parser.parse_args()
166+
167+
youtube = get_authenticated_service()
168+
154169
try:
155170
if args.action == 'set':
156-
set_playlist_localization(youtube, args.playlist_id, args.default_language, args.language, args.title, args.description)
171+
set_playlist_localization(youtube, args)
157172
elif args.action == 'get':
158-
get_playlist_localization(youtube, args.playlist_id, args.language)
173+
get_playlist_localization(youtube, args)
159174
elif args.action == 'list':
160-
list_playlist_localizations(youtube, args.playlist_id)
161-
else:
162-
exit("Please specify a valid action using the --action= parameter.")
175+
list_playlist_localizations(youtube, args)
163176
except HttpError, e:
164-
print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
165-
else:
166-
print "Set and retrieved localized metadata for a playlist."
177+
print 'An HTTP error %d occurred:\n%s' % (e.resp.status, e.content)

0 commit comments

Comments
 (0)