##// END OF EJS Templates
Check if the post is OP when opening a thread with post ID
neko259 -
r490:0e717b22 1.6-dev
parent child Browse files
Show More
@@ -1,611 +1,616 b''
1 from datetime import datetime, timedelta
1 from datetime import datetime, timedelta
2 from django.db.models import Count
2 from django.db.models import Count
3
3
4 OLD_USER_AGE_DAYS = 90
4 OLD_USER_AGE_DAYS = 90
5
5
6 __author__ = 'neko259'
6 __author__ = 'neko259'
7
7
8 import hashlib
8 import hashlib
9 import string
9 import string
10 import time
10 import time
11 import re
11 import re
12
12
13 from django.core import serializers
13 from django.core import serializers
14 from django.core.urlresolvers import reverse
14 from django.core.urlresolvers import reverse
15 from django.http import HttpResponseRedirect, Http404
15 from django.http import HttpResponseRedirect, Http404
16 from django.http.response import HttpResponse
16 from django.http.response import HttpResponse
17 from django.template import RequestContext
17 from django.template import RequestContext
18 from django.shortcuts import render, redirect, get_object_or_404
18 from django.shortcuts import render, redirect, get_object_or_404
19 from django.utils import timezone
19 from django.utils import timezone
20 from django.db import transaction
20 from django.db import transaction
21 from django.views.decorators.cache import cache_page
21 from django.views.decorators.cache import cache_page
22 from django.views.i18n import javascript_catalog
22 from django.views.i18n import javascript_catalog
23
23
24 from boards import forms
24 from boards import forms
25 import boards
25 import boards
26 from boards import utils
26 from boards import utils
27 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
27 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
28 ThreadCaptchaForm, PostCaptchaForm, LoginForm, ModeratorSettingsForm
28 ThreadCaptchaForm, PostCaptchaForm, LoginForm, ModeratorSettingsForm
29 from boards.models import Post, Tag, Ban, User
29 from boards.models import Post, Tag, Ban, User
30 from boards.models.post import SETTING_MODERATE, REGEX_REPLY
30 from boards.models.post import SETTING_MODERATE, REGEX_REPLY
31 from boards.models.user import RANK_USER
31 from boards.models.user import RANK_USER
32 from boards import authors
32 from boards import authors
33 from boards.utils import get_client_ip
33 from boards.utils import get_client_ip
34 import neboard
34 import neboard
35
35
36
36
37 BAN_REASON_SPAM = 'Autoban: spam bot'
37 BAN_REASON_SPAM = 'Autoban: spam bot'
38 MODE_GALLERY = 'gallery'
38 MODE_GALLERY = 'gallery'
39 MODE_NORMAL = 'normal'
39 MODE_NORMAL = 'normal'
40
40
41
41
42 def index(request, page=0):
42 def index(request, page=0):
43 context = _init_default_context(request)
43 context = _init_default_context(request)
44
44
45 if utils.need_include_captcha(request):
45 if utils.need_include_captcha(request):
46 threadFormClass = ThreadCaptchaForm
46 threadFormClass = ThreadCaptchaForm
47 kwargs = {'request': request}
47 kwargs = {'request': request}
48 else:
48 else:
49 threadFormClass = ThreadForm
49 threadFormClass = ThreadForm
50 kwargs = {}
50 kwargs = {}
51
51
52 if request.method == 'POST':
52 if request.method == 'POST':
53 form = threadFormClass(request.POST, request.FILES,
53 form = threadFormClass(request.POST, request.FILES,
54 error_class=PlainErrorList, **kwargs)
54 error_class=PlainErrorList, **kwargs)
55 form.session = request.session
55 form.session = request.session
56
56
57 if form.is_valid():
57 if form.is_valid():
58 return _new_post(request, form)
58 return _new_post(request, form)
59 if form.need_to_ban:
59 if form.need_to_ban:
60 # Ban user because he is suspected to be a bot
60 # Ban user because he is suspected to be a bot
61 _ban_current_user(request)
61 _ban_current_user(request)
62 else:
62 else:
63 form = threadFormClass(error_class=PlainErrorList, **kwargs)
63 form = threadFormClass(error_class=PlainErrorList, **kwargs)
64
64
65 threads = []
65 threads = []
66 for thread_to_show in Post.objects.get_threads(page=int(page)):
66 for thread_to_show in Post.objects.get_threads(page=int(page)):
67 threads.append(_get_template_thread(thread_to_show))
67 threads.append(_get_template_thread(thread_to_show))
68
68
69 # TODO Make this generic for tag and threads list pages
69 # TODO Make this generic for tag and threads list pages
70 context['threads'] = None if len(threads) == 0 else threads
70 context['threads'] = None if len(threads) == 0 else threads
71 context['form'] = form
71 context['form'] = form
72 context['current_page'] = int(page)
72 context['current_page'] = int(page)
73
73
74 page_count = Post.objects.get_thread_page_count()
74 page_count = Post.objects.get_thread_page_count()
75 context['pages'] = range(page_count) if page_count > 0 else [0]
75 context['pages'] = range(page_count) if page_count > 0 else [0]
76 page = int(page)
76 page = int(page)
77 if page < page_count - 1:
77 if page < page_count - 1:
78 context['next_page'] = str(page + 1)
78 context['next_page'] = str(page + 1)
79 if page > 0:
79 if page > 0:
80 context['prev_page'] = str(page - 1)
80 context['prev_page'] = str(page - 1)
81
81
82 return render(request, 'boards/posting_general.html',
82 return render(request, 'boards/posting_general.html',
83 context)
83 context)
84
84
85
85
86 def archive(request, page=0):
86 def archive(request, page=0):
87 context = _init_default_context(request)
87 context = _init_default_context(request)
88
88
89 threads = []
89 threads = []
90 for thread_to_show in Post.objects.get_threads(page=int(page),
90 for thread_to_show in Post.objects.get_threads(page=int(page),
91 archived=True):
91 archived=True):
92 threads.append(_get_template_thread(thread_to_show))
92 threads.append(_get_template_thread(thread_to_show))
93
93
94 context['threads'] = threads
94 context['threads'] = threads
95 context['current_page'] = int(page)
95 context['current_page'] = int(page)
96
96
97 page_count = Post.objects.get_thread_page_count(archived=True)
97 page_count = Post.objects.get_thread_page_count(archived=True)
98 context['pages'] = range(page_count) if page_count > 0 else [0]
98 context['pages'] = range(page_count) if page_count > 0 else [0]
99 page = int(page)
99 page = int(page)
100 if page < page_count - 1:
100 if page < page_count - 1:
101 context['next_page'] = str(page + 1)
101 context['next_page'] = str(page + 1)
102 if page > 0:
102 if page > 0:
103 context['prev_page'] = str(page - 1)
103 context['prev_page'] = str(page - 1)
104
104
105 return render(request, 'boards/archive.html', context)
105 return render(request, 'boards/archive.html', context)
106
106
107
107
108 @transaction.atomic
108 @transaction.atomic
109 def _new_post(request, form, opening_post=None):
109 def _new_post(request, form, opening_post=None):
110 """Add a new post (in thread or as a reply)."""
110 """Add a new post (in thread or as a reply)."""
111
111
112 ip = get_client_ip(request)
112 ip = get_client_ip(request)
113 is_banned = Ban.objects.filter(ip=ip).exists()
113 is_banned = Ban.objects.filter(ip=ip).exists()
114
114
115 if is_banned:
115 if is_banned:
116 return redirect(you_are_banned)
116 return redirect(you_are_banned)
117
117
118 data = form.cleaned_data
118 data = form.cleaned_data
119
119
120 title = data['title']
120 title = data['title']
121 text = data['text']
121 text = data['text']
122
122
123 text = _remove_invalid_links(text)
123 text = _remove_invalid_links(text)
124
124
125 if 'image' in data.keys():
125 if 'image' in data.keys():
126 image = data['image']
126 image = data['image']
127 else:
127 else:
128 image = None
128 image = None
129
129
130 tags = []
130 tags = []
131
131
132 if not opening_post:
132 if not opening_post:
133 tag_strings = data['tags']
133 tag_strings = data['tags']
134
134
135 if tag_strings:
135 if tag_strings:
136 tag_strings = tag_strings.split(' ')
136 tag_strings = tag_strings.split(' ')
137 for tag_name in tag_strings:
137 for tag_name in tag_strings:
138 tag_name = string.lower(tag_name.strip())
138 tag_name = string.lower(tag_name.strip())
139 if len(tag_name) > 0:
139 if len(tag_name) > 0:
140 tag, created = Tag.objects.get_or_create(name=tag_name)
140 tag, created = Tag.objects.get_or_create(name=tag_name)
141 tags.append(tag)
141 tags.append(tag)
142 post_thread = None
142 post_thread = None
143 else:
143 else:
144 post_thread = opening_post.thread_new
144 post_thread = opening_post.thread_new
145
145
146 post = Post.objects.create_post(title=title, text=text, ip=ip,
146 post = Post.objects.create_post(title=title, text=text, ip=ip,
147 thread=post_thread, image=image,
147 thread=post_thread, image=image,
148 tags=tags, user=_get_user(request))
148 tags=tags, user=_get_user(request))
149
149
150 thread_to_show = (opening_post.id if opening_post else post.id)
150 thread_to_show = (opening_post.id if opening_post else post.id)
151
151
152 if opening_post:
152 if opening_post:
153 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
153 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
154 '#' + str(post.id))
154 '#' + str(post.id))
155 else:
155 else:
156 return redirect(thread, post_id=thread_to_show)
156 return redirect(thread, post_id=thread_to_show)
157
157
158
158
159 def tag(request, tag_name, page=0):
159 def tag(request, tag_name, page=0):
160 """
160 """
161 Get all tag threads. Threads are split in pages, so some page is
161 Get all tag threads. Threads are split in pages, so some page is
162 requested. Default page is 0.
162 requested. Default page is 0.
163 """
163 """
164
164
165 tag = get_object_or_404(Tag, name=tag_name)
165 tag = get_object_or_404(Tag, name=tag_name)
166 threads = []
166 threads = []
167 for thread_to_show in Post.objects.get_threads(page=int(page), tag=tag):
167 for thread_to_show in Post.objects.get_threads(page=int(page), tag=tag):
168 threads.append(_get_template_thread(thread_to_show))
168 threads.append(_get_template_thread(thread_to_show))
169
169
170 if request.method == 'POST':
170 if request.method == 'POST':
171 form = ThreadForm(request.POST, request.FILES,
171 form = ThreadForm(request.POST, request.FILES,
172 error_class=PlainErrorList)
172 error_class=PlainErrorList)
173 form.session = request.session
173 form.session = request.session
174
174
175 if form.is_valid():
175 if form.is_valid():
176 return _new_post(request, form)
176 return _new_post(request, form)
177 if form.need_to_ban:
177 if form.need_to_ban:
178 # Ban user because he is suspected to be a bot
178 # Ban user because he is suspected to be a bot
179 _ban_current_user(request)
179 _ban_current_user(request)
180 else:
180 else:
181 form = forms.ThreadForm(initial={'tags': tag_name},
181 form = forms.ThreadForm(initial={'tags': tag_name},
182 error_class=PlainErrorList)
182 error_class=PlainErrorList)
183
183
184 context = _init_default_context(request)
184 context = _init_default_context(request)
185 context['threads'] = None if len(threads) == 0 else threads
185 context['threads'] = None if len(threads) == 0 else threads
186 context['tag'] = tag
186 context['tag'] = tag
187 context['current_page'] = int(page)
187 context['current_page'] = int(page)
188
188
189 page_count = Post.objects.get_thread_page_count(tag=tag)
189 page_count = Post.objects.get_thread_page_count(tag=tag)
190 context['pages'] = range(page_count)
190 context['pages'] = range(page_count)
191 page = int(page)
191 page = int(page)
192 if page < page_count - 1:
192 if page < page_count - 1:
193 context['next_page'] = str(page + 1)
193 context['next_page'] = str(page + 1)
194 if page > 0:
194 if page > 0:
195 context['prev_page'] = str(page - 1)
195 context['prev_page'] = str(page - 1)
196
196
197 context['form'] = form
197 context['form'] = form
198
198
199 return render(request, 'boards/posting_general.html',
199 return render(request, 'boards/posting_general.html',
200 context)
200 context)
201
201
202
202
203 def thread(request, post_id, mode=MODE_NORMAL):
203 def thread(request, post_id, mode=MODE_NORMAL):
204 """Get all thread posts"""
204 """Get all thread posts"""
205
205
206 if utils.need_include_captcha(request):
206 if utils.need_include_captcha(request):
207 postFormClass = PostCaptchaForm
207 postFormClass = PostCaptchaForm
208 kwargs = {'request': request}
208 kwargs = {'request': request}
209 else:
209 else:
210 postFormClass = PostForm
210 postFormClass = PostForm
211 kwargs = {}
211 kwargs = {}
212
212
213 opening_post = get_object_or_404(Post, id=post_id)
213 opening_post = get_object_or_404(Post, id=post_id)
214
215 # If this is not OP, don't show it as it is
216 if not opening_post.is_opening():
217 raise Http404
218
214 if request.method == 'POST' and not opening_post.thread_new.archived:
219 if request.method == 'POST' and not opening_post.thread_new.archived:
215 form = postFormClass(request.POST, request.FILES,
220 form = postFormClass(request.POST, request.FILES,
216 error_class=PlainErrorList, **kwargs)
221 error_class=PlainErrorList, **kwargs)
217 form.session = request.session
222 form.session = request.session
218
223
219 if form.is_valid():
224 if form.is_valid():
220 return _new_post(request, form, opening_post)
225 return _new_post(request, form, opening_post)
221 if form.need_to_ban:
226 if form.need_to_ban:
222 # Ban user because he is suspected to be a bot
227 # Ban user because he is suspected to be a bot
223 _ban_current_user(request)
228 _ban_current_user(request)
224 else:
229 else:
225 form = postFormClass(error_class=PlainErrorList, **kwargs)
230 form = postFormClass(error_class=PlainErrorList, **kwargs)
226
231
227 thread_to_show = opening_post.thread_new
232 thread_to_show = opening_post.thread_new
228
233
229 context = _init_default_context(request)
234 context = _init_default_context(request)
230
235
231 posts = thread_to_show.get_replies()
236 posts = thread_to_show.get_replies()
232 context['form'] = form
237 context['form'] = form
233 context["last_update"] = _datetime_to_epoch(thread_to_show.last_edit_time)
238 context["last_update"] = _datetime_to_epoch(thread_to_show.last_edit_time)
234 context["thread"] = thread_to_show
239 context["thread"] = thread_to_show
235
240
236 if MODE_NORMAL == mode:
241 if MODE_NORMAL == mode:
237 context['bumpable'] = thread_to_show.can_bump()
242 context['bumpable'] = thread_to_show.can_bump()
238 if context['bumpable']:
243 if context['bumpable']:
239 context['posts_left'] = neboard.settings.MAX_POSTS_PER_THREAD - posts \
244 context['posts_left'] = neboard.settings.MAX_POSTS_PER_THREAD - posts \
240 .count()
245 .count()
241 context['bumplimit_progress'] = str(
246 context['bumplimit_progress'] = str(
242 float(context['posts_left']) /
247 float(context['posts_left']) /
243 neboard.settings.MAX_POSTS_PER_THREAD * 100)
248 neboard.settings.MAX_POSTS_PER_THREAD * 100)
244
249
245 context['posts'] = posts
250 context['posts'] = posts
246
251
247 document = 'boards/thread.html'
252 document = 'boards/thread.html'
248 elif MODE_GALLERY == mode:
253 elif MODE_GALLERY == mode:
249 context['posts'] = posts.filter(image_width__gt=0)
254 context['posts'] = posts.filter(image_width__gt=0)
250
255
251 document = 'boards/thread_gallery.html'
256 document = 'boards/thread_gallery.html'
252 else:
257 else:
253 raise Http404
258 raise Http404
254
259
255 return render(request, document, context)
260 return render(request, document, context)
256
261
257
262
258 def login(request):
263 def login(request):
259 """Log in with user id"""
264 """Log in with user id"""
260
265
261 context = _init_default_context(request)
266 context = _init_default_context(request)
262
267
263 if request.method == 'POST':
268 if request.method == 'POST':
264 form = LoginForm(request.POST, request.FILES,
269 form = LoginForm(request.POST, request.FILES,
265 error_class=PlainErrorList)
270 error_class=PlainErrorList)
266 form.session = request.session
271 form.session = request.session
267
272
268 if form.is_valid():
273 if form.is_valid():
269 user = User.objects.get(user_id=form.cleaned_data['user_id'])
274 user = User.objects.get(user_id=form.cleaned_data['user_id'])
270 request.session['user_id'] = user.id
275 request.session['user_id'] = user.id
271 return redirect(index)
276 return redirect(index)
272
277
273 else:
278 else:
274 form = LoginForm()
279 form = LoginForm()
275
280
276 context['form'] = form
281 context['form'] = form
277
282
278 return render(request, 'boards/login.html', context)
283 return render(request, 'boards/login.html', context)
279
284
280
285
281 def settings(request):
286 def settings(request):
282 """User's settings"""
287 """User's settings"""
283
288
284 context = _init_default_context(request)
289 context = _init_default_context(request)
285 user = _get_user(request)
290 user = _get_user(request)
286 is_moderator = user.is_moderator()
291 is_moderator = user.is_moderator()
287
292
288 if request.method == 'POST':
293 if request.method == 'POST':
289 with transaction.atomic():
294 with transaction.atomic():
290 if is_moderator:
295 if is_moderator:
291 form = ModeratorSettingsForm(request.POST,
296 form = ModeratorSettingsForm(request.POST,
292 error_class=PlainErrorList)
297 error_class=PlainErrorList)
293 else:
298 else:
294 form = SettingsForm(request.POST, error_class=PlainErrorList)
299 form = SettingsForm(request.POST, error_class=PlainErrorList)
295
300
296 if form.is_valid():
301 if form.is_valid():
297 selected_theme = form.cleaned_data['theme']
302 selected_theme = form.cleaned_data['theme']
298
303
299 user.save_setting('theme', selected_theme)
304 user.save_setting('theme', selected_theme)
300
305
301 if is_moderator:
306 if is_moderator:
302 moderate = form.cleaned_data['moderate']
307 moderate = form.cleaned_data['moderate']
303 user.save_setting(SETTING_MODERATE, moderate)
308 user.save_setting(SETTING_MODERATE, moderate)
304
309
305 return redirect(settings)
310 return redirect(settings)
306 else:
311 else:
307 selected_theme = _get_theme(request)
312 selected_theme = _get_theme(request)
308
313
309 if is_moderator:
314 if is_moderator:
310 form = ModeratorSettingsForm(initial={'theme': selected_theme,
315 form = ModeratorSettingsForm(initial={'theme': selected_theme,
311 'moderate': context['moderator']},
316 'moderate': context['moderator']},
312 error_class=PlainErrorList)
317 error_class=PlainErrorList)
313 else:
318 else:
314 form = SettingsForm(initial={'theme': selected_theme},
319 form = SettingsForm(initial={'theme': selected_theme},
315 error_class=PlainErrorList)
320 error_class=PlainErrorList)
316
321
317 context['form'] = form
322 context['form'] = form
318
323
319 return render(request, 'boards/settings.html', context)
324 return render(request, 'boards/settings.html', context)
320
325
321
326
322 def all_tags(request):
327 def all_tags(request):
323 """All tags list"""
328 """All tags list"""
324
329
325 context = _init_default_context(request)
330 context = _init_default_context(request)
326 context['all_tags'] = Tag.objects.get_not_empty_tags()
331 context['all_tags'] = Tag.objects.get_not_empty_tags()
327
332
328 return render(request, 'boards/tags.html', context)
333 return render(request, 'boards/tags.html', context)
329
334
330
335
331 def jump_to_post(request, post_id):
336 def jump_to_post(request, post_id):
332 """Determine thread in which the requested post is and open it's page"""
337 """Determine thread in which the requested post is and open it's page"""
333
338
334 post = get_object_or_404(Post, id=post_id)
339 post = get_object_or_404(Post, id=post_id)
335
340
336 if not post.thread:
341 if not post.thread:
337 return redirect(thread, post_id=post.id)
342 return redirect(thread, post_id=post.id)
338 else:
343 else:
339 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
344 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
340 + '#' + str(post.id))
345 + '#' + str(post.id))
341
346
342
347
343 def authors(request):
348 def authors(request):
344 """Show authors list"""
349 """Show authors list"""
345
350
346 context = _init_default_context(request)
351 context = _init_default_context(request)
347 context['authors'] = boards.authors.authors
352 context['authors'] = boards.authors.authors
348
353
349 return render(request, 'boards/authors.html', context)
354 return render(request, 'boards/authors.html', context)
350
355
351
356
352 @transaction.atomic
357 @transaction.atomic
353 def delete(request, post_id):
358 def delete(request, post_id):
354 """Delete post"""
359 """Delete post"""
355
360
356 user = _get_user(request)
361 user = _get_user(request)
357 post = get_object_or_404(Post, id=post_id)
362 post = get_object_or_404(Post, id=post_id)
358
363
359 if user.is_moderator():
364 if user.is_moderator():
360 # TODO Show confirmation page before deletion
365 # TODO Show confirmation page before deletion
361 Post.objects.delete_post(post)
366 Post.objects.delete_post(post)
362
367
363 if not post.thread:
368 if not post.thread:
364 return _redirect_to_next(request)
369 return _redirect_to_next(request)
365 else:
370 else:
366 return redirect(thread, post_id=post.thread.id)
371 return redirect(thread, post_id=post.thread.id)
367
372
368
373
369 @transaction.atomic
374 @transaction.atomic
370 def ban(request, post_id):
375 def ban(request, post_id):
371 """Ban user"""
376 """Ban user"""
372
377
373 user = _get_user(request)
378 user = _get_user(request)
374 post = get_object_or_404(Post, id=post_id)
379 post = get_object_or_404(Post, id=post_id)
375
380
376 if user.is_moderator():
381 if user.is_moderator():
377 # TODO Show confirmation page before ban
382 # TODO Show confirmation page before ban
378 ban, created = Ban.objects.get_or_create(ip=post.poster_ip)
383 ban, created = Ban.objects.get_or_create(ip=post.poster_ip)
379 if created:
384 if created:
380 ban.reason = 'Banned for post ' + str(post_id)
385 ban.reason = 'Banned for post ' + str(post_id)
381 ban.save()
386 ban.save()
382
387
383 return _redirect_to_next(request)
388 return _redirect_to_next(request)
384
389
385
390
386 def you_are_banned(request):
391 def you_are_banned(request):
387 """Show the page that notifies that user is banned"""
392 """Show the page that notifies that user is banned"""
388
393
389 context = _init_default_context(request)
394 context = _init_default_context(request)
390
395
391 ban = get_object_or_404(Ban, ip=utils.get_client_ip(request))
396 ban = get_object_or_404(Ban, ip=utils.get_client_ip(request))
392 context['ban_reason'] = ban.reason
397 context['ban_reason'] = ban.reason
393 return render(request, 'boards/staticpages/banned.html', context)
398 return render(request, 'boards/staticpages/banned.html', context)
394
399
395
400
396 def page_404(request):
401 def page_404(request):
397 """Show page 404 (not found error)"""
402 """Show page 404 (not found error)"""
398
403
399 context = _init_default_context(request)
404 context = _init_default_context(request)
400 return render(request, 'boards/404.html', context)
405 return render(request, 'boards/404.html', context)
401
406
402
407
403 @transaction.atomic
408 @transaction.atomic
404 def tag_subscribe(request, tag_name):
409 def tag_subscribe(request, tag_name):
405 """Add tag to favorites"""
410 """Add tag to favorites"""
406
411
407 user = _get_user(request)
412 user = _get_user(request)
408 tag = get_object_or_404(Tag, name=tag_name)
413 tag = get_object_or_404(Tag, name=tag_name)
409
414
410 if not tag in user.fav_tags.all():
415 if not tag in user.fav_tags.all():
411 user.add_tag(tag)
416 user.add_tag(tag)
412
417
413 return _redirect_to_next(request)
418 return _redirect_to_next(request)
414
419
415
420
416 @transaction.atomic
421 @transaction.atomic
417 def tag_unsubscribe(request, tag_name):
422 def tag_unsubscribe(request, tag_name):
418 """Remove tag from favorites"""
423 """Remove tag from favorites"""
419
424
420 user = _get_user(request)
425 user = _get_user(request)
421 tag = get_object_or_404(Tag, name=tag_name)
426 tag = get_object_or_404(Tag, name=tag_name)
422
427
423 if tag in user.fav_tags.all():
428 if tag in user.fav_tags.all():
424 user.remove_tag(tag)
429 user.remove_tag(tag)
425
430
426 return _redirect_to_next(request)
431 return _redirect_to_next(request)
427
432
428
433
429 def static_page(request, name):
434 def static_page(request, name):
430 """Show a static page that needs only tags list and a CSS"""
435 """Show a static page that needs only tags list and a CSS"""
431
436
432 context = _init_default_context(request)
437 context = _init_default_context(request)
433 return render(request, 'boards/staticpages/' + name + '.html', context)
438 return render(request, 'boards/staticpages/' + name + '.html', context)
434
439
435
440
436 def api_get_post(request, post_id):
441 def api_get_post(request, post_id):
437 """
442 """
438 Get the JSON of a post. This can be
443 Get the JSON of a post. This can be
439 used as and API for external clients.
444 used as and API for external clients.
440 """
445 """
441
446
442 post = get_object_or_404(Post, id=post_id)
447 post = get_object_or_404(Post, id=post_id)
443
448
444 json = serializers.serialize("json", [post], fields=(
449 json = serializers.serialize("json", [post], fields=(
445 "pub_time", "_text_rendered", "title", "text", "image",
450 "pub_time", "_text_rendered", "title", "text", "image",
446 "image_width", "image_height", "replies", "tags"
451 "image_width", "image_height", "replies", "tags"
447 ))
452 ))
448
453
449 return HttpResponse(content=json)
454 return HttpResponse(content=json)
450
455
451
456
452 def get_post(request, post_id):
457 def get_post(request, post_id):
453 """Get the html of a post. Used for popups."""
458 """Get the html of a post. Used for popups."""
454
459
455 post = get_object_or_404(Post, id=post_id)
460 post = get_object_or_404(Post, id=post_id)
456 thread = post.thread_new
461 thread = post.thread_new
457
462
458 context = RequestContext(request)
463 context = RequestContext(request)
459 context["post"] = post
464 context["post"] = post
460 context["can_bump"] = thread.can_bump()
465 context["can_bump"] = thread.can_bump()
461 if "truncated" in request.GET:
466 if "truncated" in request.GET:
462 context["truncated"] = True
467 context["truncated"] = True
463
468
464 return render(request, 'boards/post.html', context)
469 return render(request, 'boards/post.html', context)
465
470
466 @cache_page(86400)
471 @cache_page(86400)
467 def cached_js_catalog(request, domain='djangojs', packages=None):
472 def cached_js_catalog(request, domain='djangojs', packages=None):
468 return javascript_catalog(request, domain, packages)
473 return javascript_catalog(request, domain, packages)
469
474
470
475
471 def _get_theme(request, user=None):
476 def _get_theme(request, user=None):
472 """Get user's CSS theme"""
477 """Get user's CSS theme"""
473
478
474 if not user:
479 if not user:
475 user = _get_user(request)
480 user = _get_user(request)
476 theme = user.get_setting('theme')
481 theme = user.get_setting('theme')
477 if not theme:
482 if not theme:
478 theme = neboard.settings.DEFAULT_THEME
483 theme = neboard.settings.DEFAULT_THEME
479
484
480 return theme
485 return theme
481
486
482
487
483 def _init_default_context(request):
488 def _init_default_context(request):
484 """Create context with default values that are used in most views"""
489 """Create context with default values that are used in most views"""
485
490
486 context = RequestContext(request)
491 context = RequestContext(request)
487
492
488 user = _get_user(request)
493 user = _get_user(request)
489 context['user'] = user
494 context['user'] = user
490 context['tags'] = user.get_sorted_fav_tags()
495 context['tags'] = user.get_sorted_fav_tags()
491 context['posts_per_day'] = float(Post.objects.get_posts_per_day())
496 context['posts_per_day'] = float(Post.objects.get_posts_per_day())
492
497
493 theme = _get_theme(request, user)
498 theme = _get_theme(request, user)
494 context['theme'] = theme
499 context['theme'] = theme
495 context['theme_css'] = 'css/' + theme + '/base_page.css'
500 context['theme_css'] = 'css/' + theme + '/base_page.css'
496
501
497 # This shows the moderator panel
502 # This shows the moderator panel
498 moderate = user.get_setting(SETTING_MODERATE)
503 moderate = user.get_setting(SETTING_MODERATE)
499 if moderate == 'True':
504 if moderate == 'True':
500 context['moderator'] = user.is_moderator()
505 context['moderator'] = user.is_moderator()
501 else:
506 else:
502 context['moderator'] = False
507 context['moderator'] = False
503
508
504 return context
509 return context
505
510
506
511
507 def _get_user(request):
512 def _get_user(request):
508 """
513 """
509 Get current user from the session. If the user does not exist, create
514 Get current user from the session. If the user does not exist, create
510 a new one.
515 a new one.
511 """
516 """
512
517
513 session = request.session
518 session = request.session
514 if not 'user_id' in session:
519 if not 'user_id' in session:
515 request.session.save()
520 request.session.save()
516
521
517 md5 = hashlib.md5()
522 md5 = hashlib.md5()
518 md5.update(session.session_key)
523 md5.update(session.session_key)
519 new_id = md5.hexdigest()
524 new_id = md5.hexdigest()
520
525
521 while User.objects.filter(user_id=new_id).exists():
526 while User.objects.filter(user_id=new_id).exists():
522 md5.update(str(timezone.now()))
527 md5.update(str(timezone.now()))
523 new_id = md5.hexdigest()
528 new_id = md5.hexdigest()
524
529
525 time_now = timezone.now()
530 time_now = timezone.now()
526 user = User.objects.create(user_id=new_id, rank=RANK_USER,
531 user = User.objects.create(user_id=new_id, rank=RANK_USER,
527 registration_time=time_now)
532 registration_time=time_now)
528
533
529 _delete_old_users()
534 _delete_old_users()
530
535
531 session['user_id'] = user.id
536 session['user_id'] = user.id
532 else:
537 else:
533 user = User.objects.get(id=session['user_id'])
538 user = User.objects.get(id=session['user_id'])
534
539
535 return user
540 return user
536
541
537
542
538 def _redirect_to_next(request):
543 def _redirect_to_next(request):
539 """
544 """
540 If a 'next' parameter was specified, redirect to the next page. This is
545 If a 'next' parameter was specified, redirect to the next page. This is
541 used when the user is required to return to some page after the current
546 used when the user is required to return to some page after the current
542 view has finished its work.
547 view has finished its work.
543 """
548 """
544
549
545 if 'next' in request.GET:
550 if 'next' in request.GET:
546 next_page = request.GET['next']
551 next_page = request.GET['next']
547 return HttpResponseRedirect(next_page)
552 return HttpResponseRedirect(next_page)
548 else:
553 else:
549 return redirect(index)
554 return redirect(index)
550
555
551
556
552 @transaction.atomic
557 @transaction.atomic
553 def _ban_current_user(request):
558 def _ban_current_user(request):
554 """Add current user to the IP ban list"""
559 """Add current user to the IP ban list"""
555
560
556 ip = utils.get_client_ip(request)
561 ip = utils.get_client_ip(request)
557 ban, created = Ban.objects.get_or_create(ip=ip)
562 ban, created = Ban.objects.get_or_create(ip=ip)
558 if created:
563 if created:
559 ban.can_read = False
564 ban.can_read = False
560 ban.reason = BAN_REASON_SPAM
565 ban.reason = BAN_REASON_SPAM
561 ban.save()
566 ban.save()
562
567
563
568
564 def _remove_invalid_links(text):
569 def _remove_invalid_links(text):
565 """
570 """
566 Replace invalid links in posts so that they won't be parsed.
571 Replace invalid links in posts so that they won't be parsed.
567 Invalid links are links to non-existent posts
572 Invalid links are links to non-existent posts
568 """
573 """
569
574
570 for reply_number in re.finditer(REGEX_REPLY, text):
575 for reply_number in re.finditer(REGEX_REPLY, text):
571 post_id = reply_number.group(1)
576 post_id = reply_number.group(1)
572 post = Post.objects.filter(id=post_id)
577 post = Post.objects.filter(id=post_id)
573 if not post.exists():
578 if not post.exists():
574 text = string.replace(text, '>>' + post_id, post_id)
579 text = string.replace(text, '>>' + post_id, post_id)
575
580
576 return text
581 return text
577
582
578
583
579 def _datetime_to_epoch(datetime):
584 def _datetime_to_epoch(datetime):
580 return int(time.mktime(timezone.localtime(
585 return int(time.mktime(timezone.localtime(
581 datetime,timezone.get_current_timezone()).timetuple())
586 datetime,timezone.get_current_timezone()).timetuple())
582 * 1000000 + datetime.microsecond)
587 * 1000000 + datetime.microsecond)
583
588
584
589
585 def _get_template_thread(thread_to_show):
590 def _get_template_thread(thread_to_show):
586 """Get template values for thread"""
591 """Get template values for thread"""
587
592
588 last_replies = thread_to_show.get_last_replies()
593 last_replies = thread_to_show.get_last_replies()
589 skipped_replies_count = thread_to_show.get_replies().count() \
594 skipped_replies_count = thread_to_show.get_replies().count() \
590 - len(last_replies) - 1
595 - len(last_replies) - 1
591 return {
596 return {
592 'thread': thread_to_show,
597 'thread': thread_to_show,
593 'op': thread_to_show.get_replies()[0],
598 'op': thread_to_show.get_replies()[0],
594 'bumpable': thread_to_show.can_bump(),
599 'bumpable': thread_to_show.can_bump(),
595 'last_replies': last_replies,
600 'last_replies': last_replies,
596 'skipped_replies': skipped_replies_count,
601 'skipped_replies': skipped_replies_count,
597 }
602 }
598
603
599
604
600 def _delete_old_users():
605 def _delete_old_users():
601 """
606 """
602 Delete users with no favorite tags and posted messages. These can be spam
607 Delete users with no favorite tags and posted messages. These can be spam
603 bots or just old user accounts
608 bots or just old user accounts
604 """
609 """
605
610
606 old_registration_date = datetime.now().date() - timedelta(OLD_USER_AGE_DAYS)
611 old_registration_date = datetime.now().date() - timedelta(OLD_USER_AGE_DAYS)
607
612
608 for user in User.objects.annotate(tags_count=Count('fav_tags')).filter(
613 for user in User.objects.annotate(tags_count=Count('fav_tags')).filter(
609 tags_count=0).filter(registration_time__lt=old_registration_date):
614 tags_count=0).filter(registration_time__lt=old_registration_date):
610 if not Post.objects.filter(user=user).exists():
615 if not Post.objects.filter(user=user).exists():
611 user.delete()
616 user.delete()
General Comments 0
You need to be logged in to leave comments. Login now