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