##// END OF EJS Templates
Refactored websockets notifications and updating threads when updating posts
neko259 -
r1088:9cc4c6f4 default
parent child Browse files
Show More
@@ -20,11 +20,6 b' from boards.models.user import Notificat'
20 import boards.models.thread
20 import boards.models.thread
21
21
22
22
23 WS_NOTIFICATION_TYPE_NEW_POST = 'new_post'
24 WS_NOTIFICATION_TYPE = 'notification_type'
25
26 WS_CHANNEL_THREAD = "thread:"
27
28 APP_LABEL_BOARDS = 'boards'
23 APP_LABEL_BOARDS = 'boards'
29
24
30 POSTS_PER_DAY_RANGE = 7
25 POSTS_PER_DAY_RANGE = 7
@@ -195,15 +190,11 b' class Post(models.Model, Viewable):'
195 the server from recalculating the map on every post show.
190 the server from recalculating the map on every post show.
196 """
191 """
197
192
198 post_urls = [REFMAP_STR.format(
193 post_urls = [REFMAP_STR.format(refpost.get_url(), refpost.id)
199 refpost.get_url(), refpost.id) for refpost in self.referenced_posts.all()]
194 for refpost in self.referenced_posts.all()]
200
195
201 self.refmap = ', '.join(post_urls)
196 self.refmap = ', '.join(post_urls)
202
197
203 # TODO Is this still needed?
204 def get_sorted_referenced_posts(self):
205 return self.refmap
206
207 def is_referenced(self) -> bool:
198 def is_referenced(self) -> bool:
208 return self.refmap and len(self.refmap) > 0
199 return self.refmap and len(self.refmap) > 0
209
200
@@ -240,9 +231,6 b' class Post(models.Model, Viewable):'
240
231
241 return self.threads
232 return self.threads
242
233
243 def get_referenced_posts(self) -> list:
244 return self.referenced_posts.only('id', 'threads')
245
246 def get_view(self, moderator=False, need_open_link=False,
234 def get_view(self, moderator=False, need_open_link=False,
247 truncated=False, *args, **kwargs) -> str:
235 truncated=False, *args, **kwargs) -> str:
248 """
236 """
@@ -327,7 +315,7 b' class Post(models.Model, Viewable):'
327 self.get_thread().bump_time)
315 self.get_thread().bump_time)
328 return post_json
316 return post_json
329
317
330 def send_to_websocket(self, request, recursive=True):
318 def notify_clients(self, request, recursive=True):
331 """
319 """
332 Sends post HTML data to the thread web socket.
320 Sends post HTML data to the thread web socket.
333 """
321 """
@@ -335,22 +323,11 b' class Post(models.Model, Viewable):'
335 if not settings.WEBSOCKETS_ENABLED:
323 if not settings.WEBSOCKETS_ENABLED:
336 return
324 return
337
325
338 client = Client()
339
340 logger = logging.getLogger('boards.post.websocket')
341
342 thread_ids = list()
326 thread_ids = list()
343 for thread in self.get_threads().all():
327 for thread in self.get_threads().all():
344 thread_ids.append(thread.id)
328 thread_ids.append(thread.id)
345
329
346 channel_name = WS_CHANNEL_THREAD + str(thread.get_opening_post_id())
330 thread.notify_clients(request)
347 client.publish(channel_name, {
348 WS_NOTIFICATION_TYPE: WS_NOTIFICATION_TYPE_NEW_POST,
349 })
350 client.send()
351
352 logger.info('Sent notification from post #{} to channel {}'.format(
353 self.id, channel_name))
354
331
355 if recursive:
332 if recursive:
356 for reply_number in re.finditer(REGEX_REPLY, self.get_raw_text()):
333 for reply_number in re.finditer(REGEX_REPLY, self.get_raw_text()):
@@ -362,7 +339,7 b' class Post(models.Model, Viewable):'
362 if ref_post.get_threads().exclude(id__in=thread_ids).exists():
339 if ref_post.get_threads().exclude(id__in=thread_ids).exists():
363 # If post is in this thread, its thread was already notified.
340 # If post is in this thread, its thread was already notified.
364 # Otherwise, notify its thread separately.
341 # Otherwise, notify its thread separately.
365 ref_post.send_to_websocket(request, recursive=False)
342 ref_post.notify_clients(request, recursive=False)
366 except ObjectDoesNotExist:
343 except ObjectDoesNotExist:
367 pass
344 pass
368
345
@@ -370,6 +347,13 b' class Post(models.Model, Viewable):'
370 update_fields=None):
347 update_fields=None):
371 self._text_rendered = Parser().parse(self.get_raw_text())
348 self._text_rendered = Parser().parse(self.get_raw_text())
372
349
350 if self.id:
351 for thread in self.get_threads().all():
352 thread.update_bump_status()
353 thread.last_edit_time = self.last_edit_time
354
355 thread.save(update_fields=['last_edit_time', 'bumpable'])
356
373 super().save(force_insert, force_update, using, update_fields)
357 super().save(force_insert, force_update, using, update_fields)
374
358
375 def get_text(self) -> str:
359 def get_text(self) -> str:
@@ -409,31 +393,22 b' class Post(models.Model, Viewable):'
409 referenced_post.last_edit_time = self.pub_time
393 referenced_post.last_edit_time = self.pub_time
410 referenced_post.build_refmap()
394 referenced_post.build_refmap()
411 referenced_post.save(update_fields=['refmap', 'last_edit_time'])
395 referenced_post.save(update_fields=['refmap', 'last_edit_time'])
412
413 referenced_threads = referenced_post.get_threads().all()
414 for thread in referenced_threads:
415 if thread.can_bump():
416 thread.update_bump_status()
417
418 thread.last_edit_time = self.pub_time
419 thread.save(update_fields=['last_edit_time', 'bumpable'])
420 except ObjectDoesNotExist:
396 except ObjectDoesNotExist:
421 pass
397 pass
422
398
423 def connect_threads(self, threads):
399 def connect_threads(self, opening_posts):
424 """
400 """
425 If the referenced post is an OP in another thread,
401 If the referenced post is an OP in another thread,
426 make this post multi-thread.
402 make this post multi-thread.
427 """
403 """
428
404
429 for referenced_post in threads:
405 for opening_post in opening_posts:
430 if referenced_post.is_opening():
406 threads = opening_post.get_threads().all()
431 referenced_threads = referenced_post.get_threads().all()
407 for thread in threads:
432 for thread in referenced_threads:
408 if thread.can_bump():
433 if thread.can_bump():
409 thread.update_bump_status()
434 thread.update_bump_status()
435
410
436 thread.last_edit_time = self.pub_time
411 thread.last_edit_time = self.last_edit_time
437 thread.save(update_fields=['last_edit_time', 'bumpable'])
412 thread.save(update_fields=['last_edit_time', 'bumpable'])
438
413
439 self.threads.add(thread)
414 self.threads.add(thread)
@@ -1,4 +1,5 b''
1 import logging
1 import logging
2 from adjacent import Client
2
3
3 from django.db.models import Count, Sum
4 from django.db.models import Count, Sum
4 from django.utils import timezone
5 from django.utils import timezone
@@ -17,6 +18,12 b' from boards.models.tag import Tag'
17 logger = logging.getLogger(__name__)
18 logger = logging.getLogger(__name__)
18
19
19
20
21 WS_NOTIFICATION_TYPE_NEW_POST = 'new_post'
22 WS_NOTIFICATION_TYPE = 'notification_type'
23
24 WS_CHANNEL_THREAD = "thread:"
25
26
20 class ThreadManager(models.Manager):
27 class ThreadManager(models.Manager):
21 def process_oldest_threads(self):
28 def process_oldest_threads(self):
22 """
29 """
@@ -199,3 +206,15 b' class Thread(models.Model):'
199 self.post_set.update(last_edit_time=self.last_edit_time)
206 self.post_set.update(last_edit_time=self.last_edit_time)
200 for post in self.post_set.all():
207 for post in self.post_set.all():
201 post.threads.update(last_edit_time=self.last_edit_time)
208 post.threads.update(last_edit_time=self.last_edit_time)
209
210 def notify_clients(self, request):
211 if not settings.WEBSOCKETS_ENABLED:
212 return
213
214 client = Client()
215
216 channel_name = WS_CHANNEL_THREAD + str(self.get_opening_post_id())
217 client.publish(channel_name, {
218 WS_NOTIFICATION_TYPE: WS_NOTIFICATION_TYPE_NEW_POST,
219 })
220 client.send() No newline at end of file
@@ -14,11 +14,14 b' class ApiTest(TestCase):'
14 opening_post = Post.objects.create_post(title='title', text='text',
14 opening_post = Post.objects.create_post(title='title', text='text',
15 tags=[tag])
15 tags=[tag])
16
16
17 last_edit_time = datetime_to_epoch(opening_post.last_edit_time)
17 last_edit_time = str(opening_post.last_edit_time)
18
18
19 req = MockRequest()
20 req.GET['thread'] = opening_post.id
21 req.GET['last_update'] = last_edit_time
22 req.GET['last_post'] = opening_post.id
19 # Check the exact timestamp post was added
23 # Check the exact timestamp post was added
20 empty_response = api.api_get_threaddiff(
24 empty_response = api.api_get_threaddiff(req)
21 MockRequest(), str(opening_post.get_thread().id), str(last_edit_time))
22 diff = simplejson.loads(empty_response.content)
25 diff = simplejson.loads(empty_response.content)
23 self.assertEqual(0, len(diff['added']),
26 self.assertEqual(0, len(diff['added']),
24 'There must be no added posts in the diff.')
27 'There must be no added posts in the diff.')
@@ -29,18 +32,23 b' class ApiTest(TestCase):'
29 text='[post]%d[/post]\ntext' % opening_post.id,
32 text='[post]%d[/post]\ntext' % opening_post.id,
30 thread=opening_post.get_thread())
33 thread=opening_post.get_thread())
31
34
35 req = MockRequest()
36 req.GET['thread'] = opening_post.id
37 req.GET['last_update'] = last_edit_time
38 req.GET['last_post'] = opening_post.id
32 # Check the timestamp before post was added
39 # Check the timestamp before post was added
33 response = api.api_get_threaddiff(
40 response = api.api_get_threaddiff(req)
34 MockRequest(), str(opening_post.get_thread().id), str(last_edit_time))
35 diff = simplejson.loads(response.content)
41 diff = simplejson.loads(response.content)
36 self.assertEqual(1, len(diff['added']),
42 self.assertEqual(1, len(diff['added']),
37 'There must be 1 added posts in the diff.')
43 'There must be 1 added posts in the diff.')
38 self.assertEqual(1, len(diff['updated']),
44 self.assertEqual(1, len(diff['updated']),
39 'There must be 1 updated posts in the diff.')
45 'There must be 1 updated posts in the diff.')
40
46
41 empty_response = api.api_get_threaddiff(MockRequest(),
47 req = MockRequest()
42 str(opening_post.get_thread().id),
48 req.GET['thread'] = opening_post.id
43 str(datetime_to_epoch(reply.last_edit_time)))
49 req.GET['last_update'] = str(reply.last_edit_time)
50 req.GET['last_post'] = reply.id
51 empty_response = api.api_get_threaddiff(req)
44 diff = simplejson.loads(empty_response.content)
52 diff = simplejson.loads(empty_response.content)
45 self.assertEqual(0, len(diff['added']),
53 self.assertEqual(0, len(diff['added']),
46 'There must be no added posts in the diff.')
54 'There must be no added posts in the diff.')
@@ -7,7 +7,7 b" NEW_THREAD_PAGE = '/'"
7 THREAD_PAGE_ONE = '/thread/1/'
7 THREAD_PAGE_ONE = '/thread/1/'
8 THREAD_PAGE = '/thread/'
8 THREAD_PAGE = '/thread/'
9 TAG_PAGE = '/tag/'
9 TAG_PAGE = '/tag/'
10 HTTP_CODE_REDIRECT = 301
10 HTTP_CODE_REDIRECT = 302
11 HTTP_CODE_OK = 200
11 HTTP_CODE_OK = 200
12 HTTP_CODE_NOT_FOUND = 404
12 HTTP_CODE_NOT_FOUND = 404
13
13
@@ -45,7 +45,7 b' class PagesTest(TestCase):'
45
45
46 reply_id = Post.objects.create_post('', TEST_TEXT,
46 reply_id = Post.objects.create_post('', TEST_TEXT,
47 thread=Post.objects.all()[0]
47 thread=Post.objects.all()[0]
48 .get_thread())
48 .get_thread()).id
49 response_not_existing = client.get(THREAD_PAGE + str(
49 response_not_existing = client.get(THREAD_PAGE + str(
50 reply_id) + '/')
50 reply_id) + '/')
51 self.assertEqual(HTTP_CODE_REDIRECT, response_not_existing.status_code,
51 self.assertEqual(HTTP_CODE_REDIRECT, response_not_existing.status_code,
@@ -10,6 +10,7 b' HTTP_CODE_OK = 200'
10
10
11 EXCLUDED_VIEWS = {
11 EXCLUDED_VIEWS = {
12 'banned',
12 'banned',
13 'get_thread_diff',
13 }
14 }
14
15
15
16
@@ -133,7 +133,7 b' class AllThreadsView(PostMixin, BaseBoar'
133
133
134 # This is required to update the threads to which posts we have replied
134 # This is required to update the threads to which posts we have replied
135 # when creating this one
135 # when creating this one
136 post.send_to_websocket(request)
136 post.notify_clients(request)
137
137
138 if html_response:
138 if html_response:
139 return redirect(post.get_url())
139 return redirect(post.get_url())
@@ -106,7 +106,7 b' class ThreadView(BaseBoardView, PostMixi'
106
106
107 post = Post.objects.create_post(title=title, text=text, image=image,
107 post = Post.objects.create_post(title=title, text=text, image=image,
108 thread=post_thread, ip=ip, threads=threads)
108 thread=post_thread, ip=ip, threads=threads)
109 post.send_to_websocket(request)
109 post.notify_clients(request)
110
110
111 if html_response:
111 if html_response:
112 if opening_post:
112 if opening_post:
General Comments 0
You need to be logged in to leave comments. Login now