categoriestracker.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 get_cutoff_date, is_date_tracked
  6. from .models import CategoryRead
  7. def make_read_aware(user, categories):
  8. if not hasattr(categories, '__iter__'):
  9. categories = [categories]
  10. if user.is_anonymous:
  11. make_read(categories)
  12. return None
  13. categories_dict = {}
  14. for category in categories:
  15. category.last_read_on = user.joined_on
  16. category.is_read = not is_date_tracked(category.last_post_on, user)
  17. if not category.is_read:
  18. categories_dict[category.pk] = category
  19. if categories_dict:
  20. categories_records = user.categoryread_set.filter(category__in=categories_dict.keys())
  21. for record in categories_records:
  22. category = categories_dict[record.category_id]
  23. category.last_read_on = record.last_read_on
  24. category.is_read = category.last_read_on >= category.last_post_on
  25. def make_read(categories):
  26. now = timezone.now()
  27. for category in categories:
  28. category.last_read_on = now
  29. category.is_read = True
  30. def start_record(user, category):
  31. from misago.core import deprecations
  32. deprecations.warn("categoriestracker.start_record has been deprecated")
  33. user.categoryread_set.create(
  34. category=category,
  35. last_read_on=user.joined_on,
  36. )
  37. def sync_record(user, category):
  38. from misago.core import deprecations
  39. deprecations.warn("categoriestracker.sync_record has been deprecated")
  40. cutoff_date = get_cutoff_date()
  41. if user.joined_on > cutoff_date:
  42. cutoff_date = user.joined_on
  43. try:
  44. category_record = user.categoryread_set.get(category=category)
  45. if category_record.last_read_on > cutoff_date:
  46. cutoff_date = category_record.last_read_on
  47. except CategoryRead.DoesNotExist:
  48. category_record = None
  49. all_threads = category.thread_set.filter(last_post_on__gt=cutoff_date)
  50. all_threads_count = exclude_invisible_threads(user, [category], all_threads).count()
  51. read_threads_count = user.threadread_set.filter(
  52. category=category,
  53. thread__in=all_threads,
  54. last_read_on__gt=cutoff_date,
  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, last_read_on=last_read_on
  73. )
  74. def read_category(user, category):
  75. from misago.core import deprecations
  76. deprecations.warn("categoriestracker.read_category has been deprecated")
  77. categories = [category.pk]
  78. if not category.is_leaf_node():
  79. categories += category.get_descendants().filter(
  80. id__in=user.acl_cache['visible_categories'],
  81. ).values_list(
  82. 'id',
  83. flat=True,
  84. )
  85. user.categoryread_set.filter(category_id__in=categories).delete()
  86. user.threadread_set.filter(category_id__in=categories).delete()
  87. now = timezone.now()
  88. new_reads = []
  89. for category in categories:
  90. new_reads.append(CategoryRead(
  91. user=user,
  92. category_id=category,
  93. last_read_on=now,
  94. ))
  95. if new_reads:
  96. CategoryRead.objects.bulk_create(new_reads)
  97. signals.category_read.send(sender=user, category=category)