categoriestracker.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. user.categoryread_set.create(
  32. category=category,
  33. last_read_on=user.joined_on,
  34. )
  35. def sync_record(user, category):
  36. cutoff_date = get_cutoff_date()
  37. if user.joined_on > cutoff_date:
  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. all_threads = category.thread_set.filter(last_post_on__gt=cutoff_date)
  46. all_threads_count = exclude_invisible_threads(user, [category], all_threads).count()
  47. read_threads_count = user.threadread_set.filter(
  48. category=category,
  49. thread__in=all_threads,
  50. last_read_on__gt=cutoff_date,
  51. thread__last_post_on__lte=F("last_read_on"),
  52. ).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 = timezone.now()
  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, last_read_on=last_read_on
  69. )
  70. def read_category(user, category):
  71. categories = [category.pk]
  72. if not category.is_leaf_node():
  73. categories += category.get_descendants().filter(
  74. id__in=user.acl_cache['visible_categories'],
  75. ).values_list(
  76. 'id',
  77. flat=True,
  78. )
  79. user.categoryread_set.filter(category_id__in=categories).delete()
  80. user.threadread_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)