Show More
@@ -1,157 +1,158 b'' | |||||
1 | from django.core.urlresolvers import reverse |
|
1 | from django.core.urlresolvers import reverse | |
2 | from django.db import transaction |
|
2 | from django.db import transaction | |
3 | from django.http import Http404 |
|
3 | from django.http import Http404 | |
4 | from django.shortcuts import get_object_or_404, render, redirect |
|
4 | from django.shortcuts import get_object_or_404, render, redirect | |
5 | from django.views.decorators.cache import never_cache, cache_control |
|
5 | from django.views.decorators.cache import never_cache, cache_control | |
6 | from django.views.generic.edit import FormMixin |
|
6 | from django.views.generic.edit import FormMixin | |
7 |
|
7 | |||
8 | from boards import utils, settings |
|
8 | from boards import utils, settings | |
9 | from boards.forms import PostForm, PlainErrorList |
|
9 | from boards.forms import PostForm, PlainErrorList | |
10 | from boards.models import Post, Ban |
|
10 | from boards.models import Post, Ban | |
11 | from boards.views.banned import BannedView |
|
11 | from boards.views.banned import BannedView | |
12 | from boards.views.base import BaseBoardView, CONTEXT_FORM |
|
12 | from boards.views.base import BaseBoardView, CONTEXT_FORM | |
13 | from boards.views.posting_mixin import PostMixin |
|
13 | from boards.views.posting_mixin import PostMixin | |
14 | import neboard |
|
14 | import neboard | |
15 |
|
15 | |||
16 | TEMPLATE_GALLERY = 'boards/thread_gallery.html' |
|
16 | TEMPLATE_GALLERY = 'boards/thread_gallery.html' | |
17 | TEMPLATE_NORMAL = 'boards/thread.html' |
|
17 | TEMPLATE_NORMAL = 'boards/thread.html' | |
18 |
|
18 | |||
19 | CONTEXT_POSTS = 'posts' |
|
19 | CONTEXT_POSTS = 'posts' | |
20 | CONTEXT_OP = 'opening_post' |
|
20 | CONTEXT_OP = 'opening_post' | |
21 | CONTEXT_BUMPLIMIT_PRG = 'bumplimit_progress' |
|
21 | CONTEXT_BUMPLIMIT_PRG = 'bumplimit_progress' | |
22 | CONTEXT_POSTS_LEFT = 'posts_left' |
|
22 | CONTEXT_POSTS_LEFT = 'posts_left' | |
23 | CONTEXT_LASTUPDATE = "last_update" |
|
23 | CONTEXT_LASTUPDATE = "last_update" | |
24 | CONTEXT_MAX_REPLIES = 'max_replies' |
|
24 | CONTEXT_MAX_REPLIES = 'max_replies' | |
25 | CONTEXT_THREAD = 'thread' |
|
25 | CONTEXT_THREAD = 'thread' | |
26 | CONTEXT_BUMPABLE = 'bumpable' |
|
26 | CONTEXT_BUMPABLE = 'bumpable' | |
27 | CONTEXT_WS_TOKEN = 'ws_token' |
|
27 | CONTEXT_WS_TOKEN = 'ws_token' | |
28 | CONTEXT_WS_PROJECT = 'ws_project' |
|
28 | CONTEXT_WS_PROJECT = 'ws_project' | |
29 | CONTEXT_WS_HOST = 'ws_host' |
|
29 | CONTEXT_WS_HOST = 'ws_host' | |
30 | CONTEXT_WS_PORT = 'ws_port' |
|
30 | CONTEXT_WS_PORT = 'ws_port' | |
31 |
|
31 | |||
32 | FORM_TITLE = 'title' |
|
32 | FORM_TITLE = 'title' | |
33 | FORM_TEXT = 'text' |
|
33 | FORM_TEXT = 'text' | |
34 | FORM_IMAGE = 'image' |
|
34 | FORM_IMAGE = 'image' | |
35 |
|
35 | |||
36 | MODE_GALLERY = 'gallery' |
|
36 | MODE_GALLERY = 'gallery' | |
37 | MODE_NORMAL = 'normal' |
|
37 | MODE_NORMAL = 'normal' | |
38 |
|
38 | |||
39 |
|
39 | |||
40 | class ThreadView(BaseBoardView, PostMixin, FormMixin): |
|
40 | class ThreadView(BaseBoardView, PostMixin, FormMixin): | |
41 |
|
41 | |||
42 | @cache_control(no_cache=True) |
|
42 | @cache_control(no_cache=True) | |
43 | def get(self, request, post_id, mode=MODE_NORMAL, form=None): |
|
43 | def get(self, request, post_id, mode=MODE_NORMAL, form=None): | |
44 | try: |
|
44 | try: | |
45 | opening_post = Post.objects.filter(id=post_id).only('thread_new')[0] |
|
45 | opening_post = Post.objects.filter(id=post_id).only('thread_new')[0] | |
46 | except IndexError: |
|
46 | except IndexError: | |
47 | raise Http404 |
|
47 | raise Http404 | |
48 |
|
48 | |||
49 | # If this is not OP, don't show it as it is |
|
49 | # If this is not OP, don't show it as it is | |
50 | if not opening_post or not opening_post.is_opening(): |
|
50 | if not opening_post or not opening_post.is_opening(): | |
51 | raise Http404 |
|
51 | raise Http404 | |
52 |
|
52 | |||
53 | if not form: |
|
53 | if not form: | |
54 | form = PostForm(error_class=PlainErrorList) |
|
54 | form = PostForm(error_class=PlainErrorList) | |
55 |
|
55 | |||
56 | thread_to_show = opening_post.get_thread() |
|
56 | thread_to_show = opening_post.get_thread() | |
57 |
|
57 | |||
58 | context = self.get_context_data(request=request) |
|
58 | context = self.get_context_data(request=request) | |
59 |
|
59 | |||
60 | context[CONTEXT_FORM] = form |
|
60 | context[CONTEXT_FORM] = form | |
61 | context[CONTEXT_LASTUPDATE] = str(utils.datetime_to_epoch( |
|
61 | context[CONTEXT_LASTUPDATE] = str(utils.datetime_to_epoch( | |
62 | thread_to_show.last_edit_time)) |
|
62 | thread_to_show.last_edit_time)) | |
63 | context[CONTEXT_THREAD] = thread_to_show |
|
63 | context[CONTEXT_THREAD] = thread_to_show | |
64 | context[CONTEXT_MAX_REPLIES] = settings.MAX_POSTS_PER_THREAD |
|
64 | context[CONTEXT_MAX_REPLIES] = settings.MAX_POSTS_PER_THREAD | |
65 |
|
65 | |||
66 | if settings.WEBSOCKETS_ENABLED: |
|
66 | if settings.WEBSOCKETS_ENABLED: | |
67 | context[CONTEXT_WS_TOKEN] = utils.get_websocket_token( |
|
67 | context[CONTEXT_WS_TOKEN] = utils.get_websocket_token( | |
68 | timestamp=context[CONTEXT_LASTUPDATE]) |
|
68 | timestamp=context[CONTEXT_LASTUPDATE]) | |
69 | context[CONTEXT_WS_PROJECT] = neboard.settings.CENTRIFUGE_PROJECT_ID |
|
69 | context[CONTEXT_WS_PROJECT] = neboard.settings.CENTRIFUGE_PROJECT_ID | |
70 | context[CONTEXT_WS_HOST] = request.get_host().split(':')[0] |
|
70 | context[CONTEXT_WS_HOST] = request.get_host().split(':')[0] | |
71 | context[CONTEXT_WS_PORT] = neboard.settings.CENTRIFUGE_PORT |
|
71 | context[CONTEXT_WS_PORT] = neboard.settings.CENTRIFUGE_PORT | |
72 |
|
72 | |||
|
73 | # TODO Move this to subclasses: NormalThreadView, GalleryThreadView etc | |||
73 | if MODE_NORMAL == mode: |
|
74 | if MODE_NORMAL == mode: | |
74 | bumpable = thread_to_show.can_bump() |
|
75 | bumpable = thread_to_show.can_bump() | |
75 | context[CONTEXT_BUMPABLE] = bumpable |
|
76 | context[CONTEXT_BUMPABLE] = bumpable | |
76 | if bumpable: |
|
77 | if bumpable: | |
77 | left_posts = settings.MAX_POSTS_PER_THREAD \ |
|
78 | left_posts = settings.MAX_POSTS_PER_THREAD \ | |
78 | - thread_to_show.get_reply_count() |
|
79 | - thread_to_show.get_reply_count() | |
79 | context[CONTEXT_POSTS_LEFT] = left_posts |
|
80 | context[CONTEXT_POSTS_LEFT] = left_posts | |
80 | context[CONTEXT_BUMPLIMIT_PRG] = str( |
|
81 | context[CONTEXT_BUMPLIMIT_PRG] = str( | |
81 | float(left_posts) / settings.MAX_POSTS_PER_THREAD * 100) |
|
82 | float(left_posts) / settings.MAX_POSTS_PER_THREAD * 100) | |
82 |
|
83 | |||
83 | context[CONTEXT_OP] = opening_post |
|
84 | context[CONTEXT_OP] = opening_post | |
84 |
|
85 | |||
85 | document = TEMPLATE_NORMAL |
|
86 | document = TEMPLATE_NORMAL | |
86 | elif MODE_GALLERY == mode: |
|
87 | elif MODE_GALLERY == mode: | |
87 | context[CONTEXT_POSTS] = thread_to_show.get_replies_with_images( |
|
88 | context[CONTEXT_POSTS] = thread_to_show.get_replies_with_images( | |
88 | view_fields_only=True) |
|
89 | view_fields_only=True) | |
89 |
|
90 | |||
90 | document = TEMPLATE_GALLERY |
|
91 | document = TEMPLATE_GALLERY | |
91 | else: |
|
92 | else: | |
92 | raise Http404 |
|
93 | raise Http404 | |
93 |
|
94 | |||
94 | return render(request, document, context) |
|
95 | return render(request, document, context) | |
95 |
|
96 | |||
96 | def post(self, request, post_id, mode=MODE_NORMAL): |
|
97 | def post(self, request, post_id, mode=MODE_NORMAL): | |
97 | opening_post = get_object_or_404(Post, id=post_id) |
|
98 | opening_post = get_object_or_404(Post, id=post_id) | |
98 |
|
99 | |||
99 | # If this is not OP, don't show it as it is |
|
100 | # If this is not OP, don't show it as it is | |
100 | if not opening_post.is_opening(): |
|
101 | if not opening_post.is_opening(): | |
101 | raise Http404 |
|
102 | raise Http404 | |
102 |
|
103 | |||
103 | if not opening_post.get_thread().archived: |
|
104 | if not opening_post.get_thread().archived: | |
104 | form = PostForm(request.POST, request.FILES, |
|
105 | form = PostForm(request.POST, request.FILES, | |
105 | error_class=PlainErrorList) |
|
106 | error_class=PlainErrorList) | |
106 | form.session = request.session |
|
107 | form.session = request.session | |
107 |
|
108 | |||
108 | if form.is_valid(): |
|
109 | if form.is_valid(): | |
109 | return self.new_post(request, form, opening_post) |
|
110 | return self.new_post(request, form, opening_post) | |
110 | if form.need_to_ban: |
|
111 | if form.need_to_ban: | |
111 | # Ban user because he is suspected to be a bot |
|
112 | # Ban user because he is suspected to be a bot | |
112 | self._ban_current_user(request) |
|
113 | self._ban_current_user(request) | |
113 |
|
114 | |||
114 | return self.get(request, post_id, mode, form) |
|
115 | return self.get(request, post_id, mode, form) | |
115 |
|
116 | |||
116 | @transaction.atomic |
|
117 | @transaction.atomic | |
117 | def new_post(self, request, form, opening_post=None, html_response=True): |
|
118 | def new_post(self, request, form, opening_post=None, html_response=True): | |
118 | """Add a new post (in thread or as a reply).""" |
|
119 | """Add a new post (in thread or as a reply).""" | |
119 |
|
120 | |||
120 | ip = utils.get_client_ip(request) |
|
121 | ip = utils.get_client_ip(request) | |
121 | is_banned = Ban.objects.filter(ip=ip).exists() |
|
122 | is_banned = Ban.objects.filter(ip=ip).exists() | |
122 |
|
123 | |||
123 | if is_banned: |
|
124 | if is_banned: | |
124 | if html_response: |
|
125 | if html_response: | |
125 | return redirect(BannedView().as_view()) |
|
126 | return redirect(BannedView().as_view()) | |
126 | else: |
|
127 | else: | |
127 | return None |
|
128 | return None | |
128 |
|
129 | |||
129 | data = form.cleaned_data |
|
130 | data = form.cleaned_data | |
130 |
|
131 | |||
131 | title = data[FORM_TITLE] |
|
132 | title = data[FORM_TITLE] | |
132 | text = data[FORM_TEXT] |
|
133 | text = data[FORM_TEXT] | |
133 |
|
134 | |||
134 | text = self._remove_invalid_links(text) |
|
135 | text = self._remove_invalid_links(text) | |
135 |
|
136 | |||
136 | if FORM_IMAGE in list(data.keys()): |
|
137 | if FORM_IMAGE in list(data.keys()): | |
137 | image = data[FORM_IMAGE] |
|
138 | image = data[FORM_IMAGE] | |
138 | else: |
|
139 | else: | |
139 | image = None |
|
140 | image = None | |
140 |
|
141 | |||
141 | tags = [] |
|
142 | tags = [] | |
142 |
|
143 | |||
143 | post_thread = opening_post.get_thread() |
|
144 | post_thread = opening_post.get_thread() | |
144 |
|
145 | |||
145 | post = Post.objects.create_post(title=title, text=text, image=image, |
|
146 | post = Post.objects.create_post(title=title, text=text, image=image, | |
146 | thread=post_thread, ip=ip, tags=tags) |
|
147 | thread=post_thread, ip=ip, tags=tags) | |
147 | post.send_to_websocket(request) |
|
148 | post.send_to_websocket(request) | |
148 |
|
149 | |||
149 | 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) | |
150 |
|
151 | |||
151 | if html_response: |
|
152 | if html_response: | |
152 | if opening_post: |
|
153 | if opening_post: | |
153 | return redirect( |
|
154 | return redirect( | |
154 | reverse('thread', kwargs={'post_id': thread_to_show}) |
|
155 | reverse('thread', kwargs={'post_id': thread_to_show}) | |
155 | + '#' + str(post.id)) |
|
156 | + '#' + str(post.id)) | |
156 | else: |
|
157 | else: | |
157 | return post |
|
158 | return post |
General Comments 0
You need to be logged in to leave comments.
Login now