1
1
#!/usr/bin/python
2
2
3
+ import argparse
3
4
import httplib
4
5
import httplib2
5
6
import os
6
7
import random
7
- import sys
8
8
import time
9
9
10
- from apiclient . discovery import build
11
- from apiclient . errors import HttpError
12
- from apiclient . http import MediaFileUpload
13
- from oauth2client . client import flow_from_clientsecrets
14
- from oauth2client . file import Storage
15
- from oauth2client . tools import argparser , run_flow
10
+ import google . oauth2 . credentials
11
+ import google_auth_oauthlib . flow
12
+ from googleapiclient . discovery import build
13
+ from googleapiclient . errors import HttpError
14
+ from googleapiclient . http import MediaFileUpload
15
+ from google_auth_oauthlib . flow import InstalledAppFlow
16
16
17
17
18
18
# Explicitly tell the underlying HTTP transport library not to retry, since
42
42
# https://developers.google.com/youtube/v3/guides/authentication
43
43
# For more information about the client_secrets.json file format, see:
44
44
# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
45
- CLIENT_SECRETS_FILE = "client_secrets .json"
45
+ CLIENT_SECRETS_FILE = 'client_secret .json'
46
46
47
47
# This OAuth 2.0 access scope allows an application to upload files to the
48
48
# authenticated user's YouTube channel, but doesn't allow other types of access.
49
- YOUTUBE_UPLOAD_SCOPE = " https://www.googleapis.com/auth/youtube.upload"
50
- YOUTUBE_API_SERVICE_NAME = " youtube"
51
- YOUTUBE_API_VERSION = "v3"
49
+ SCOPES = [ ' https://www.googleapis.com/auth/youtube.upload' ]
50
+ API_SERVICE_NAME = ' youtube'
51
+ API_VERSION = 'v3'
52
52
53
- # This variable defines a message to display if the CLIENT_SECRETS_FILE is
54
- # missing.
55
- MISSING_CLIENT_SECRETS_MESSAGE = """
56
- WARNING: Please configure OAuth 2.0
53
+ VALID_PRIVACY_STATUSES = ('public' , 'private' , 'unlisted' )
57
54
58
- To make this sample run you will need to populate the client_secrets.json file
59
- found at:
60
55
61
- %s
62
-
63
- with information from the {{ Cloud Console }}
64
- {{ https://cloud.google.com/console }}
65
-
66
- For more information about the client_secrets.json file format, please visit:
67
- https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
68
- """ % os .path .abspath (os .path .join (os .path .dirname (__file__ ),
69
- CLIENT_SECRETS_FILE ))
70
-
71
- VALID_PRIVACY_STATUSES = ("public" , "private" , "unlisted" )
72
-
73
-
74
- def get_authenticated_service (args ):
75
- flow = flow_from_clientsecrets (CLIENT_SECRETS_FILE ,
76
- scope = YOUTUBE_UPLOAD_SCOPE ,
77
- message = MISSING_CLIENT_SECRETS_MESSAGE )
78
-
79
- storage = Storage ("%s-oauth2.json" % sys .argv [0 ])
80
- credentials = storage .get ()
81
-
82
- if credentials is None or credentials .invalid :
83
- credentials = run_flow (flow , storage , args )
84
-
85
- return build (YOUTUBE_API_SERVICE_NAME , YOUTUBE_API_VERSION ,
86
- http = credentials .authorize (httplib2 .Http ()))
56
+ # Authorize the request and store authorization credentials.
57
+ def get_authenticated_service ():
58
+ flow = InstalledAppFlow .from_client_secrets_file (CLIENT_SECRETS_FILE , SCOPES )
59
+ credentials = flow .run_console ()
60
+ return build (API_SERVICE_NAME , API_VERSION , credentials = credentials )
87
61
88
62
def initialize_upload (youtube , options ):
89
63
tags = None
90
64
if options .keywords :
91
- tags = options .keywords .split ("," )
65
+ tags = options .keywords .split (',' )
92
66
93
67
body = dict (
94
68
snippet = dict (
@@ -104,14 +78,14 @@ def initialize_upload(youtube, options):
104
78
105
79
# Call the API's videos.insert method to create and upload the video.
106
80
insert_request = youtube .videos ().insert (
107
- part = "," .join (body .keys ()),
81
+ part = ',' .join (body .keys ()),
108
82
body = body ,
109
83
# The chunksize parameter specifies the size of each chunk of data, in
110
84
# bytes, that will be uploaded at a time. Set a higher value for
111
85
# reliable connections as fewer chunks lead to faster uploads. Set a lower
112
86
# value for better recovery on less reliable connections.
113
87
#
114
- # Setting " chunksize" equal to -1 in the code below means that the entire
88
+ # Setting ' chunksize' equal to -1 in the code below means that the entire
115
89
# file will be uploaded in a single HTTP request. (If the upload fails,
116
90
# it will still be retried where it left off.) This is usually a best
117
91
# practice, but if you're using Python older than 2.6 or if you're
@@ -124,58 +98,57 @@ def initialize_upload(youtube, options):
124
98
125
99
# This method implements an exponential backoff strategy to resume a
126
100
# failed upload.
127
- def resumable_upload (insert_request ):
101
+ def resumable_upload (request ):
128
102
response = None
129
103
error = None
130
104
retry = 0
131
105
while response is None :
132
106
try :
133
- print " Uploading file..."
134
- status , response = insert_request .next_chunk ()
107
+ print ' Uploading file...'
108
+ status , response = request .next_chunk ()
135
109
if response is not None :
136
110
if 'id' in response :
137
- print " Video id '%s' was successfully uploaded." % response ['id' ]
111
+ print ' Video id "%s" was successfully uploaded.' % response ['id' ]
138
112
else :
139
- exit (" The upload failed with an unexpected response: %s" % response )
113
+ exit (' The upload failed with an unexpected response: %s' % response )
140
114
except HttpError , e :
141
115
if e .resp .status in RETRIABLE_STATUS_CODES :
142
- error = " A retriable HTTP error %d occurred:\n %s" % (e .resp .status ,
116
+ error = ' A retriable HTTP error %d occurred:\n %s' % (e .resp .status ,
143
117
e .content )
144
118
else :
145
119
raise
146
120
except RETRIABLE_EXCEPTIONS , e :
147
- error = " A retriable error occurred: %s" % e
121
+ error = ' A retriable error occurred: %s' % e
148
122
149
123
if error is not None :
150
124
print error
151
125
retry += 1
152
126
if retry > MAX_RETRIES :
153
- exit (" No longer attempting to retry." )
127
+ exit (' No longer attempting to retry.' )
154
128
155
129
max_sleep = 2 ** retry
156
130
sleep_seconds = random .random () * max_sleep
157
- print " Sleeping %f seconds and then retrying..." % sleep_seconds
131
+ print ' Sleeping %f seconds and then retrying...' % sleep_seconds
158
132
time .sleep (sleep_seconds )
159
133
160
134
if __name__ == '__main__' :
161
- argparser .add_argument ("--file" , required = True , help = "Video file to upload" )
162
- argparser .add_argument ("--title" , help = "Video title" , default = "Test Title" )
163
- argparser .add_argument ("--description" , help = "Video description" ,
164
- default = "Test Description" )
165
- argparser .add_argument ("--category" , default = "22" ,
166
- help = "Numeric video category. " +
167
- "See https://developers.google.com/youtube/v3/docs/videoCategories/list" )
168
- argparser .add_argument ("--keywords" , help = "Video keywords, comma separated" ,
169
- default = "" )
170
- argparser .add_argument ("--privacyStatus" , choices = VALID_PRIVACY_STATUSES ,
171
- default = VALID_PRIVACY_STATUSES [0 ], help = "Video privacy status." )
172
- args = argparser .parse_args ()
173
-
174
- if not os .path .exists (args .file ):
175
- exit ("Please specify a valid file using the --file= parameter." )
176
-
177
- youtube = get_authenticated_service (args )
135
+ parser = argparse .ArgumentParser ()
136
+ parser .add_argument ('--file' , required = True , help = 'Video file to upload' )
137
+ parser .add_argument ('--title' , help = 'Video title' , default = 'Test Title' )
138
+ parser .add_argument ('--description' , help = 'Video description' ,
139
+ default = 'Test Description' )
140
+ parser .add_argument ('--category' , default = '22' ,
141
+ help = 'Numeric video category. ' +
142
+ 'See https://developers.google.com/youtube/v3/docs/videoCategories/list' )
143
+ parser .add_argument ('--keywords' , help = 'Video keywords, comma separated' ,
144
+ default = '' )
145
+ parser .add_argument ('--privacyStatus' , choices = VALID_PRIVACY_STATUSES ,
146
+ default = 'private' , help = 'Video privacy status.' )
147
+ args = parser .parse_args ()
148
+
149
+ youtube = get_authenticated_service ()
150
+
178
151
try :
179
152
initialize_upload (youtube , args )
180
153
except HttpError , e :
181
- print " An HTTP error %d occurred:\n %s" % (e .resp .status , e .content )
154
+ print ' An HTTP error %d occurred:\n %s' % (e .resp .status , e .content )
0 commit comments