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