Show More
@@ -38,9 +38,5 b' MaxLandingThreads = 20' | |||||
38 | # Enable archiving threads instead of deletion when the thread limit is reached |
|
38 | # Enable archiving threads instead of deletion when the thread limit is reached | |
39 | ArchiveThreads = true |
|
39 | ArchiveThreads = true | |
40 |
|
40 | |||
41 | [External] |
|
|||
42 | # Thread update |
|
|||
43 | WebsocketsEnabled = false |
|
|||
44 |
|
||||
45 | [RSS] |
|
41 | [RSS] | |
46 | MaxItems = 20 |
|
42 | MaxItems = 20 |
@@ -1,11 +1,7 b'' | |||||
1 | from boards.abstracts.settingsmanager import get_settings_manager, \ |
|
1 | from boards.abstracts.settingsmanager import get_settings_manager, \ | |
2 | SETTING_LAST_NOTIFICATION_ID, SETTING_IMAGE_VIEWER, SETTING_ONLY_FAVORITES |
|
2 | SETTING_LAST_NOTIFICATION_ID, SETTING_IMAGE_VIEWER, SETTING_ONLY_FAVORITES | |
|
3 | from boards.models import Banner | |||
3 | from boards.models.user import Notification |
|
4 | from boards.models.user import Notification | |
4 | from boards.models import Banner |
|
|||
5 |
|
||||
6 | __author__ = 'neko259' |
|
|||
7 |
|
||||
8 | import neboard |
|
|||
9 | from boards import settings |
|
5 | from boards import settings | |
10 | from boards.models import Post, Tag, Thread |
|
6 | from boards.models import Post, Tag, Thread | |
11 |
|
7 |
@@ -264,31 +264,6 b' class Post(models.Model, Viewable):' | |||||
264 | return get_exporter(format_type).export(self, request, |
|
264 | return get_exporter(format_type).export(self, request, | |
265 | include_last_update) |
|
265 | include_last_update) | |
266 |
|
266 | |||
267 | def notify_clients(self, recursive=True): |
|
|||
268 | """ |
|
|||
269 | Sends post HTML data to the thread web socket. |
|
|||
270 | """ |
|
|||
271 |
|
||||
272 | if not settings.get_bool('External', 'WebsocketsEnabled'): |
|
|||
273 | return |
|
|||
274 |
|
||||
275 | thread_ids = list() |
|
|||
276 | self.get_thread().notify_clients() |
|
|||
277 |
|
||||
278 | if recursive: |
|
|||
279 | for reply_number in re.finditer(REGEX_REPLY, self.get_raw_text()): |
|
|||
280 | post_id = reply_number.group(1) |
|
|||
281 |
|
||||
282 | try: |
|
|||
283 | ref_post = Post.objects.get(id=post_id) |
|
|||
284 |
|
||||
285 | if ref_post.get_thread().id not in thread_ids: |
|
|||
286 | # If post is in this thread, its thread was already notified. |
|
|||
287 | # Otherwise, notify its thread separately. |
|
|||
288 | ref_post.notify_clients(recursive=False) |
|
|||
289 | except ObjectDoesNotExist: |
|
|||
290 | pass |
|
|||
291 |
|
||||
292 | def _build_url(self): |
|
267 | def _build_url(self): | |
293 | opening = self.is_opening() |
|
268 | opening = self.is_opening() | |
294 | opening_id = self.id if opening else self.get_thread().get_opening_post_id() |
|
269 | opening_id = self.id if opening else self.get_thread().get_opening_post_id() |
@@ -1,20 +1,17 b'' | |||||
1 | import logging |
|
1 | import logging | |
2 | from adjacent import Client |
|
|||
3 | from datetime import timedelta |
|
2 | from datetime import timedelta | |
4 |
|
3 | |||
5 |
|
4 | from django.db import models, transaction | ||
6 | from django.db.models import Count, Sum, QuerySet, Q |
|
5 | from django.db.models import Count, Sum, QuerySet, Q | |
7 | from django.utils import timezone |
|
6 | from django.utils import timezone | |
8 | from django.db import models, transaction |
|
|||
9 |
|
7 | |||
10 | from boards.models.attachment import FILE_TYPES_IMAGE |
|
8 | import boards | |
|
9 | from boards import settings | |||
11 | from boards.models import STATUS_BUMPLIMIT, STATUS_ACTIVE, STATUS_ARCHIVE |
|
10 | from boards.models import STATUS_BUMPLIMIT, STATUS_ACTIVE, STATUS_ARCHIVE | |
12 |
|
11 | from boards.models.attachment import FILE_TYPES_IMAGE | ||
13 | from boards import settings |
|
|||
14 | import boards |
|
|||
15 | from boards.utils import cached_result, datetime_to_epoch |
|
|||
16 | from boards.models.post import Post |
|
12 | from boards.models.post import Post | |
17 | from boards.models.tag import Tag |
|
13 | from boards.models.tag import Tag | |
|
14 | from boards.utils import cached_result, datetime_to_epoch | |||
18 |
|
15 | |||
19 | FAV_THREAD_NO_UPDATES = -1 |
|
16 | FAV_THREAD_NO_UPDATES = -1 | |
20 |
|
17 | |||
@@ -244,18 +241,6 b' class Thread(models.Model):' | |||||
244 | post.last_edit_time = last_edit_time |
|
241 | post.last_edit_time = last_edit_time | |
245 | post.save(update_fields=['last_edit_time']) |
|
242 | post.save(update_fields=['last_edit_time']) | |
246 |
|
243 | |||
247 | def notify_clients(self): |
|
|||
248 | if not settings.get_bool('External', 'WebsocketsEnabled'): |
|
|||
249 | return |
|
|||
250 |
|
||||
251 | client = Client() |
|
|||
252 |
|
||||
253 | channel_name = WS_CHANNEL_THREAD + str(self.get_opening_post_id()) |
|
|||
254 | client.publish(channel_name, { |
|
|||
255 | WS_NOTIFICATION_TYPE: WS_NOTIFICATION_TYPE_NEW_POST, |
|
|||
256 | }) |
|
|||
257 | client.send() |
|
|||
258 |
|
||||
259 | def get_absolute_url(self): |
|
244 | def get_absolute_url(self): | |
260 | return self.get_opening_post().get_absolute_url() |
|
245 | return self.get_opening_post().get_absolute_url() | |
261 |
|
246 |
@@ -42,8 +42,6 b' var ALLOWED_FOR_PARTIAL_UPDATE = [' | |||||
42 | var ATTR_CLASS = 'class'; |
|
42 | var ATTR_CLASS = 'class'; | |
43 | var ATTR_UID = 'data-uid'; |
|
43 | var ATTR_UID = 'data-uid'; | |
44 |
|
44 | |||
45 | var wsUser = ''; |
|
|||
46 |
|
||||
47 | var unreadPosts = 0; |
|
45 | var unreadPosts = 0; | |
48 | var documentOriginalTitle = ''; |
|
46 | var documentOriginalTitle = ''; | |
49 |
|
47 | |||
@@ -52,56 +50,6 b" var threadId = $('div.thread').children(" | |||||
52 | var blinkColor = $('<div class="post-blink"></div>').css('background-color'); |
|
50 | var blinkColor = $('<div class="post-blink"></div>').css('background-color'); | |
53 |
|
51 | |||
54 | /** |
|
52 | /** | |
55 | * Connect to websocket server and subscribe to thread updates. On any update we |
|
|||
56 | * request a thread diff. |
|
|||
57 | * |
|
|||
58 | * @returns {boolean} true if connected, false otherwise |
|
|||
59 | */ |
|
|||
60 | function connectWebsocket() { |
|
|||
61 | var metapanel = $('.metapanel')[0]; |
|
|||
62 |
|
||||
63 | var wsHost = metapanel.getAttribute('data-ws-host'); |
|
|||
64 | var wsPort = metapanel.getAttribute('data-ws-port'); |
|
|||
65 |
|
||||
66 | if (wsHost.length > 0 && wsPort.length > 0) { |
|
|||
67 | var centrifuge = new Centrifuge({ |
|
|||
68 | "url": 'ws://' + wsHost + ':' + wsPort + "/connection/websocket", |
|
|||
69 | "project": metapanel.getAttribute('data-ws-project'), |
|
|||
70 | "user": wsUser, |
|
|||
71 | "timestamp": metapanel.getAttribute('data-ws-token-time'), |
|
|||
72 | "token": metapanel.getAttribute('data-ws-token'), |
|
|||
73 | "debug": false |
|
|||
74 | }); |
|
|||
75 |
|
||||
76 | centrifuge.on('error', function(error_message) { |
|
|||
77 | console.log("Error connecting to websocket server."); |
|
|||
78 | console.log(error_message); |
|
|||
79 | console.log("Using javascript update instead."); |
|
|||
80 |
|
||||
81 | // If websockets don't work, enable JS update instead |
|
|||
82 | enableJsUpdate() |
|
|||
83 | }); |
|
|||
84 |
|
||||
85 | centrifuge.on('connect', function() { |
|
|||
86 | var channelName = 'thread:' + threadId; |
|
|||
87 | centrifuge.subscribe(channelName, function(message) { |
|
|||
88 | getThreadDiff(); |
|
|||
89 | }); |
|
|||
90 |
|
||||
91 | // For the case we closed the browser and missed some updates |
|
|||
92 | getThreadDiff(); |
|
|||
93 | $('#autoupdate').hide(); |
|
|||
94 | }); |
|
|||
95 |
|
||||
96 | centrifuge.connect(); |
|
|||
97 |
|
||||
98 | return true; |
|
|||
99 | } else { |
|
|||
100 | return false; |
|
|||
101 | } |
|
|||
102 | } |
|
|||
103 |
|
||||
104 | /** |
|
|||
105 | * Get diff of the posts from the current thread timestamp. |
|
53 | * Get diff of the posts from the current thread timestamp. | |
106 | * This is required if the browser was closed and some post updates were |
|
54 | * This is required if the browser was closed and some post updates were | |
107 | * missed. |
|
55 | * missed. | |
@@ -226,15 +174,7 b' function enableJsUpdate() {' | |||||
226 | } |
|
174 | } | |
227 |
|
175 | |||
228 | function initAutoupdate() { |
|
176 | function initAutoupdate() { | |
229 | if (location.protocol === 'https:') { |
|
177 | return enableJsUpdate(); | |
230 | return enableJsUpdate(); |
|
|||
231 | } else { |
|
|||
232 | if (connectWebsocket()) { |
|
|||
233 | return true; |
|
|||
234 | } else { |
|
|||
235 | return enableJsUpdate(); |
|
|||
236 | } |
|
|||
237 | } |
|
|||
238 | } |
|
178 | } | |
239 |
|
179 | |||
240 | function getReplyCount() { |
|
180 | function getReplyCount() { |
@@ -24,11 +24,7 b'' | |||||
24 |
|
24 | |||
25 | <span class="metapanel" |
|
25 | <span class="metapanel" | |
26 | data-last-update="{{ last_update }}" |
|
26 | data-last-update="{{ last_update }}" | |
27 | data-ws-token-time="{{ ws_token_time }}" |
|
27 | data-ws-token-time="{{ ws_token_time }}"> | |
28 | data-ws-token="{{ ws_token }}" |
|
|||
29 | data-ws-project="{{ ws_project }}" |
|
|||
30 | data-ws-host="{{ ws_host }}" |
|
|||
31 | data-ws-port="{{ ws_port }}"> |
|
|||
32 |
|
28 | |||
33 | {% with replies_count=thread.get_reply_count%} |
|
29 | {% with replies_count=thread.get_reply_count%} | |
34 | ♥ <span id="reply-count">{{ thread.get_reply_count }}</span>{% if thread.has_post_limit %}/{{ thread.max_posts }}{% endif %} |
|
30 | ♥ <span id="reply-count">{{ thread.get_reply_count }}</span>{% if thread.has_post_limit %}/{{ thread.max_posts }}{% endif %} |
@@ -155,11 +155,7 b' class AllThreadsView(PostMixin, FileUplo' | |||||
155 | ip=ip, tags=tags, |
|
155 | ip=ip, tags=tags, | |
156 | tripcode=form.get_tripcode(), |
|
156 | tripcode=form.get_tripcode(), | |
157 | monochrome=monochrome, images=images, |
|
157 | monochrome=monochrome, images=images, | |
158 |
file_urls |
|
158 | file_urls=file_urls) | |
159 |
|
||||
160 | # This is required to update the threads to which posts we have replied |
|
|||
161 | # when creating this one |
|
|||
162 | post.notify_clients() |
|
|||
163 |
|
159 | |||
164 | if form.is_subscribe(): |
|
160 | if form.is_subscribe(): | |
165 | settings_manager = get_settings_manager(request) |
|
161 | settings_manager = get_settings_manager(request) |
@@ -24,11 +24,6 b" REQ_POST_ID = 'post_id'" | |||||
24 |
|
24 | |||
25 | CONTEXT_LASTUPDATE = "last_update" |
|
25 | CONTEXT_LASTUPDATE = "last_update" | |
26 | CONTEXT_THREAD = 'thread' |
|
26 | CONTEXT_THREAD = 'thread' | |
27 | CONTEXT_WS_TOKEN = 'ws_token' |
|
|||
28 | CONTEXT_WS_PROJECT = 'ws_project' |
|
|||
29 | CONTEXT_WS_HOST = 'ws_host' |
|
|||
30 | CONTEXT_WS_PORT = 'ws_port' |
|
|||
31 | CONTEXT_WS_TIME = 'ws_token_time' |
|
|||
32 | CONTEXT_MODE = 'mode' |
|
27 | CONTEXT_MODE = 'mode' | |
33 | CONTEXT_OP = 'opening_post' |
|
28 | CONTEXT_OP = 'opening_post' | |
34 | CONTEXT_FAVORITE = 'is_favorite' |
|
29 | CONTEXT_FAVORITE = 'is_favorite' | |
@@ -75,16 +70,6 b' class ThreadView(BaseBoardView, PostMixi' | |||||
75 | params[CONTEXT_FAVORITE] = favorite |
|
70 | params[CONTEXT_FAVORITE] = favorite | |
76 | params[CONTEXT_RSS_URL] = self.get_rss_url(post_id) |
|
71 | params[CONTEXT_RSS_URL] = self.get_rss_url(post_id) | |
77 |
|
72 | |||
78 | if settings.get_bool('External', 'WebsocketsEnabled'): |
|
|||
79 | token_time = format(timezone.now(), u'U') |
|
|||
80 |
|
||||
81 | params[CONTEXT_WS_TIME] = token_time |
|
|||
82 | params[CONTEXT_WS_TOKEN] = utils.get_websocket_token( |
|
|||
83 | timestamp=token_time) |
|
|||
84 | params[CONTEXT_WS_PROJECT] = neboard.settings.CENTRIFUGE_PROJECT_ID |
|
|||
85 | params[CONTEXT_WS_HOST] = request.get_host().split(':')[0] |
|
|||
86 | params[CONTEXT_WS_PORT] = neboard.settings.CENTRIFUGE_PORT |
|
|||
87 |
|
||||
88 | params.update(self.get_data(thread_to_show)) |
|
73 | params.update(self.get_data(thread_to_show)) | |
89 |
|
74 | |||
90 | return render(request, self.get_template(), params) |
|
75 | return render(request, self.get_template(), params) | |
@@ -139,7 +124,6 b' class ThreadView(BaseBoardView, PostMixi' | |||||
139 | thread=post_thread, ip=ip, |
|
124 | thread=post_thread, ip=ip, | |
140 | tripcode=form.get_tripcode(), |
|
125 | tripcode=form.get_tripcode(), | |
141 | images=images, file_urls=file_urls) |
|
126 | images=images, file_urls=file_urls) | |
142 | post.notify_clients() |
|
|||
143 |
|
127 | |||
144 | if form.is_subscribe(): |
|
128 | if form.is_subscribe(): | |
145 | settings_manager = get_settings_manager(request) |
|
129 | settings_manager = get_settings_manager(request) |
@@ -188,15 +188,6 b" ALLOWED_HOSTS = ['*']" | |||||
188 |
|
188 | |||
189 | POSTING_DELAY = 20 # seconds |
|
189 | POSTING_DELAY = 20 # seconds | |
190 |
|
190 | |||
191 | # Websocket settins |
|
|||
192 | CENTRIFUGE_HOST = 'localhost' |
|
|||
193 | CENTRIFUGE_PORT = '9090' |
|
|||
194 |
|
||||
195 | CENTRIFUGE_ADDRESS = 'http://{}:{}'.format(CENTRIFUGE_HOST, CENTRIFUGE_PORT) |
|
|||
196 | CENTRIFUGE_PROJECT_ID = '<project id here>' |
|
|||
197 | CENTRIFUGE_PROJECT_SECRET = '<project secret here>' |
|
|||
198 | CENTRIFUGE_TIMEOUT = 5 |
|
|||
199 |
|
||||
200 | SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' |
|
191 | SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' | |
201 |
|
192 | |||
202 | # Debug middlewares |
|
193 | # Debug middlewares |
General Comments 0
You need to be logged in to leave comments.
Login now