categoriestracker.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from django.db.models import F
  2. from django.utils import timezone
  3. from misago.readtracker import signals
  4. from misago.readtracker.dates import is_date_tracked
  5. from misago.readtracker.models import CategoryRead
  6. from misago.threads.permissions import exclude_invisible_threads
  7. __all__ = ['make_read_aware', 'sync_record']
  8. def make_read_aware(user, categories):
  9. if not hasattr(categories, '__iter__'):
  10. categories = [categories]
  11. if user.is_anonymous():
  12. make_read(categories)
  13. return None
  14. categories_dict = {}
  15. for category in categories:
  16. category.last_read_on = user.joined_on
  17. category.is_read = not is_date_tracked(category.last_post_on, user)
  18. if not category.is_read:
  19. categories_dict[category.pk] = category
  20. if categories_dict:
  21. categories_records = user.categoryread_set.filter(
  22. category__in=categories_dict.keys())
  23. for record in categories_records:
  24. category = categories_dict[record.category_id]
  25. category.last_read_on = record.last_read_on
  26. category.is_read = category.last_read_on >= category.last_post_on
  27. def make_read(categories):
  28. now = timezone.now()
  29. for category in categories:
  30. category.last_read_on = now
  31. category.is_read = True
  32. def start_record(user, category):
  33. user.categoryread_set.create(
  34. category=category,
  35. last_read_on=user.joined_on,
  36. )
  37. def sync_record(user, category):
  38. cutoff_date = user.joined_on
  39. try:
  40. category_record = user.categoryread_set.get(category=category)
  41. if category_record.last_read_on > cutoff_date:
  42. cutoff_date = category_record.last_read_on
  43. except CategoryRead.DoesNotExist:
  44. category_record = None
  45. recorded_threads = category.thread_set.filter(last_post_on__gt=cutoff_date)
  46. recorded_threads = exclude_invisible_threads(
  47. user, [category], recorded_threads)
  48. all_threads_count = recorded_threads.count()
  49. read_threads = user.threadread_set.filter(
  50. category=category, last_read_on__gt=cutoff_date)
  51. read_threads_count = read_threads.filter(
  52. thread__last_post_on__lte=F("last_read_on")).count()
  53. category_is_read = read_threads_count == all_threads_count
  54. if category_is_read:
  55. signals.category_read.send(sender=user, category=category)
  56. if category_record:
  57. if category_is_read:
  58. category_record.last_read_on = category_record.last_read_on
  59. else:
  60. category_record.last_read_on = cutoff_date
  61. category_record.save(update_fields=['last_read_on'])
  62. else:
  63. if category_is_read:
  64. last_read_on = timezone.now()
  65. else:
  66. last_read_on = cutoff_date
  67. category_record = user.categoryread_set.create(
  68. category=category,
  69. last_read_on=last_read_on)
  70. def read_category(user, category):
  71. if category.is_leaf_node():
  72. categories = [category]
  73. else:
  74. categories = category.get_descendants(include_self=True)
  75. user.categoryread_set.filter(category__in=categories).delete()
  76. now = timezone.now()
  77. new_reads = []
  78. for category in categories:
  79. new_reads.append(CategoryRead(
  80. user=user,
  81. category=category,
  82. last_read_on=now,
  83. ))
  84. if new_reads:
  85. CategoryRead.objects.bulk_create(new_reads)
  86. signals.category_read.send(sender=user, category=category)