categoriestracker.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. from django.db.models import F
  2. from django.utils import timezone
  3. from misago.threads.permissions import exclude_invisible_threads
  4. from . import signals
  5. from .dates import is_date_tracked
  6. from .models import CategoryRead
  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. )
  24. for record in categories_records:
  25. category = categories_dict[record.category_id]
  26. category.last_read_on = record.last_read_on
  27. category.is_read = category.last_read_on >= category.last_post_on
  28. def make_read(categories):
  29. now = timezone.now()
  30. for category in categories:
  31. category.last_read_on = now
  32. category.is_read = True
  33. def start_record(user, category):
  34. user.categoryread_set.create(
  35. category=category,
  36. last_read_on=user.joined_on,
  37. )
  38. def sync_record(user, category):
  39. cutoff_date = user.joined_on
  40. try:
  41. category_record = user.categoryread_set.get(category=category)
  42. if category_record.last_read_on > cutoff_date:
  43. cutoff_date = category_record.last_read_on
  44. except CategoryRead.DoesNotExist:
  45. category_record = None
  46. recorded_threads = category.thread_set.filter(last_post_on__gt=cutoff_date)
  47. recorded_threads = exclude_invisible_threads(
  48. user, [category], recorded_threads)
  49. all_threads_count = recorded_threads.count()
  50. read_threads = user.threadread_set.filter(
  51. category=category,
  52. last_read_on__gt=cutoff_date
  53. )
  54. read_threads_count = read_threads.filter(
  55. thread__last_post_on__lte=F("last_read_on")
  56. ).count()
  57. category_is_read = read_threads_count == all_threads_count
  58. if category_is_read:
  59. signals.category_read.send(sender=user, category=category)
  60. if category_record:
  61. if category_is_read:
  62. category_record.last_read_on = timezone.now()
  63. else:
  64. category_record.last_read_on = cutoff_date
  65. category_record.save(update_fields=['last_read_on'])
  66. else:
  67. if category_is_read:
  68. last_read_on = timezone.now()
  69. else:
  70. last_read_on = cutoff_date
  71. category_record = user.categoryread_set.create(
  72. category=category,
  73. last_read_on=last_read_on
  74. )
  75. def read_category(user, category):
  76. categories = [category.pk]
  77. if not category.is_leaf_node():
  78. queryset = category.get_descendants().filter(id__in=user.acl['visible_categories'])
  79. categories += queryset.values_list('id', flat=True)
  80. user.categoryread_set.filter(category_id__in=categories).delete()
  81. now = timezone.now()
  82. new_reads = []
  83. for category in categories:
  84. new_reads.append(CategoryRead(
  85. user=user,
  86. category_id=category,
  87. last_read_on=now,
  88. ))
  89. if new_reads:
  90. CategoryRead.objects.bulk_create(new_reads)
  91. signals.category_read.send(sender=user, category=category)