Merge remote-tracking branch 'gsoc2016/Subtitle-1'
[mediagoblin.git] / mediagoblin / media_types / blog / views.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
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
17 import logging
18 _log = logging.getLogger(__name__)
19
20 from datetime import datetime
21
22 import six
23
24 from werkzeug.exceptions import Forbidden
25 from mediagoblin.tools import pluginapi
26
27 from mediagoblin import mg_globals
28
29 from mediagoblin.media_types.blog import forms as blog_forms
30 from mediagoblin.media_types.blog.models import Blog, BlogPostData
31 from mediagoblin.media_types.blog.lib import (
32 may_edit_blogpost, set_blogpost_state, get_all_blogposts_of_blog,
33 get_blog_by_slug)
34
35 from mediagoblin.decorators import (require_active_login, active_user_from_url,
36 get_media_entry_by_id, user_may_alter_collection,
37 get_user_collection, uses_pagination)
38 from mediagoblin.tools.pagination import Pagination
39 from mediagoblin.tools.response import (render_to_response,
40 redirect, render_404)
41 from mediagoblin.tools.translate import pass_to_ugettext as _
42 from mediagoblin.tools.template import render_template
43 from mediagoblin.tools.text import (
44 convert_to_tag_list_of_dicts, media_tags_as_string, clean_html,
45 cleaned_markdown_conversion)
46
47 from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used
48 from mediagoblin.db.models import User, Collection, MediaEntry, LocalUser
49
50 from mediagoblin.notifications import add_comment_subscription
51
52
53 @require_active_login
54 def blog_edit(request):
55 """
56 View for editing an existing blog or creating a new blog
57 if user have not exceeded maximum allowed acount of blogs.
58 """
59 url_user = request.matchdict.get('user', None)
60 blog_slug = request.matchdict.get('blog_slug', None)
61
62 config = pluginapi.get_config('mediagoblin.media_types.blog')
63 max_blog_count = config['max_blog_count']
64 form = blog_forms.BlogEditForm(request.form)
65 # creating a blog
66 if not blog_slug:
67 if Blog.query.filter_by(author=request.user.id).count()<max_blog_count:
68 if request.method=='GET':
69 return render_to_response(
70 request,
71 'mediagoblin/blog/blog_edit_create.html',
72 {'form': form,
73 'user' : request.user,
74 'app_config': mg_globals.app_config})
75
76 if request.method=='POST' and form.validate():
77 _log.info("Here")
78 blog = request.db.Blog()
79 blog.title = six.text_type(form.title.data)
80 blog.description = six.text_type(cleaned_markdown_conversion((form.description.data)))
81 blog.author = request.user.id
82 blog.generate_slug()
83
84 blog.save()
85 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
86 user=request.user.username
87 )
88 else:
89 messages.add_message(
90 request,
91 messages.ERROR,
92 "Welcome! You already have created maximum number of blogs.")
93 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
94 user=request.user.username)
95
96
97 #Blog already exists.
98 else:
99 blog = get_blog_by_slug(request, blog_slug)
100 if not blog:
101 return render_404(request)
102 if request.method == 'GET':
103 defaults = dict(
104 title = blog.title,
105 description = cleaned_markdown_conversion(blog.description),
106 author = request.user.id)
107
108 form = blog_forms.BlogEditForm(**defaults)
109
110 return render_to_response(
111 request,
112 'mediagoblin/blog/blog_edit_create.html',
113 {'form': form,
114 'user': request.user,
115 'app_config': mg_globals.app_config})
116 else:
117 if request.method == 'POST' and form.validate():
118 blog.title = six.text_type(form.title.data)
119 blog.description = six.text_type(cleaned_markdown_conversion((form.description.data)))
120 blog.author = request.user.id
121 blog.generate_slug()
122
123 blog.save()
124 messages.add_message(
125 request,
126 messages.SUCCESS,
127 "Your blog is updated.")
128 return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
129 user=request.user.username,
130 blog_slug=blog.slug)
131
132
133 @require_active_login
134 def blogpost_create(request):
135
136 form = blog_forms.BlogPostEditForm(request.form, license=request.user.license_preference)
137
138 if request.method == 'POST' and form.validate():
139 blog_slug = request.matchdict.get('blog_slug')
140 blog = get_blog_by_slug(request, blog_slug, author=request.user.id)
141 if not blog:
142 return render_404(request)
143
144 blogpost = request.db.MediaEntry()
145 blogpost.media_type = 'mediagoblin.media_types.blogpost'
146 blogpost.title = six.text_type(form.title.data)
147 blogpost.description = six.text_type(cleaned_markdown_conversion((form.description.data)))
148 blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data)
149 blogpost.license = six.text_type(form.license.data) or None
150 blogpost.actor = request.user.id
151 blogpost.generate_slug()
152
153 set_blogpost_state(request, blogpost)
154 blogpost.save()
155
156 # connect this blogpost to its blog
157 blog_post_data = request.db.BlogPostData()
158 blog_post_data.blog = blog.id
159 blog_post_data.media_entry = blogpost.id
160 blog_post_data.save()
161
162 messages.add_message(
163 request,
164 messages.SUCCESS,
165 _('Woohoo! Submitted!'))
166 add_comment_subscription(request.user, blogpost)
167 return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
168 user=request.user.username,
169 blog_slug=blog.slug)
170
171 return render_to_response(
172 request,
173 'mediagoblin/blog/blog_post_edit_create.html',
174 {'form': form,
175 'app_config': mg_globals.app_config,
176 'user': request.user.username})
177
178
179 @require_active_login
180 def blogpost_edit(request):
181
182 blog_slug = request.matchdict.get('blog_slug', None)
183 blog_post_slug = request.matchdict.get('blog_post_slug', None)
184
185 blogpost = request.db.MediaEntry.query.filter_by(slug=blog_post_slug, actor=request.user.id).first()
186 blog = get_blog_by_slug(request, blog_slug, author=request.user.id)
187
188 if not blogpost or not blog:
189 return render_404(request)
190
191 defaults = dict(
192 title = blogpost.title,
193 description = cleaned_markdown_conversion(blogpost.description),
194 tags=media_tags_as_string(blogpost.tags),
195 license=blogpost.license)
196
197 form = blog_forms.BlogPostEditForm(request.form, **defaults)
198 if request.method == 'POST' and form.validate():
199 blogpost.title = six.text_type(form.title.data)
200 blogpost.description = six.text_type(cleaned_markdown_conversion((form.description.data)))
201 blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data)
202 blogpost.license = six.text_type(form.license.data)
203 set_blogpost_state(request, blogpost)
204 blogpost.generate_slug()
205 blogpost.save()
206
207 messages.add_message(
208 request,
209 messages.SUCCESS,
210 _('Woohoo! edited blogpost is submitted'))
211 return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
212 user=request.user.username,
213 blog_slug=blog.slug)
214
215 return render_to_response(
216 request,
217 'mediagoblin/blog/blog_post_edit_create.html',
218 {'form': form,
219 'app_config': mg_globals.app_config,
220 'user': request.user.username,
221 'blog_post_slug': blog_post_slug
222 })
223
224
225 @active_user_from_url
226 @uses_pagination
227 def blog_dashboard(request, page, url_user=None):
228 """
229 Dashboard for a blog, only accessible to
230 the owner of the blog.
231 """
232 blog_slug = request.matchdict.get('blog_slug', None)
233 blogs = request.db.Blog.query.filter_by(author=url_user.id)
234 config = pluginapi.get_config('mediagoblin.media_types.blog')
235 max_blog_count = config['max_blog_count']
236 if request.user and (request.user.id == url_user.id or request.user.has_privilege(u'admin')):
237 if blog_slug:
238 blog = get_blog_by_slug(request, blog_slug)
239 if not blog:
240 return render_404(request)
241 else:
242 blog_posts_list = blog.get_all_blog_posts().order_by(MediaEntry.created.desc())
243 pagination = Pagination(page, blog_posts_list)
244 pagination.per_page = 15
245 blog_posts_on_a_page = pagination()
246 if may_edit_blogpost(request, blog):
247 return render_to_response(
248 request,
249 'mediagoblin/blog/blog_admin_dashboard.html',
250 {'blog_posts_list': blog_posts_on_a_page,
251 'blog_slug':blog_slug,
252 'blog':blog,
253 'user':url_user,
254 'pagination':pagination
255 })
256 if not request.user or request.user.id != url_user.id or not blog_slug:
257 blogs = blogs.all()
258 return render_to_response(
259 request,
260 'mediagoblin/blog/list_of_blogs.html',
261 {
262 'blogs':blogs,
263 'user':url_user,
264 'max_blog_count':max_blog_count
265 })
266
267
268 @active_user_from_url
269 @uses_pagination
270 def blog_post_listing(request, page, url_user=None):
271 """
272 Page, listing all the blog posts of a particular blog.
273 """
274 blog_slug = request.matchdict['blog_slug']
275 blog = get_blog_by_slug(request, blog_slug, author=url_user.id)
276 if not blog:
277 return render_404(request)
278
279 all_blog_posts = blog.get_all_blog_posts(u'processed').order_by(MediaEntry.created.desc())
280 pagination = Pagination(page, all_blog_posts)
281 pagination.per_page = 8
282 blog_posts_on_a_page = pagination()
283
284 return render_to_response(
285 request,
286 'mediagoblin/blog/blog_post_listing.html',
287 {'blog_posts': blog_posts_on_a_page,
288 'pagination': pagination,
289 'blog_owner': url_user,
290 'blog':blog
291 })
292
293
294 @require_active_login
295 def draft_view(request):
296 blog_slug = request.matchdict.get('blog_slug', None)
297 blog_post_slug = request.matchdict.get('blog_post_slug', None)
298 user = request.matchdict.get('user')
299 blog = get_blog_by_slug(request, blog_slug, author=request.user.id)
300 blogpost = request.db.MediaEntry.query.filter_by(state = u'failed', actor=request.user.id, slug=blog_post_slug).first()
301
302 if not blog or not blogpost:
303 return render_404(request)
304
305 return render_to_response(
306 request,
307 'mediagoblin/blog/blogpost_draft_view.html',
308 {'blogpost':blogpost,
309 'blog': blog
310 })
311
312
313 @require_active_login
314 def blog_delete(request, **kwargs):
315 """
316 Deletes a blog and media entries, tags associated with it.
317 """
318 url_user = request.matchdict.get('user')
319 owner_user = request.db.LocalUser.query.filter(
320 LocalUser.username==url_user
321 ).first()
322
323 blog_slug = request.matchdict.get('blog_slug', None)
324 blog = get_blog_by_slug(request, blog_slug, author=owner_user.id)
325 if not blog:
326 return render_404(request)
327
328 form = blog_forms.ConfirmDeleteForm(request.form)
329 if request.user.id == blog.author or request.user.has_privilege(u'admin'):
330 if request.method == 'POST' and form.validate():
331 if form.confirm.data is True:
332 blog.delete()
333 messages.add_message(
334 request,
335 messages.SUCCESS,
336 _('You deleted the Blog.'))
337 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
338 user=request.user.username)
339 else:
340 messages.add_message(
341 request,
342 messages.ERROR,
343 _("The media was not deleted because you didn't check "
344 "that you were sure."))
345 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
346 user=request.user.username)
347 else:
348 if request.user.has_privilege(u'admin'):
349 messages.add_message(
350 request,
351 messages.WARNING,
352 _("You are about to delete another user's Blog. "
353 "Proceed with caution."))
354 return render_to_response(
355 request,
356 'mediagoblin/blog/blog_confirm_delete.html',
357 {'blog':blog,
358 'form':form
359 })
360 else:
361 messages.add_message(
362 request,
363 messages.ERROR,
364 _("The blog was not deleted because you have no rights."))
365 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
366 user=request.user.username)
367
368
369 def blog_about_view(request):
370 """
371 Page containing blog description and statistics
372 """
373 blog_slug = request.matchdict.get('blog_slug', None)
374 url_user = request.matchdict.get('user', None)
375
376 user = request.db.LocalUser.query.filter(
377 LocalUser.username==url_user
378 ).first()
379
380 if user:
381 blog = get_blog_by_slug(request, blog_slug, author=user.id)
382
383 if not user or not blog:
384 return render_404(request)
385
386 else:
387 blog_posts_processed = blog.get_all_blog_posts(u'processed').count()
388 return render_to_response(
389 request,
390 'mediagoblin/blog/blog_about.html',
391 {'user': user,
392 'blog': blog,
393 'blogpost_count': blog_posts_processed
394 })