1 # MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011 MediaGoblin contributors. See AUTHORS.
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.
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.
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/>.
19 from mediagoblin
import messages
, mg_globals
20 from mediagoblin
.db
.util
import DESCENDING
, ObjectId
21 from mediagoblin
.util
import (
22 Pagination
, render_to_response
, redirect
, cleaned_markdown_conversion
,
23 render_404
, delete_media_files
)
24 from mediagoblin
.util
import pass_to_ugettext
as _
25 from mediagoblin
.user_pages
import forms
as user_forms
27 from mediagoblin
.decorators
import (uses_pagination
, get_user_media_entry
,
28 require_active_login
, user_may_delete_media
)
30 from werkzeug
.contrib
.atom
import AtomFeed
34 def user_home(request
, page
):
35 """'Homepage' of a User()"""
36 user
= request
.db
.User
.find_one({
37 'username': request
.matchdict
['user']})
39 return render_404(request
)
40 elif user
['status'] != u
'active':
41 return render_to_response(
43 'mediagoblin/user_pages/user.html',
46 cursor
= request
.db
.MediaEntry
.find(
47 {'uploader': user
['_id'],
48 'state': 'processed'}).sort('created', DESCENDING
)
50 pagination
= Pagination(page
, cursor
)
51 media_entries
= pagination()
53 #if no data is available, return NotFound
54 if media_entries
== None:
55 return render_404(request
)
57 user_gallery_url
= request
.urlgen(
58 'mediagoblin.user_pages.user_gallery',
59 user
=user
['username'])
61 return render_to_response(
63 'mediagoblin/user_pages/user.html',
65 'user_gallery_url': user_gallery_url
,
66 'media_entries': media_entries
,
67 'pagination': pagination
})
70 def user_gallery(request
, page
):
71 """'Gallery' of a User()"""
72 user
= request
.db
.User
.find_one({
73 'username': request
.matchdict
['user'],
76 return render_404(request
)
78 cursor
= request
.db
.MediaEntry
.find(
79 {'uploader': user
['_id'],
80 'state': 'processed'}).sort('created', DESCENDING
)
82 pagination
= Pagination(page
, cursor
)
83 media_entries
= pagination()
85 #if no data is available, return NotFound
86 if media_entries
== None:
87 return render_404(request
)
89 return render_to_response(
91 'mediagoblin/user_pages/gallery.html',
93 'media_entries': media_entries
,
94 'pagination': pagination
})
96 MEDIA_COMMENTS_PER_PAGE
= 50
100 def media_home(request
, media
, page
, **kwargs
):
102 'Homepage' of a MediaEntry()
104 if ObjectId(request
.matchdict
.get('comment')):
105 pagination
= Pagination(
106 page
, media
.get_comments(), MEDIA_COMMENTS_PER_PAGE
,
107 ObjectId(request
.matchdict
.get('comment')))
109 pagination
= Pagination(
110 page
, media
.get_comments(), MEDIA_COMMENTS_PER_PAGE
)
112 comments
= pagination()
114 comment_form
= user_forms
.MediaCommentForm(request
.POST
)
116 return render_to_response(
118 'mediagoblin/user_pages/media.html',
120 'comments': comments
,
121 'pagination': pagination
,
122 'comment_form': comment_form
,
123 'app_config': mg_globals
.app_config
})
126 @require_active_login
127 def media_post_comment(request
):
129 recieves POST from a MediaEntry() comment form, saves the comment.
131 comment
= request
.db
.MediaComment()
132 comment
['media_entry'] = ObjectId(request
.matchdict
['media'])
133 comment
['author'] = request
.user
['_id']
134 comment
['content'] = unicode(request
.POST
['comment_content'])
136 comment
['content_html'] = cleaned_markdown_conversion(comment
['content'])
140 messages
.add_message(
141 request
, messages
.SUCCESS
,
144 return redirect(request
, 'mediagoblin.user_pages.media_home',
145 media
= request
.matchdict
['media'],
146 user
= request
.matchdict
['user'])
149 @get_user_media_entry
150 @require_active_login
151 @user_may_delete_media
152 def media_confirm_delete(request
, media
):
154 form
= user_forms
.ConfirmDeleteForm(request
.POST
)
156 if request
.method
== 'POST' and form
.validate():
157 if form
.confirm
.data
is True:
158 username
= media
.uploader()['username']
160 # Delete all files on the public storage
161 delete_media_files(media
)
165 return redirect(request
, "mediagoblin.user_pages.user_home",
168 return redirect(request
, "mediagoblin.user_pages.media_home",
169 user
=media
.uploader()['username'],
172 if ((request
.user
[u
'is_admin'] and
173 request
.user
[u
'_id'] != media
.uploader()[u
'_id'])):
174 messages
.add_message(
175 request
, messages
.WARNING
,
176 _("You are about to delete another user's media. "
177 "Proceed with caution."))
179 return render_to_response(
181 'mediagoblin/user_pages/media_confirm_delete.html',
186 ATOM_DEFAULT_NR_OF_UPDATED_ITEMS
= 15
188 def atom_feed(request
):
190 generates the atom feed with the newest images
193 user
= request
.db
.User
.find_one({
194 'username': request
.matchdict
['user'],
197 return render_404(request
)
199 cursor
= request
.db
.MediaEntry
.find({
200 'uploader': user
['_id'],
201 'state': 'processed'}) \
202 .sort('created', DESCENDING
) \
203 .limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS
)
205 feed
= AtomFeed(request
.matchdict
['user'],
206 feed_url
=request
.url
,
207 url
=request
.host_url
)
210 feed
.add(entry
.get('title'),
211 entry
.get('description_html'),
213 author
=request
.matchdict
['user'],
214 updated
=entry
.get('created'),
215 url
=entry
.url_for_self(request
.urlgen
))
217 return feed
.get_response()
220 @require_active_login
221 def processing_panel(request
):
223 Show to the user what media is still in conversion/processing...
224 and what failed, and why!
227 user
= request
.db
.User
.find_one(
228 {'username': request
.matchdict
['user'],
231 # Make sure the user exists and is active
233 return render_404(request
)
234 elif user
['status'] != u
'active':
235 return render_to_response(
237 'mediagoblin/user_pages/user.html',
240 # XXX: Should this be a decorator?
242 # Make sure we have permission to access this user's panel. Only
243 # admins and this user herself should be able to do so.
244 if not (user
[u
'_id'] == request
.user
[u
'_id']
245 or request
.user
.is_admin
):
246 # No? Let's simply redirect to this user's homepage then.
248 request
, 'mediagoblin.user_pages.user_home',
249 user
=request
.matchdict
['user'])
251 # Get media entries which are in-processing
252 processing_entries
= request
.db
.MediaEntry
.find(
253 {'uploader': user
['_id'],
254 'state': 'processing'}).sort('created', DESCENDING
)
256 # Get media entries which have failed to process
257 failed_entries
= request
.db
.MediaEntry
.find(
258 {'uploader': user
['_id'],
259 'state': 'failed'}).sort('created', DESCENDING
)
262 return render_to_response(
264 'mediagoblin/user_pages/processing_panel.html',
266 'processing_entries': processing_entries
,
267 'failed_entries': failed_entries
})