Skip to content

Commit d598fb3

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. Finally, the --mine argument lets you list all of your channel's sections and their localized values, making it easier to then use the script to add a localization for a single channel section.
1 parent c8e98d8 commit d598fb3

File tree

1 file changed

+152
-101
lines changed

1 file changed

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

3-
# Usage example:
3+
# Retrieve or set localized channel section metadata.
4+
# See the Prerequisites section in the README file in this directory
5+
# for more information about running this sample locally.
6+
7+
# Usage examples:
8+
# python channel_sections_localizations.py --action=list --mine=True
49
# python channel_sections_localizations.py --action='<action>' --channel_section_id='<channel_section_id>' --default_language='<default_language>' --language='<language>' --title='<title>'
510

6-
import httplib2
11+
import argparse
712
import os
8-
import sys
13+
import re
914

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
15+
import google.oauth2.credentials
16+
import google_auth_oauthlib.flow
17+
from googleapiclient.discovery import build
18+
from googleapiclient.errors import HttpError
19+
from google_auth_oauthlib.flow import InstalledAppFlow
1520

1621

1722
# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
@@ -25,135 +30,181 @@
2530
# https://developers.google.com/youtube/v3/guides/authentication
2631
# For more information about the client_secrets.json file format, see:
2732
# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
28-
CLIENT_SECRETS_FILE = "client_secrets.json"
33+
CLIENT_SECRETS_FILE = 'client_secret.json'
2934

3035
# This OAuth 2.0 access scope allows for full read/write access to the
3136
# 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))
51-
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)
37+
SCOPES = ['https://www.googleapis.com/auth/youtube']
38+
API_SERVICE_NAME = 'youtube'
39+
API_VERSION = 'v3'
6240

63-
return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
64-
http=credentials.authorize(httplib2.Http()))
41+
ACTIONS = ('get', 'list', 'set')
6542

43+
# Authorize the request and store authorization credentials.
44+
def get_authenticated_service():
45+
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
46+
credentials = flow.run_console()
47+
return build(API_SERVICE_NAME, API_VERSION, credentials = credentials)
6648

6749
# Call the API's channelSections.update method to update an existing channel section's
6850
# default language, and localized title in a specific language.
69-
def set_channel_section_localization(youtube, channel_section_id, default_language, language, title):
51+
def set_channel_section_localization(youtube, args):
52+
53+
# Retrieve the snippet and localizations for the channel section.
7054
results = youtube.channelSections().list(
71-
part="snippet,localizations",
72-
id=channel_section_id
55+
part='snippet,contentDetails,localizations',
56+
id=args.channel_section_id
7357
).execute()
7458

75-
channel_section = results["items"][0]
76-
# Ensure that a value is set for the resource's snippet.defaultLanguage property.
77-
channel_section["snippet"]["defaultLanguage"] = default_language
78-
if "localizations" not in channel_section:
79-
channel_section["localizations"] = {}
80-
channel_section["localizations"][language] = {
81-
"title": title
82-
}
59+
channel_section = results['items'][0]
60+
61+
# If the language argument is set, set the localized title for that language.
62+
# The "title" argument has a default value to make the script simpler to run
63+
# as a demo. But in an actual app, you would likely want to set its value.
64+
if args.language and args.language != '':
65+
if 'localizations' not in channel_section:
66+
channel_section['localizations'] = {}
67+
68+
channel_section['localizations'][args.language] = {
69+
'title': args.title,
70+
}
71+
72+
# If the default language is set AND there is localized metadata for that
73+
# language, set the channel section's title and description to match the
74+
# localized title and description for the newly set default language.
75+
if args.default_language:
76+
channel_section['snippet']['defaultLanguage'] = args.default_language
77+
if args.default_language in channel_section['localizations']:
78+
channel_section['snippet']['title'] = (
79+
channel_section['localizations'][args.default_language]['title'])
8380

8481
update_result = youtube.channelSections().update(
85-
part="snippet,localizations",
82+
part='snippet,contentDetails,localizations',
8683
body=channel_section
8784
).execute()
8885

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

95101
# Call the API's channelSections.list method to retrieve an existing channel section localization.
96102
# If the localized text is not available in the requested language,
97103
# this method will return text in the default language.
98-
def get_channel_section_localization(youtube, channel_section_id, language):
104+
def get_channel_section_localization(youtube, args):
99105
results = youtube.channelSections().list(
100-
part="snippet",
101-
id=channel_section_id,
102-
hl=language
106+
part='snippet',
107+
id=args.channel_section_id,
108+
hl=args.language
103109
).execute()
104110

105111
# The localized object contains localized text if the hl parameter specified
106112
# a language for which localized text is available. Otherwise, the localized
107113
# object will contain metadata in the default language.
108-
localized = results["items"][0]["snippet"]["localized"]
109-
110-
print "Channel section title is '%s' in language '%s'" % (localized["title"], language)
114+
localized = results['items'][0]['snippet']['localized']
111115

116+
print('The channel section\'s title is \'%s\' in language \'%s\'.' %
117+
(localized['title'], language))
112118

113-
# Call the API's channelSections.list method to list the existing channel section localizations.
114-
def list_channel_section_localizations(youtube, channel_section_id):
119+
# Call the API's channelSections.list method to list all existing localizations
120+
# for the channel section.
121+
def list_channel_section_localizations(youtube, args):
115122
results = youtube.channelSections().list(
116-
part="snippet,localizations",
117-
id=channel_section_id
123+
part='snippet,localizations',
124+
id=args.channel_section_id
118125
).execute()
119126

120-
localizations = results["items"][0]["localizations"]
127+
localizations = results['items'][0]['localizations']
121128

122129
for language, localization in localizations.iteritems():
123-
print "Channel section title is '%s' in language '%s'" % (localization["title"], language)
124-
125-
126-
if __name__ == "__main__":
127-
# The "action" option specifies the action to be processed.
128-
argparser.add_argument("--action", help="Action")
129-
# The "channel_section_id" option specifies the ID of the selected YouTube channel section.
130-
argparser.add_argument("--channel_section_id",
131-
help="ID for channel section for which the localization will be applied.")
132-
# The "default_language" option specifies the language of the channel section's default metadata.
133-
argparser.add_argument("--default_language",
134-
help="Default language of the channel section to update.", default="en")
135-
# The "language" option specifies the language of the localization that is being processed.
136-
argparser.add_argument("--language", help="Language of the localization.", default="de")
137-
# The "title" option specifies the localized title of the channel section to be set.
138-
argparser.add_argument("--title", help="Localized title of the channel section to be set.",
139-
default="Localized Title")
140-
141-
args = argparser.parse_args()
142-
143-
if not args.channel_section_id:
144-
exit("Please specify channel section id using the --channel_section_id= parameter.")
145-
146-
youtube = get_authenticated_service(args)
130+
print('The channel section title is \'%s\' in language \'%s\'.' %
131+
(localization['title'], language))
132+
133+
# Call the API's channelSections.list method to list localizations for all
134+
# channel sections in the authorizing user\'s channel. This function might
135+
# be called as a way of identifying the ID of the section you actually want
136+
# to update.
137+
def list_my_channel_section_localizations(youtube, args):
138+
results = youtube.channelSections().list(
139+
part='snippet,localizations',
140+
mine=True,
141+
).execute()
142+
143+
print(results)
144+
145+
for i in range(0, len(results['items'])):
146+
item = results['items'][i]
147+
print str(item['snippet']['position']) + ':'
148+
print ' ID: ' + item['id']
149+
print ' Type: ' + item['snippet']['type']
150+
if ('title' in item['snippet'] and item['snippet']['title']):
151+
print ' Title: ' + str(item['snippet']['title'])
152+
153+
if 'localizations' in results['items'][i]:
154+
localizations = results['items'][i]['localizations']
155+
print(' Localized titles by language:')
156+
for language, localization in localizations.iteritems():
157+
print(' ' + language + ': ' + localization['title'])
158+
else:
159+
print(' No localizations. :(\n')
160+
161+
#for language, localization in localizations.iteritems():
162+
# print('The channel section title is \'%s\' in language \'%s\'.' %
163+
# (localization['title'], language))
164+
165+
166+
if __name__ == '__main__':
167+
parser = argparse.ArgumentParser()
168+
# The 'action' option specifies the action to be processed.
169+
parser.add_argument('--action', choices=ACTIONS, required=True,
170+
help='The type of operation. Supported values are: "get", "list", "set"')
171+
# The ID of the channel section for which data is being retrieved or updated.
172+
parser.add_argument('--channel_section_id',
173+
help='ID of channel section for which localized data is being ' +
174+
'retrieved or updated.')
175+
# The language of the channel section's default metadata.
176+
parser.add_argument('--default_language',
177+
help='Default language of the channel section to update.')
178+
# The language of the localization that is being processed.
179+
parser.add_argument('--language', help='Language of the localized metadata.')
180+
# The localized channel section title for the specified language.
181+
parser.add_argument('--title',
182+
help='Localized title of the channel section to be set.',
183+
default='Localized Title')
184+
# The language of the channel section's default metadata.
185+
parser.add_argument('--mine', type=bool, default=False,
186+
help='List localizations for all of my channel sections.')
187+
188+
args = parser.parse_args()
189+
190+
if not args.channel_section_id and not args.mine:
191+
exit('You must either specify a channel section ID using the ' +
192+
'--channel_section_id argument or retrieve localizations ' +
193+
'for all of your channel sections by setting the --mine ' +
194+
'argument to True.')
195+
196+
youtube = get_authenticated_service()
147197
try:
148198
if args.action == 'set':
149-
set_channel_section_localization(youtube, args.channel_section_id, args.default_language, args.language, args.title)
199+
set_channel_section_localization(youtube, args)
150200
elif args.action == 'get':
151-
get_channel_section_localization(youtube, args.channel_section_id, args.language)
201+
get_channel_section_localization(youtube, args)
152202
elif args.action == 'list':
153-
list_channel_section_localizations(youtube, args.channel_section_id)
203+
if args.mine:
204+
list_my_channel_section_localizations(youtube, args)
205+
else:
206+
list_channel_section_localizations(youtube, args)
154207
else:
155-
exit("Please specify a valid action using the --action= parameter.")
208+
exit('Please specify a valid action using the --action= parameter.')
156209
except HttpError, e:
157-
print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
158-
else:
159-
print "Set and retrieved localized metadata for a channel section."
210+
print 'An HTTP error %d occurred:\n%s' % (e.resp.status, e.content)

0 commit comments

Comments
 (0)