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