Commit | Line | Data |
---|---|---|
7f4ebeed | 1 | # GNU MediaGoblin -- federated, autonomous media hosting |
cf29e8a8 | 2 | # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. |
9a16e16f SS |
3 | # |
4 | # This program is free software: you can redistribute it and/or modify | |
5 | # it under the terms of the GNU Affero General Public License as published by | |
6 | # the Free Software Foundation, either version 3 of the License, or | |
7 | # (at your option) any later version. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU Affero General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
fb2fbe2c | 17 | import logging |
64712915 | 18 | import datetime |
52359e91 | 19 | |
3a8c3a38 | 20 | from mediagoblin import messages, mg_globals |
b0c8328e | 21 | from mediagoblin.db.models import (MediaEntry, Collection, CollectionItem, |
af008743 | 22 | User) |
152a3bfa | 23 | from mediagoblin.tools.response import render_to_response, render_404, redirect |
ae3bc7fa | 24 | from mediagoblin.tools.translate import pass_to_ugettext as _ |
152a3bfa | 25 | from mediagoblin.tools.pagination import Pagination |
9074ee7c | 26 | from mediagoblin.user_pages import forms as user_forms |
252eaf21 | 27 | from mediagoblin.user_pages.lib import send_comment_email |
f6249408 | 28 | |
50854db0 | 29 | from mediagoblin.decorators import (uses_pagination, get_user_media_entry, |
461dd971 | 30 | get_media_entry_by_id, |
6d1e55b2 | 31 | require_active_login, user_may_delete_media, user_may_alter_collection, |
64c2a400 | 32 | get_user_collection, get_user_collection_item, active_user_from_url) |
9a16e16f | 33 | |
00c39256 | 34 | from werkzeug.contrib.atom import AtomFeed |
1301a8ad | 35 | |
9074ee7c | 36 | |
fb2fbe2c JAN |
37 | _log = logging.getLogger(__name__) |
38 | _log.setLevel(logging.DEBUG) | |
39 | ||
64712915 | 40 | |
3eb6fc4f | 41 | @uses_pagination |
1301a8ad | 42 | def user_home(request, page): |
9a16e16f | 43 | """'Homepage' of a User()""" |
af008743 SS |
44 | # TODO: decide if we only want homepages for active users, we can |
45 | # then use the @get_active_user decorator and also simplify the | |
46 | # template html. | |
47 | user = User.query.filter_by(username=request.matchdict['user']).first() | |
7acdbfd3 | 48 | if not user: |
de12b4e7 | 49 | return render_404(request) |
7a3d00ec | 50 | elif user.status != u'active': |
990d3b69 CAW |
51 | return render_to_response( |
52 | request, | |
53 | 'mediagoblin/user_pages/user.html', | |
54 | {'user': user}) | |
9a16e16f | 55 | |
2fb36dac SS |
56 | cursor = MediaEntry.query.\ |
57 | filter_by(uploader = user.id, | |
0efe9e27 | 58 | state = u'processed').order_by(MediaEntry.created.desc()) |
9a16e16f | 59 | |
1301a8ad | 60 | pagination = Pagination(page, cursor) |
ca3ca51c | 61 | media_entries = pagination() |
44e3e917 | 62 | |
ae85ed0f BK |
63 | #if no data is available, return NotFound |
64 | if media_entries == None: | |
de12b4e7 | 65 | return render_404(request) |
243c3843 | 66 | |
5949be9a CAW |
67 | user_gallery_url = request.urlgen( |
68 | 'mediagoblin.user_pages.user_gallery', | |
5a4e3ff1 | 69 | user=user.username) |
5949be9a | 70 | |
9038c9f9 CAW |
71 | return render_to_response( |
72 | request, | |
c9c24934 E |
73 | 'mediagoblin/user_pages/user.html', |
74 | {'user': user, | |
5949be9a | 75 | 'user_gallery_url': user_gallery_url, |
c9c24934 E |
76 | 'media_entries': media_entries, |
77 | 'pagination': pagination}) | |
f6249408 | 78 | |
243c3843 | 79 | |
64c2a400 | 80 | @active_user_from_url |
184f2240 | 81 | @uses_pagination |
64c2a400 | 82 | def user_gallery(request, page, url_user=None): |
184f2240 | 83 | """'Gallery' of a User()""" |
64c2a400 SS |
84 | cursor = MediaEntry.query.filter_by( |
85 | uploader=url_user.id, | |
86 | state=u'processed').order_by(MediaEntry.created.desc()) | |
af008743 | 87 | |
64c2a400 | 88 | # Paginate gallery |
184f2240 | 89 | pagination = Pagination(page, cursor) |
90 | media_entries = pagination() | |
91 | ||
92 | #if no data is available, return NotFound | |
64c2a400 | 93 | # TODO: Should we really also return 404 for empty galleries? |
184f2240 | 94 | if media_entries == None: |
de12b4e7 | 95 | return render_404(request) |
243c3843 | 96 | |
4b5f5a08 | 97 | return render_to_response( |
98 | request, | |
99 | 'mediagoblin/user_pages/gallery.html', | |
64c2a400 | 100 | {'user': url_user, |
4b5f5a08 | 101 | 'media_entries': media_entries, |
102 | 'pagination': pagination}) | |
184f2240 | 103 | |
6f59a3a3 | 104 | MEDIA_COMMENTS_PER_PAGE = 50 |
434b3221 | 105 | |
243c3843 | 106 | |
01674e10 | 107 | @get_user_media_entry |
9074ee7c | 108 | @uses_pagination |
6f59a3a3 | 109 | def media_home(request, media, page, **kwargs): |
9074ee7c JW |
110 | """ |
111 | 'Homepage' of a MediaEntry() | |
112 | """ | |
7d16a01b E |
113 | comment_id = request.matchdict.get('comment', None) |
114 | if comment_id: | |
af2fcba5 | 115 | pagination = Pagination( |
7c378f2c CAW |
116 | page, media.get_comments( |
117 | mg_globals.app_config['comments_ascending']), | |
118 | MEDIA_COMMENTS_PER_PAGE, | |
7d16a01b | 119 | comment_id) |
af2fcba5 JW |
120 | else: |
121 | pagination = Pagination( | |
7c378f2c CAW |
122 | page, media.get_comments( |
123 | mg_globals.app_config['comments_ascending']), | |
124 | MEDIA_COMMENTS_PER_PAGE) | |
9074ee7c | 125 | |
6f59a3a3 | 126 | comments = pagination() |
9074ee7c | 127 | |
111a609d | 128 | comment_form = user_forms.MediaCommentForm(request.form) |
9074ee7c | 129 | |
5f8b4ae8 | 130 | media_template_name = media.media_manager['display_template'] |
93bdab9d | 131 | |
9038c9f9 CAW |
132 | return render_to_response( |
133 | request, | |
93bdab9d | 134 | media_template_name, |
9074ee7c JW |
135 | {'media': media, |
136 | 'comments': comments, | |
137 | 'pagination': pagination, | |
3a8c3a38 JW |
138 | 'comment_form': comment_form, |
139 | 'app_config': mg_globals.app_config}) | |
9074ee7c | 140 | |
95e6da02 | 141 | |
461dd971 | 142 | @get_media_entry_by_id |
9074ee7c | 143 | @require_active_login |
95e12bf2 | 144 | def media_post_comment(request, media): |
9074ee7c JW |
145 | """ |
146 | recieves POST from a MediaEntry() comment form, saves the comment. | |
147 | """ | |
95e12bf2 CAW |
148 | assert request.method == 'POST' |
149 | ||
9074ee7c | 150 | comment = request.db.MediaComment() |
8efcd405 E |
151 | comment.media_entry = media.id |
152 | comment.author = request.user.id | |
111a609d | 153 | comment.content = unicode(request.form['comment_content']) |
9074ee7c | 154 | |
8efcd405 | 155 | if not comment.content.strip(): |
7298ffa1 AW |
156 | messages.add_message( |
157 | request, | |
158 | messages.ERROR, | |
eae7d058 | 159 | _("Oops, your comment was empty.")) |
7298ffa1 AW |
160 | else: |
161 | comment.save() | |
b5d3aec6 | 162 | |
7298ffa1 AW |
163 | messages.add_message( |
164 | request, messages.SUCCESS, | |
eae7d058 | 165 | _('Your comment has been posted!')) |
52359e91 | 166 | |
252eaf21 DM |
167 | media_uploader = media.get_uploader |
168 | #don't send email if you comment on your own post | |
169 | if (comment.author != media_uploader and | |
00722c99 | 170 | media_uploader.wants_comment_notification): |
252eaf21 DM |
171 | send_comment_email(media_uploader, comment, media, request) |
172 | ||
950124e6 | 173 | return redirect(request, location=media.url_for_self(request.urlgen)) |
00c39256 | 174 | |
95e6da02 | 175 | |
be5be115 AW |
176 | @get_user_media_entry |
177 | @require_active_login | |
178 | def media_collect(request, media): | |
f6bc0336 | 179 | """Add media to collection submission""" |
be5be115 | 180 | |
111a609d | 181 | form = user_forms.MediaCollectForm(request.form) |
f6bc0336 | 182 | # A user's own collections: |
2fb36dac SS |
183 | form.collection.query = Collection.query.filter_by( |
184 | creator = request.user.id).order_by(Collection.title) | |
f6bc0336 SS |
185 | |
186 | if request.method != 'POST' or not form.validate(): | |
187 | # No POST submission, or invalid form | |
188 | if not form.validate(): | |
189 | messages.add_message(request, messages.ERROR, | |
190 | _('Please check your entries and try again.')) | |
be5be115 | 191 | |
f6bc0336 SS |
192 | return render_to_response( |
193 | request, | |
194 | 'mediagoblin/user_pages/media_collect.html', | |
195 | {'media': media, | |
196 | 'form': form}) | |
197 | ||
198 | # If we are here, method=POST and the form is valid, submit things. | |
199 | # If the user is adding a new collection, use that: | |
200 | if request.form['collection_title']: | |
201 | # Make sure this user isn't duplicating an existing collection | |
202 | existing_collection = Collection.query.filter_by( | |
203 | creator=request.user.id, | |
204 | title=request.form['collection_title']).first() | |
205 | if existing_collection: | |
206 | messages.add_message(request, messages.ERROR, | |
207 | _('You already have a collection called "%s"!' | |
208 | % collection.title)) | |
be5be115 | 209 | return redirect(request, "mediagoblin.user_pages.media_home", |
f6bc0336 | 210 | user=request.user.username, |
be5be115 | 211 | media=media.id) |
be5be115 | 212 | |
f6bc0336 SS |
213 | collection = Collection() |
214 | collection.title = request.form['collection_title'] | |
215 | collection.description = request.form.get('collection_description') | |
216 | collection.creator = request.user.id | |
217 | collection.generate_slug() | |
b39d1f23 | 218 | collection.save() |
be5be115 | 219 | |
f6bc0336 SS |
220 | # Otherwise, use the collection selected from the drop-down |
221 | else: | |
222 | collection = Collection.query.filter_by( | |
223 | id=request.form.get('collection')).first() | |
be5be115 | 224 | |
f6bc0336 SS |
225 | # Make sure the user actually selected a collection |
226 | if not collection: | |
227 | messages.add_message( | |
228 | request, messages.ERROR, | |
229 | _('You have to select or add a collection')) | |
ba5ea989 SS |
230 | return redirect(request, "mediagoblin.user_pages.media_collect", |
231 | user=media.get_uploader.username, | |
232 | media=media.id) | |
233 | ||
f6bc0336 SS |
234 | |
235 | # Check whether media already exists in collection | |
236 | elif CollectionItem.query.filter_by( | |
237 | media_entry=media.id, | |
238 | collection=collection.id).first(): | |
239 | messages.add_message(request, messages.ERROR, | |
240 | _('"%s" already in collection "%s"' | |
241 | % (media.title, collection.title))) | |
242 | else: # Add item to collection | |
243 | collection_item = request.db.CollectionItem() | |
244 | collection_item.collection = collection.id | |
245 | collection_item.media_entry = media.id | |
246 | collection_item.author = request.user.id | |
247 | collection_item.note = request.form['note'] | |
b39d1f23 | 248 | collection_item.save() |
f6bc0336 SS |
249 | |
250 | collection.items = collection.items + 1 | |
b39d1f23 | 251 | collection.save() |
f6bc0336 SS |
252 | |
253 | media.collected = media.collected + 1 | |
254 | media.save() | |
255 | ||
256 | messages.add_message(request, messages.SUCCESS, | |
257 | _('"%s" added to collection "%s"' | |
258 | % (media.title, collection.title))) | |
259 | ||
260 | return redirect(request, "mediagoblin.user_pages.media_home", | |
261 | user=media.get_uploader.username, | |
262 | media=media.id) | |
263 | ||
264 | ||
265 | #TODO: Why does @user_may_delete_media not implicate @require_active_login? | |
461dd971 | 266 | @get_media_entry_by_id |
502073f2 JW |
267 | @require_active_login |
268 | @user_may_delete_media | |
269 | def media_confirm_delete(request, media): | |
270 | ||
111a609d | 271 | form = user_forms.ConfirmDeleteForm(request.form) |
502073f2 JW |
272 | |
273 | if request.method == 'POST' and form.validate(): | |
8daef28d | 274 | if form.confirm.data is True: |
05751758 | 275 | username = media.get_uploader.username |
fdc34b8b | 276 | # Delete MediaEntry and all related files, comments etc. |
502073f2 | 277 | media.delete() |
ea33f636 E |
278 | messages.add_message( |
279 | request, messages.SUCCESS, _('You deleted the media.')) | |
502073f2 JW |
280 | |
281 | return redirect(request, "mediagoblin.user_pages.user_home", | |
282 | user=username) | |
283 | else: | |
d0ba62e2 PUS |
284 | messages.add_message( |
285 | request, messages.ERROR, | |
56bfd91a | 286 | _("The media was not deleted because you didn't check that you were sure.")) |
950124e6 SS |
287 | return redirect(request, |
288 | location=media.url_for_self(request.urlgen)) | |
502073f2 | 289 | |
bec591d8 | 290 | if ((request.user.is_admin and |
5c2b8486 | 291 | request.user.id != media.uploader)): |
7a4c0126 CAW |
292 | messages.add_message( |
293 | request, messages.WARNING, | |
294 | _("You are about to delete another user's media. " | |
295 | "Proceed with caution.")) | |
296 | ||
502073f2 JW |
297 | return render_to_response( |
298 | request, | |
299 | 'mediagoblin/user_pages/media_confirm_delete.html', | |
300 | {'media': media, | |
301 | 'form': form}) | |
302 | ||
303 | ||
e2ae0f59 | 304 | @active_user_from_url |
be5be115 | 305 | @uses_pagination |
e2ae0f59 | 306 | def user_collection(request, page, url_user=None): |
be5be115 | 307 | """A User-defined Collection""" |
e2ae0f59 SS |
308 | collection = Collection.query.filter_by( |
309 | get_creator=url_user, | |
310 | slug=request.matchdict['collection']).first() | |
be5be115 | 311 | |
e2ae0f59 | 312 | cursor = collection.get_collection_items() |
be5be115 AW |
313 | |
314 | pagination = Pagination(page, cursor) | |
315 | collection_items = pagination() | |
316 | ||
e2ae0f59 SS |
317 | # if no data is available, return NotFound |
318 | # TODO: Should an empty collection really also return 404? | |
be5be115 AW |
319 | if collection_items == None: |
320 | return render_404(request) | |
321 | ||
322 | return render_to_response( | |
323 | request, | |
324 | 'mediagoblin/user_pages/collection.html', | |
e2ae0f59 | 325 | {'user': url_user, |
be5be115 AW |
326 | 'collection': collection, |
327 | 'collection_items': collection_items, | |
328 | 'pagination': pagination}) | |
329 | ||
330 | ||
b0cc1ade | 331 | @active_user_from_url |
4f8f0353 | 332 | def collection_list(request, url_user=None): |
b0cc1ade SZ |
333 | """A User-defined Collection""" |
334 | collections = Collection.query.filter_by( | |
335 | get_creator=url_user) | |
336 | ||
b0cc1ade SZ |
337 | return render_to_response( |
338 | request, | |
4f8f0353 | 339 | 'mediagoblin/user_pages/collection_list.html', |
b0cc1ade | 340 | {'user': url_user, |
947f38c0 | 341 | 'collections': collections}) |
b0cc1ade SZ |
342 | |
343 | ||
be5be115 AW |
344 | @get_user_collection_item |
345 | @require_active_login | |
346 | @user_may_alter_collection | |
347 | def collection_item_confirm_remove(request, collection_item): | |
348 | ||
111a609d | 349 | form = user_forms.ConfirmCollectionItemRemoveForm(request.form) |
be5be115 AW |
350 | |
351 | if request.method == 'POST' and form.validate(): | |
352 | username = collection_item.in_collection.get_creator.username | |
353 | collection = collection_item.in_collection | |
354 | ||
355 | if form.confirm.data is True: | |
356 | entry = collection_item.get_media_entry | |
357 | entry.collected = entry.collected - 1 | |
358 | entry.save() | |
359 | ||
360 | collection_item.delete() | |
6d1e55b2 | 361 | collection.items = collection.items - 1 |
be5be115 AW |
362 | collection.save() |
363 | ||
364 | messages.add_message( | |
365 | request, messages.SUCCESS, _('You deleted the item from the collection.')) | |
366 | else: | |
367 | messages.add_message( | |
368 | request, messages.ERROR, | |
369 | _("The item was not removed because you didn't check that you were sure.")) | |
370 | ||
371 | return redirect(request, "mediagoblin.user_pages.user_collection", | |
372 | user=username, | |
373 | collection=collection.slug) | |
374 | ||
375 | if ((request.user.is_admin and | |
5c2b8486 | 376 | request.user.id != collection_item.in_collection.creator)): |
be5be115 AW |
377 | messages.add_message( |
378 | request, messages.WARNING, | |
379 | _("You are about to delete an item from another user's collection. " | |
380 | "Proceed with caution.")) | |
381 | ||
382 | return render_to_response( | |
383 | request, | |
384 | 'mediagoblin/user_pages/collection_item_confirm_remove.html', | |
385 | {'collection_item': collection_item, | |
386 | 'form': form}) | |
387 | ||
388 | ||
389 | @get_user_collection | |
390 | @require_active_login | |
391 | @user_may_alter_collection | |
392 | def collection_confirm_delete(request, collection): | |
393 | ||
111a609d | 394 | form = user_forms.ConfirmDeleteForm(request.form) |
be5be115 AW |
395 | |
396 | if request.method == 'POST' and form.validate(): | |
397 | ||
398 | username = collection.get_creator.username | |
399 | ||
400 | if form.confirm.data is True: | |
401 | collection_title = collection.title | |
402 | ||
403 | # Delete all the associated collection items | |
404 | for item in collection.get_collection_items(): | |
405 | entry = item.get_media_entry | |
406 | entry.collected = entry.collected - 1 | |
407 | entry.save() | |
408 | item.delete() | |
409 | ||
410 | collection.delete() | |
411 | messages.add_message( | |
412 | request, messages.SUCCESS, _('You deleted the collection "%s"' % collection_title)) | |
413 | ||
414 | return redirect(request, "mediagoblin.user_pages.user_home", | |
415 | user=username) | |
416 | else: | |
417 | messages.add_message( | |
418 | request, messages.ERROR, | |
419 | _("The collection was not deleted because you didn't check that you were sure.")) | |
420 | ||
421 | return redirect(request, "mediagoblin.user_pages.user_collection", | |
422 | user=username, | |
423 | collection=collection.slug) | |
424 | ||
425 | if ((request.user.is_admin and | |
5c2b8486 | 426 | request.user.id != collection.creator)): |
be5be115 AW |
427 | messages.add_message( |
428 | request, messages.WARNING, | |
429 | _("You are about to delete another user's collection. " | |
430 | "Proceed with caution.")) | |
431 | ||
432 | return render_to_response( | |
433 | request, | |
434 | 'mediagoblin/user_pages/collection_confirm_delete.html', | |
435 | {'collection': collection, | |
436 | 'form': form}) | |
437 | ||
438 | ||
a5303e47 | 439 | ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 15 |
00c39256 | 440 | |
243c3843 | 441 | |
00c39256 BK |
442 | def atom_feed(request): |
443 | """ | |
444 | generates the atom feed with the newest images | |
445 | """ | |
2fb36dac SS |
446 | user = User.query.filter_by( |
447 | username = request.matchdict['user'], | |
448 | status = u'active').first() | |
00c39256 | 449 | if not user: |
de12b4e7 | 450 | return render_404(request) |
00c39256 | 451 | |
2fb36dac SS |
452 | cursor = MediaEntry.query.filter_by( |
453 | uploader = user.id, | |
454 | state = u'processed').\ | |
0efe9e27 | 455 | order_by(MediaEntry.created.desc()).\ |
2fb36dac | 456 | limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS) |
00c39256 | 457 | |
1df68a35 MA |
458 | """ |
459 | ATOM feed id is a tag URI (see http://en.wikipedia.org/wiki/Tag_URI) | |
460 | """ | |
5b1a7bae MA |
461 | atomlinks = [{ |
462 | 'href': request.urlgen( | |
463 | 'mediagoblin.user_pages.user_home', | |
64712915 | 464 | qualified=True, user=request.matchdict['user']), |
5b1a7bae MA |
465 | 'rel': 'alternate', |
466 | 'type': 'text/html' | |
64712915 JW |
467 | }] |
468 | ||
bb025ebd MA |
469 | if mg_globals.app_config["push_urls"]: |
470 | for push_url in mg_globals.app_config["push_urls"]: | |
471 | atomlinks.append({ | |
472 | 'rel': 'hub', | |
473 | 'href': push_url}) | |
5b1a7bae | 474 | |
1df68a35 MA |
475 | feed = AtomFeed( |
476 | "MediaGoblin: Feed for user '%s'" % request.matchdict['user'], | |
00c39256 | 477 | feed_url=request.url, |
64712915 JW |
478 | id='tag:{host},{year}:gallery.user-{user}'.format( |
479 | host=request.host, | |
480 | year=datetime.datetime.today().strftime('%Y'), | |
481 | user=request.matchdict['user']), | |
5b1a7bae MA |
482 | links=atomlinks) |
483 | ||
00c39256 BK |
484 | for entry in cursor: |
485 | feed.add(entry.get('title'), | |
1e72e075 | 486 | entry.description_html, |
64712915 | 487 | id=entry.url_for_self(request.urlgen, qualified=True), |
00c39256 | 488 | content_type='html', |
1df68a35 MA |
489 | author={ |
490 | 'name': entry.get_uploader.username, | |
491 | 'uri': request.urlgen( | |
492 | 'mediagoblin.user_pages.user_home', | |
493 | qualified=True, user=entry.get_uploader.username)}, | |
00c39256 | 494 | updated=entry.get('created'), |
1df68a35 MA |
495 | links=[{ |
496 | 'href': entry.url_for_self( | |
497 | request.urlgen, | |
be5be115 AW |
498 | qualified=True), |
499 | 'rel': 'alternate', | |
500 | 'type': 'text/html'}]) | |
501 | ||
502 | return feed.get_response() | |
503 | ||
6d1e55b2 | 504 | |
be5be115 AW |
505 | def collection_atom_feed(request): |
506 | """ | |
507 | generates the atom feed with the newest images from a collection | |
508 | """ | |
2fb36dac SS |
509 | user = User.query.filter_by( |
510 | username = request.matchdict['user'], | |
511 | status = u'active').first() | |
be5be115 AW |
512 | if not user: |
513 | return render_404(request) | |
514 | ||
af008743 SS |
515 | collection = Collection.query.filter_by( |
516 | creator=user.id, | |
517 | slug=request.matchdict['collection']).first() | |
be5be115 | 518 | |
af008743 SS |
519 | cursor = CollectionItem.query.filter_by( |
520 | collection=collection.id) \ | |
20be9bb7 | 521 | .order_by(CollectionItem.added.desc()) \ |
be5be115 AW |
522 | .limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS) |
523 | ||
524 | """ | |
525 | ATOM feed id is a tag URI (see http://en.wikipedia.org/wiki/Tag_URI) | |
526 | """ | |
527 | atomlinks = [{ | |
528 | 'href': request.urlgen( | |
529 | 'mediagoblin.user_pages.user_collection', | |
530 | qualified=True, user=request.matchdict['user'], collection=collection.slug), | |
531 | 'rel': 'alternate', | |
532 | 'type': 'text/html' | |
533 | }] | |
534 | ||
535 | if mg_globals.app_config["push_urls"]: | |
536 | for push_url in mg_globals.app_config["push_urls"]: | |
537 | atomlinks.append({ | |
538 | 'rel': 'hub', | |
539 | 'href': push_url}) | |
540 | ||
541 | feed = AtomFeed( | |
542 | "MediaGoblin: Feed for %s's collection %s" % (request.matchdict['user'], collection.title), | |
543 | feed_url=request.url, | |
544 | id='tag:{host},{year}:collection.user-{user}.title-{title}'.format( | |
545 | host=request.host, | |
546 | year=datetime.datetime.today().strftime('%Y'), | |
547 | user=request.matchdict['user'], | |
548 | title=collection.title), | |
549 | links=atomlinks) | |
550 | ||
551 | for item in cursor: | |
552 | entry = item.get_media_entry | |
553 | feed.add(entry.get('title'), | |
554 | item.note_html, | |
555 | id=entry.url_for_self(request.urlgen, qualified=True), | |
556 | content_type='html', | |
557 | author={ | |
558 | 'name': entry.get_uploader.username, | |
559 | 'uri': request.urlgen( | |
560 | 'mediagoblin.user_pages.user_home', | |
561 | qualified=True, user=entry.get_uploader.username)}, | |
562 | updated=item.get('added'), | |
563 | links=[{ | |
564 | 'href': entry.url_for_self( | |
565 | request.urlgen, | |
1df68a35 MA |
566 | qualified=True), |
567 | 'rel': 'alternate', | |
568 | 'type': 'text/html'}]) | |
00c39256 | 569 | |
9074ee7c | 570 | return feed.get_response() |
01c75c7e CAW |
571 | |
572 | ||
573 | @require_active_login | |
574 | def processing_panel(request): | |
575 | """ | |
576 | Show to the user what media is still in conversion/processing... | |
577 | and what failed, and why! | |
578 | """ | |
af008743 SS |
579 | user = User.query.filter_by(username=request.matchdict['user']).first() |
580 | # TODO: XXX: Should this be a decorator? | |
01c75c7e CAW |
581 | # |
582 | # Make sure we have permission to access this user's panel. Only | |
583 | # admins and this user herself should be able to do so. | |
dfc23dd1 | 584 | if not (user.id == request.user.id or request.user.is_admin): |
af008743 | 585 | # No? Simply redirect to this user's homepage. |
01c75c7e CAW |
586 | return redirect( |
587 | request, 'mediagoblin.user_pages.user_home', | |
af008743 | 588 | user=user.username) |
01c75c7e CAW |
589 | |
590 | # Get media entries which are in-processing | |
af008743 | 591 | processing_entries = MediaEntry.query.\ |
2fb36dac SS |
592 | filter_by(uploader = user.id, |
593 | state = u'processing').\ | |
af008743 | 594 | order_by(MediaEntry.created.desc()) |
01c75c7e CAW |
595 | |
596 | # Get media entries which have failed to process | |
af008743 | 597 | failed_entries = MediaEntry.query.\ |
2fb36dac SS |
598 | filter_by(uploader = user.id, |
599 | state = u'failed').\ | |
af008743 SS |
600 | order_by(MediaEntry.created.desc()) |
601 | ||
602 | processed_entries = MediaEntry.query.\ | |
2fb36dac SS |
603 | filter_by(uploader = user.id, |
604 | state = u'processed').\ | |
af008743 SS |
605 | order_by(MediaEntry.created.desc()).\ |
606 | limit(10) | |
64712915 | 607 | |
01c75c7e CAW |
608 | # Render to response |
609 | return render_to_response( | |
610 | request, | |
611 | 'mediagoblin/user_pages/processing_panel.html', | |
612 | {'user': user, | |
613 | 'processing_entries': processing_entries, | |
64712915 JW |
614 | 'failed_entries': failed_entries, |
615 | 'processed_entries': processed_entries}) |