threadstracker.py 3.6 KB

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