My favorites | Sign in
Project Logo
                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


__author__ = ('api.jscudder (Jeffrey Scudder), '
'api.jhartmann@gmail.com (Jochen Hartmann)')


import wsgiref.handlers
import urllib
import cgi
from google.appengine.ext import webapp
from google.appengine.api import users
from google.appengine.ext import db
import gdata.service
import gdata.youtube
import gdata.youtube.service
import gdata.media
import gdata.geo
import gdata.urlfetch

gdata.service.http_request_handler = gdata.urlfetch


class StoredToken(db.Model):
user_email = db.StringProperty(required=True)
session_token = db.StringProperty(required=True)
developer_key = db.StringProperty()


class AuthSub(webapp.RequestHandler):

def __init__(self):
self.current_user = None
self.client = None
self.token = None
self.feed_url = 'http://gdata.youtube.com/feeds/api/users/default/uploads'
self.youtube_scope = 'http://gdata.youtube.com'
self.developer_key = None
self.upload_status = None
self.new_video_id = None

def get(self):
self.client = gdata.youtube.service.YouTubeService()
self.my_app_domain = 'http://' + self.request._environ['HTTP_HOST']
self.response.out.write("""<html><head><title>
hello_browser_based_upload: Browser based video upload demo</title>
<link type="text/css" rel="stylesheet" href="/stylesheets/main.css" />
""")
# Get the current user
self.current_user = users.GetCurrentUser()
self.response.out.write('</head><body>')
# Allow the user to sign in or sign out



for param in self.request.query.split('&'):
if param.startswith('token'):
self.token = param.split('=')[1]
elif param.startswith('feed_url'):
self.feed_url = urllib.unquote_plus(param.split('=')[1])
elif param.startswith('status'):
self.upload_status = urllib.unquote_plus(param.split('=')[1])
elif param.startswith('id'):
self.new_video_id = urllib.unquote_plus(param.split('=')[1])

if self.current_user:
self.response.out.write('<a href="%s">Sign Out</a><br /><br />' % (
users.CreateLogoutURL(self.request.uri)))
if self.LookupToken():
self.response.out.write('<div id="video_listing">')

if self.upload_status:
self.response.out.write('<span class="video_keywords">Video upload'
' status: %s<br />' % self.upload_status)
self.response.out.write('New video Id: %s</span><br /><br />' %
self.new_video_id)

self.FetchFeed()
if self.LookupDevKey():
self.DisplayUploadForm()
self.DisplayChangeDevKeyForm()

else:
self.DisplayDevKeyForm()
self.response.out.write('</div>')

# not authenticated...
else:
if self.token:
self.UpgradeAndStoreToken()
self.redirect('/')
else:
# request a one-time token
self.response.out.write('<div id="sidebar"> '
'<div id="scopes"><h4>Request a token</h4><ul>')
self.response.out.write('<li><a href="%s">YouTube API</a></li>' % (
self.client.GenerateAuthSubURL(
self.my_app_domain, self.youtube_scope, secure=False, session=True))
)
else:
self.response.out.write('<a href="%s">Sign In</a><br />' % (
users.CreateLoginURL(self.request.uri)))



def FetchFeed(self):
# Attempt to fetch the feed.
if not self.client:
self.client = gdata.youtube.service.YouTubeService()

try:
feed = self.client.GetYouTubeVideoFeed(self.feed_url)

self.response.out.write(
'<span class="listing_title">My Videos</span><br /><br />')
self.response.out.write(
'<table border="0" cellpadding="2" cellspacing="0">')

for entry in feed.entry:
self.response.out.write('<tr><td class="thumbnail">')
if len(entry.media.thumbnail) > 0:
self.response.out.write(
'<img src="%s"></p>' % entry.media.thumbnail[0].url)
else:
self.response.out.write('&nbsp;')
self.response.out.write('</td>')

self.response.out.write('<td valign="top">')
self.response.out.write(
'<span class="video_title">%s </span><br />' % entry.title.text)
self.response.out.write(
'<span class="video_description">%s </span><br />' %
entry.media.description)
self.response.out.write(
'<span class="video_category"><strong>%s</strong></span>' %
entry.media.category[0])
self.response.out.write('<span class="video_published"> | published '
'on %s</span><br />' % (entry.published.text.split('T')[0] + ' at ' +
entry.published.text.split('T')[1][:5] + ' PST'))
self.response.out.write('<span class="video_keywords"><strong>Keywords:'
'</strong> %s </span><br />' % entry.media.keywords)


self.response.out.write('</td></tr>')
self.response.out.write(
'<tr><td height="20" colspan="2"><hr class="slight"/></tr>')

self.response.out.write('</table><br />')

except gdata.service.RequestError, request_error:
# If fetching fails, then tell the user that they need to login to
# authorize this app by logging in at the following URL.
if request_error[0]['status'] == 401:
self.response.out.write(
'<div id="sidebar"><div id="scopes"><h4>Request a token</h4><ul>')
self.response.out.write(
'<li><a href="%s">YouTube API</a></li>' % (
self.client.GenerateAuthSubURL(
self.my_app_domain, self.youtube_scope, secure=False, session=True))
)
else:
self.response.out.write(
'Something else went wrong, here is the error object: %s ' % (
str(request_error[0])))

def post(self):
self.response.out.write("""<html><head><title>
hello_browser_based_upload: Storing developer key</title>
<link type="text/css" rel="stylesheet" href="/stylesheets/main.css" />
</head><body>""")

self.current_user = users.GetCurrentUser()
developer_key = cgi.escape(self.request.get('developer_key'))
self.response.out.write("<p>Storing developer key: %s" % developer_key)
# look up token
stored_tokens = StoredToken.gql('WHERE user_email = :1',
self.current_user.email())
for token in stored_tokens:
new_token = StoredToken(user_email=token.user_email,
session_token=token.session_token,
developer_key=developer_key)
token.delete()
new_token.put()
self.response.out.write("<br /><br /><a href="">Go back to main page</a>")

def UpgradeAndStoreToken(self):
self.client.auth_token = self.token
self.client.UpgradeToSessionToken()
if self.current_user:
new_token = StoredToken(user_email=self.current_user.email(),
session_token=self.client.GetAuthSubToken())
new_token.put()

def LookupToken(self):
if self.feed_url and self.current_user:
stored_tokens = StoredToken.gql('WHERE user_email = :1',
self.current_user.email())
for token in stored_tokens:
self.client.auth_token = token.session_token
return True

def LookupDevKey(self):
if self.current_user:
stored_tokens = StoredToken.gql('WHERE user_email = :1',
self.current_user.email())
for token in stored_tokens:
if token.developer_key:
self.client.developer_key = token.developer_key
return True

def DisplayUploadForm(self):
self.response.out.write("""<br /><div id="upload_form">
<strong>Upload a new Video</strong><br /><br />
<form action="/upload" method="post" >
Video Title<br /><input type="text" name="video_title" /><br /><br />
Video Description<br /><textarea cols="50" name="video_description">
</textarea><br /><br />
Select a Category <select name="video_category">
<option value="Autos">Autos &amp; Vehicles</option>
<option value="Music">Music</option>
<option value="Animals">Pets &amp; Animals</option>
<option value="Sports">Sports</option>
<option value="Travel">Travel &amp; Events</option>
<option value="Games">Gadgets &amp; Games</option>
<option value="Comedy">Comedy</option>
<option value="People">People &amp; Blogs</option>
<option value="News">News &amp; Politics</option>
<option value="Entertainment">Entertainment</option>
<option value="Education">Education</option>
<option value="Howto">Howto &amp; Style</option>
<option value="Nonprofit">Nonprofit &amp; Activism</option>
<option value="Tech">Science &amp; Technology</option>',
</select><br /><br />
Enter some tags to describe your video <em>(separated by spaces)</em>
<br /><br />
<input type="text" name="video_tags" />
<input type="submit" value="Go"/>
</form></div>
""")

def DisplayDevKeyForm(self):
self.response.out.write("""<br /><div id="dev_key_form">
<form action="/" method="post" >
Enter your developer key <input type="text" name="developer_key" />
<input type="submit" value="Go"/>
</form></div>
""")

def DisplayChangeDevKeyForm(self):
self.response.out.write("""<br /><hr class="slight"><br />
<div id="dev_key_form">
Current Developer Key stored:<br />
<form action="/" method="post" >
<input type="text" name="developer_key" value="%s" size="90"/><br />
<input type="submit" value="Store as New"/>
</form></div>""" %
self.client.additional_headers['X-GData-Key'].split('=')[1])

def main():
application = webapp.WSGIApplication([('/.*', AuthSub),], debug=True)
wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
main()
Show details Hide details

Change log

r43 by api.jhartmann on Jun 12, 2008   Diff
Updated all code samples with the latest
version of the Python Client library which
is up to date (up to r415)
Go to: 
Project members, sign in to write a code review

Older revisions

r41 by api.jhartmann on May 28, 2008   Diff
removed ability to store multiple
token scopes
r35 by api.jhartmann on May 27, 2008   Diff
fixes with udpated datamodel
r14 by api.jhartmann on May 26, 2008   Diff
App Engine app
All revisions of this file

File info

Size: 10505 bytes, 276 lines
Hosted by Google Code