1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 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/>.
18 _log
= logging
.getLogger(__name__
)
20 from datetime
import datetime
22 from werkzeug
.exceptions
import Forbidden
23 from mediagoblin
.tools
import pluginapi
25 from mediagoblin
import mg_globals
27 from mediagoblin
.media_types
.blog
import forms
as blog_forms
28 from mediagoblin
.media_types
.blog
.models
import Blog
, BlogPostData
29 from mediagoblin
.media_types
.blog
.lib
import (
30 may_edit_blogpost
, set_blogpost_state
, get_all_blogposts_of_blog
,
33 from mediagoblin
.messages
import add_message
, SUCCESS
, ERROR
34 from mediagoblin
.decorators
import (require_active_login
, active_user_from_url
,
35 get_media_entry_by_id
, user_may_alter_collection
,
36 get_user_collection
, uses_pagination
)
37 from mediagoblin
.tools
.pagination
import Pagination
38 from mediagoblin
.tools
.response
import (render_to_response
,
40 from mediagoblin
.tools
.translate
import pass_to_ugettext
as _
41 from mediagoblin
.tools
.template
import render_template
42 from mediagoblin
.tools
.text
import (
43 convert_to_tag_list_of_dicts
, media_tags_as_string
, clean_html
,
44 cleaned_markdown_conversion
)
46 from mediagoblin
.db
.util
import check_media_slug_used
, check_collection_slug_used
47 from mediagoblin
.db
.models
import User
, Collection
, MediaEntry
49 from mediagoblin
.notifications
import add_comment_subscription
53 def blog_edit(request
):
55 View for editing an existing blog or creating a new blog
56 if user have not exceeded maximum allowed acount of blogs.
58 url_user
= request
.matchdict
.get('user', None)
59 blog_slug
= request
.matchdict
.get('blog_slug', None)
61 config
= pluginapi
.get_config('mediagoblin.media_types.blog')
62 max_blog_count
= config
['max_blog_count']
63 form
= blog_forms
.BlogEditForm(request
.form
)
66 if Blog
.query
.filter_by(author
=request
.user
.id).count()<max_blog_count
:
67 if request
.method
=='GET':
68 return render_to_response(
70 'mediagoblin/blog/blog_edit_create.html',
72 'user' : request
.user
,
73 'app_config': mg_globals
.app_config
})
75 if request
.method
=='POST' and form
.validate():
77 blog
= request
.db
.Blog()
78 blog
.title
= unicode(form
.title
.data
)
79 blog
.description
= unicode(cleaned_markdown_conversion((form
.description
.data
)))
80 blog
.author
= request
.user
.id
84 return redirect(request
, "mediagoblin.media_types.blog.blog_admin_dashboard",
85 user
=request
.user
.username
88 add_message(request
, ERROR
, "Welcome! You already have created \
89 maximum number of blogs.")
90 return redirect(request
, "mediagoblin.media_types.blog.blog_admin_dashboard",
91 user
=request
.user
.username
)
96 blog
= get_blog_by_slug(request
, blog_slug
)
98 return render_404(request
)
99 if request
.method
== 'GET':
102 description
= cleaned_markdown_conversion(blog
.description
),
103 author
= request
.user
.id)
105 form
= blog_forms
.BlogEditForm(**defaults
)
107 return render_to_response(
109 'mediagoblin/blog/blog_edit_create.html',
111 'user': request
.user
,
112 'app_config': mg_globals
.app_config
})
114 if request
.method
== 'POST' and form
.validate():
115 blog
.title
= unicode(form
.title
.data
)
116 blog
.description
= unicode(cleaned_markdown_conversion((form
.description
.data
)))
117 blog
.author
= request
.user
.id
121 add_message(request
, SUCCESS
, "Your blog is updated.")
122 return redirect(request
, "mediagoblin.media_types.blog.blog-dashboard",
123 user
=request
.user
.username
,
127 @require_active_login
128 def blogpost_create(request
):
130 form
= blog_forms
.BlogPostEditForm(request
.form
, license
=request
.user
.license_preference
)
132 if request
.method
== 'POST' and form
.validate():
133 blog_slug
= request
.matchdict
.get('blog_slug')
134 blog
= get_blog_by_slug(request
, blog_slug
, author
=request
.user
.id)
136 return render_404(request
)
138 blogpost
= request
.db
.MediaEntry()
139 blogpost
.media_type
= 'mediagoblin.media_types.blogpost'
140 blogpost
.title
= unicode(form
.title
.data
)
141 blogpost
.description
= unicode(cleaned_markdown_conversion((form
.description
.data
)))
142 blogpost
.tags
= convert_to_tag_list_of_dicts(form
.tags
.data
)
143 blogpost
.license
= unicode(form
.license
.data
) or None
144 blogpost
.uploader
= request
.user
.id
145 blogpost
.generate_slug()
147 set_blogpost_state(request
, blogpost
)
150 # connect this blogpost to its blog
151 blog_post_data
= request
.db
.BlogPostData()
152 blog_post_data
.blog
= blog
.id
153 blog_post_data
.media_entry
= blogpost
.id
154 blog_post_data
.save()
156 add_message(request
, SUCCESS
, _('Woohoo! Submitted!'))
157 add_comment_subscription(request
.user
, blogpost
)
158 return redirect(request
, "mediagoblin.media_types.blog.blog-dashboard",
159 user
=request
.user
.username
,
162 return render_to_response(
164 'mediagoblin/blog/blog_post_edit_create.html',
166 'app_config': mg_globals
.app_config
,
167 'user': request
.user
.username
})
170 @require_active_login
171 def blogpost_edit(request
):
173 blog_slug
= request
.matchdict
.get('blog_slug', None)
174 blog_post_slug
= request
.matchdict
.get('blog_post_slug', None)
176 blogpost
= request
.db
.MediaEntry
.query
.filter_by(slug
=blog_post_slug
, uploader
=request
.user
.id).first()
177 blog
= get_blog_by_slug(request
, blog_slug
, author
=request
.user
.id)
179 if not blogpost
or not blog
:
180 return render_404(request
)
183 title
= blogpost
.title
,
184 description
= cleaned_markdown_conversion(blogpost
.description
),
185 tags
=media_tags_as_string(blogpost
.tags
),
186 license
=blogpost
.license
)
188 form
= blog_forms
.BlogPostEditForm(request
.form
, **defaults
)
189 if request
.method
== 'POST' and form
.validate():
190 blogpost
.title
= unicode(form
.title
.data
)
191 blogpost
.description
= unicode(cleaned_markdown_conversion((form
.description
.data
)))
192 blogpost
.tags
= convert_to_tag_list_of_dicts(form
.tags
.data
)
193 blogpost
.license
= unicode(form
.license
.data
)
194 set_blogpost_state(request
, blogpost
)
195 blogpost
.generate_slug()
198 add_message(request
, SUCCESS
, _('Woohoo! edited blogpost is submitted'))
199 return redirect(request
, "mediagoblin.media_types.blog.blog-dashboard",
200 user
=request
.user
.username
,
203 return render_to_response(
205 'mediagoblin/blog/blog_post_edit_create.html',
207 'app_config': mg_globals
.app_config
,
208 'user': request
.user
.username
,
209 'blog_post_slug': blog_post_slug
213 @active_user_from_url
215 def blog_dashboard(request
, page
, url_user
=None):
217 Dashboard for a blog, only accessible to
218 the owner of the blog.
220 blog_slug
= request
.matchdict
.get('blog_slug', None)
221 blogs
= request
.db
.Blog
.query
.filter_by(author
=url_user
.id)
222 config
= pluginapi
.get_config('mediagoblin.media_types.blog')
223 max_blog_count
= config
['max_blog_count']
224 if request
.user
and (request
.user
.id == url_user
.id or request
.user
.has_privilege(u
'admin')):
226 blog
= get_blog_by_slug(request
, blog_slug
)
228 return render_404(request
)
230 blog_posts_list
= blog
.get_all_blog_posts().order_by(MediaEntry
.created
.desc())
231 pagination
= Pagination(page
, blog_posts_list
)
232 pagination
.per_page
= 15
233 blog_posts_on_a_page
= pagination()
234 if may_edit_blogpost(request
, blog
):
235 return render_to_response(
237 'mediagoblin/blog/blog_admin_dashboard.html',
238 {'blog_posts_list': blog_posts_on_a_page
,
239 'blog_slug':blog_slug
,
242 'pagination':pagination
244 if not request
.user
or request
.user
.id != url_user
.id or not blog_slug
:
246 return render_to_response(
248 'mediagoblin/blog/list_of_blogs.html',
252 'max_blog_count':max_blog_count
256 @active_user_from_url
258 def blog_post_listing(request
, page
, url_user
=None):
260 Page, listing all the blog posts of a particular blog.
262 blog_slug
= request
.matchdict
['blog_slug']
263 blog
= get_blog_by_slug(request
, blog_slug
, author
=url_user
.id)
265 return render_404(request
)
267 all_blog_posts
= blog
.get_all_blog_posts(u
'processed').order_by(MediaEntry
.created
.desc())
268 pagination
= Pagination(page
, all_blog_posts
)
269 pagination
.per_page
= 8
270 blog_posts_on_a_page
= pagination()
272 return render_to_response(
274 'mediagoblin/blog/blog_post_listing.html',
275 {'blog_posts': blog_posts_on_a_page
,
276 'pagination': pagination
,
277 'blog_owner': url_user
,
282 @require_active_login
283 def draft_view(request
):
284 blog_slug
= request
.matchdict
.get('blog_slug', None)
285 blog_post_slug
= request
.matchdict
.get('blog_post_slug', None)
286 user
= request
.matchdict
.get('user')
287 blog
= get_blog_by_slug(request
, blog_slug
, author
=request
.user
.id)
288 blogpost
= request
.db
.MediaEntry
.query
.filter_by(state
= u
'failed', uploader
=request
.user
.id, slug
=blog_post_slug
).first()
290 if not blog
or not blogpost
:
291 return render_404(request
)
293 return render_to_response(
295 'mediagoblin/blog/blogpost_draft_view.html',
296 {'blogpost':blogpost
,
301 @require_active_login
302 def blog_delete(request
, **kwargs
):
304 Deletes a blog and media entries, tags associated with it.
306 url_user
= request
.matchdict
.get('user')
307 owner_user
= request
.db
.User
.query
.filter_by(username
=url_user
).first()
309 blog_slug
= request
.matchdict
.get('blog_slug', None)
310 blog
= get_blog_by_slug(request
, blog_slug
, author
=owner_user
.id)
312 return render_404(reequest
)
314 form
= blog_forms
.ConfirmDeleteForm(request
.form
)
315 if request
.user
.id == blog
.author
or request
.user
.has_privilege(u
'admin'):
316 if request
.method
== 'POST' and form
.validate():
317 if form
.confirm
.data
is True:
320 request
, SUCCESS
, _('You deleted the Blog.'))
321 return redirect(request
, "mediagoblin.media_types.blog.blog_admin_dashboard",
322 user
=request
.user
.username
)
326 _("The media was not deleted because you didn't check that you were sure."))
327 return redirect(request
, "mediagoblin.media_types.blog.blog_admin_dashboard",
328 user
=request
.user
.username
)
330 if request
.user
.has_privilege(u
'admin'):
333 _("You are about to delete another user's Blog. "
334 "Proceed with caution."))
335 return render_to_response(
337 'mediagoblin/blog/blog_confirm_delete.html',
344 _("The blog was not deleted because you have no rights."))
345 return redirect(request
, "mediagoblin.media_types.blog.blog_admin_dashboard",
346 user
=request
.user
.username
)
349 def blog_about_view(request
):
351 Page containing blog description and statistics
353 blog_slug
= request
.matchdict
.get('blog_slug', None)
354 url_user
= request
.matchdict
.get('user', None)
356 user
= request
.db
.User
.query
.filter_by(username
=url_user
).first()
357 blog
= get_blog_by_slug(request
, blog_slug
, author
=user
.id)
359 if not user
or not blog
:
360 return render_404(request
)
363 blog_posts_processed
= blog
.get_all_blog_posts(u
'processed').count()
364 return render_to_response(
366 'mediagoblin/blog/blog_about.html',
369 'blogpost_count': blog_posts_processed