readstrackers.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from datetime import timedelta
  2. from django.conf import settings
  3. from django.utils import timezone
  4. from misago.models import Thread, ForumRead, ThreadRead
  5. class ForumsTracker(object):
  6. def __init__(self, user):
  7. self.user = user
  8. self.cutoff = timezone.now() - timedelta(days=settings.READS_TRACKER_LENGTH)
  9. self.forums = {}
  10. if user.is_authenticated() and settings.READS_TRACKER_LENGTH > 0:
  11. if user.join_date > self.cutoff:
  12. self.cutoff = user.join_date
  13. for forum in ForumRead.objects.filter(user=user).filter(updated__gte=self.cutoff).values('id', 'forum_id', 'updated', 'cleared'):
  14. self.forums[forum['forum_id']] = forum
  15. def is_read(self, forum):
  16. if not self.user.is_authenticated() or not forum.last_thread_date:
  17. return True
  18. try:
  19. return forum.last_thread_date <= self.cutoff or forum.last_thread_date <= self.forums[forum.pk]['cleared']
  20. except KeyError:
  21. return False
  22. class ThreadsTracker(object):
  23. def __init__(self, request, forum):
  24. self.need_create = None
  25. self.need_update = None
  26. self.request = request
  27. self.forum = forum
  28. self.cutoff = timezone.now() - timedelta(days=settings.READS_TRACKER_LENGTH)
  29. if request.user.is_authenticated():
  30. if request.user.join_date > self.cutoff:
  31. self.cutoff = request.user.join_date
  32. try:
  33. self.record = ForumRead.objects.get(user=request.user, forum=forum)
  34. if self.record.cleared > self.cutoff:
  35. self.cutoff = self.record.cleared
  36. except ForumRead.DoesNotExist:
  37. self.record = ForumRead(user=request.user, forum=forum, cleared=self.cutoff)
  38. self.threads = self.record.get_threads()
  39. def read_date(self, thread):
  40. if not self.request.user.is_authenticated():
  41. return timezone.now()
  42. try:
  43. if self.threads[thread.pk].updated > self.cutoff:
  44. return self.threads[thread.pk].updated
  45. except KeyError:
  46. pass
  47. return self.cutoff
  48. def is_read(self, thread):
  49. if not self.request.user.is_authenticated():
  50. return True
  51. try:
  52. return thread.last <= self.cutoff or thread.last <= self.threads[thread.pk].updated
  53. except KeyError:
  54. return False
  55. def set_read(self, thread, post):
  56. if self.request.user.is_authenticated() and post.date > self.cutoff:
  57. try:
  58. self.threads[thread.pk].updated = post.date
  59. self.need_update = self.threads[thread.pk]
  60. except KeyError:
  61. self.need_create = thread
  62. def unread_count(self, queryset=None):
  63. try:
  64. return self.unread_threads
  65. except AttributeError:
  66. self.unread_threads = 0
  67. if queryset == None:
  68. queryset = self.default_queryset()
  69. for thread in queryset.filter(last__gte=self.record.cleared):
  70. if not self.is_read(thread):
  71. self.unread_threads += 1
  72. return self.unread_threads
  73. def sync(self, queryset=None):
  74. now = timezone.now()
  75. if queryset == None:
  76. queryset = self.default_queryset()
  77. if self.need_create:
  78. new_record = ThreadRead(
  79. user=self.request.user,
  80. thread=self.need_create,
  81. forum=self.forum,
  82. updated=now
  83. )
  84. new_record.save(force_insert=True)
  85. self.threads[new_record.thread_id] = new_record
  86. if self.need_update:
  87. self.need_update.updated = now
  88. self.need_update.save(force_update=True)
  89. if self.need_create or self.need_update:
  90. if not self.unread_count(queryset):
  91. self.record.cleared = now
  92. self.record.updated = now
  93. if self.record.pk:
  94. self.record.save(force_update=True)
  95. else:
  96. self.record.save(force_insert=True)
  97. def default_queryset(self):
  98. return self.request.acl.threads.filter_threads(self.request, self.forum, self.forum.thread_set)