threadstracker.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. def make_read(threads):
  32. for thread in threads:
  33. thread.unread_replies = 0
  34. thread.is_read = True
  35. def make_thread_read_aware(user, thread):
  36. thread.is_read = True
  37. if user.is_authenticated() and is_date_tracked(user, thread.last_post_on):
  38. try:
  39. record = user.threadread_set.filter(thread=thread).all()[0]
  40. thread.last_read_on = record.last_read_on
  41. thread.is_new = False
  42. thread.is_read = thread.last_post_on <= record.last_read_on
  43. thread.read_record = record
  44. except IndexError:
  45. thread.read_record = None
  46. thread.is_new = True
  47. thread.is_read = False
  48. thread.last_read_on = user.joined_on
  49. def make_posts_read_aware(user, thread, posts):
  50. try:
  51. is_thread_read = thread.is_read
  52. except AttributeError:
  53. raise ValueError("thread passed make_posts_read_aware should be "
  54. "read aware too via make_thread_read_aware")
  55. if is_thread_read:
  56. for post in posts:
  57. post.is_read = True
  58. else:
  59. for post in posts:
  60. if is_date_tracked(user, post.updated_on):
  61. post.is_read = post.updated_on <= thread.last_read_on
  62. else:
  63. post.is_read = True
  64. def read_thread(user, thread, last_read_reply):
  65. if not thread.is_read:
  66. if thread.last_read_on < last_read_reply.updated_on:
  67. sync_record(user, thread, last_read_reply)
  68. def sync_record(user, thread, last_read_reply):
  69. read_replies = count_read_replies(user, thread, last_read_reply)
  70. if thread.read_record:
  71. thread.read_record.read_replies = read_replies
  72. thread.read_record.last_read_on = last_read_reply.updated_on
  73. thread.read_record.save(update_fields=['read_replies', 'last_read_on'])
  74. else:
  75. user.threadread_set.create(
  76. forum=thread.forum,
  77. thread=thread,
  78. read_replies=read_replies,
  79. last_read_on=last_read_reply.updated_on)
  80. if last_read_reply.updated_on == thread.last_post_on:
  81. signals.thread_read.send(sender=user, thread=thread)
  82. forumstracker.sync_record(user, thread.forum)
  83. def count_read_replies(user, thread, last_read_reply):
  84. if last_read_reply.updated_on >= thread.last_read_on:
  85. return 0
  86. else:
  87. last_reply_date = last_read_reply.last_read_on
  88. queryset = thread.post_set.filter(last_read_on__lte=last_reply_date)
  89. queryset = queryset.filter(is_moderated=False)
  90. return queryset.count() - 1 # - starters post