threadstracker.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from misago.readtracker import forumstracker, signals
  2. from misago.readtracker.dates import is_date_tracked
  3. __all__ = ['make_read_aware', 'read_thread']
  4. def make_read_aware(user, target):
  5. if hasattr(target, '__iter__'):
  6. make_threads_read_aware(user, target)
  7. else:
  8. make_thread_read_aware(user, target)
  9. def make_threads_read_aware(user, threads):
  10. if user.is_anonymous():
  11. make_read(threads)
  12. return None
  13. threads_dict = {}
  14. for thread in threads:
  15. thread.is_read = not is_date_tracked(user, thread.last_post_on)
  16. thread.is_new = True
  17. if thread.is_read:
  18. thread.unread_replies = 0
  19. else:
  20. thread.unread_replies = thread.replies
  21. threads_dict[thread.pk] = thread
  22. for record in user.threadread_set.filter(thread__in=threads_dict.keys()):
  23. if record.thread_id in threads_dict:
  24. thread = threads_dict[record.thread_id]
  25. thread.is_new = False
  26. thread.is_read = record.last_read_on >= thread.last_post_on
  27. if thread.is_read:
  28. thread.unread_replies = 0
  29. else:
  30. thread.unread_replies = thread.replies - record.read_replies
  31. if thread.unread_replies < 1:
  32. thread.unread_replies = 1
  33. def make_read(threads):
  34. for thread in threads:
  35. thread.unread_replies = 0
  36. thread.is_read = True
  37. def make_thread_read_aware(user, thread):
  38. thread.is_read = True
  39. if user.is_authenticated() and is_date_tracked(user, thread.last_post_on):
  40. try:
  41. record = user.threadread_set.filter(thread=thread).all()[0]
  42. thread.last_read_on = record.last_read_on
  43. thread.is_new = False
  44. thread.is_read = thread.last_post_on <= record.last_read_on
  45. thread.read_record = record
  46. except IndexError:
  47. thread.read_record = None
  48. thread.is_new = True
  49. thread.is_read = False
  50. thread.last_read_on = user.joined_on
  51. def make_posts_read_aware(user, thread, posts):
  52. try:
  53. is_thread_read = thread.is_read
  54. except AttributeError:
  55. raise ValueError("thread passed make_posts_read_aware should be "
  56. "read aware too via make_thread_read_aware")
  57. if is_thread_read:
  58. for post in posts:
  59. post.is_read = True
  60. else:
  61. for post in posts:
  62. if is_date_tracked(user, post.updated_on):
  63. post.is_read = post.updated_on <= thread.last_read_on
  64. else:
  65. post.is_read = True
  66. def read_thread(user, thread, last_read_reply):
  67. if not thread.is_read:
  68. if thread.last_read_on < last_read_reply.updated_on:
  69. sync_record(user, thread, last_read_reply)
  70. def sync_record(user, thread, last_read_reply):
  71. read_replies = count_read_replies(user, thread, last_read_reply)
  72. if thread.read_record:
  73. thread.read_record.read_replies = read_replies
  74. thread.read_record.last_read_on = last_read_reply.updated_on
  75. thread.read_record.save(update_fields=['read_replies', 'last_read_on'])
  76. else:
  77. user.threadread_set.create(
  78. forum=thread.forum,
  79. thread=thread,
  80. read_replies=read_replies,
  81. last_read_on=last_read_reply.updated_on)
  82. signals.thread_tracked.send(sender=user, thread=thread)
  83. if last_read_reply.updated_on == thread.last_post_on:
  84. signals.thread_read.send(sender=user, thread=thread)
  85. forumstracker.sync_record(user, thread.forum)
  86. def count_read_replies(user, thread, last_read_reply):
  87. if last_read_reply.updated_on >= thread.last_read_on:
  88. return 0
  89. else:
  90. last_reply_date = last_read_reply.last_read_on
  91. queryset = thread.post_set.filter(last_read_on__lte=last_reply_date)
  92. queryset = queryset.filter(is_moderated=False)
  93. return queryset.count() - 1 # - starters post