trackers.py 3.6 KB

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