warnings.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. from collections import OrderedDict
  2. from datetime import timedelta
  3. from django.conf import settings
  4. from django.db import models
  5. from django.utils import timezone
  6. from django.utils.encoding import python_2_unicode_compatible
  7. from django.utils.translation import ugettext_lazy as _
  8. from misago.core import threadstore
  9. from misago.core.cache import cache
  10. __all__ = [
  11. 'RESTRICT_NO', 'RESTRICT_MODERATOR_REVIEW', 'RESTRICT_DISALLOW',
  12. 'RESTRICTIONS_CHOICES', 'WarningLevel', 'UserWarning'
  13. ]
  14. CACHE_NAME = 'misago_warning_levels'
  15. RESTRICT_NO = 0
  16. RESTRICT_MODERATOR_REVIEW = 1
  17. RESTRICT_DISALLOW = 2
  18. RESTRICTIONS_CHOICES = (
  19. (RESTRICT_NO, _("No restrictions")),
  20. (RESTRICT_MODERATOR_REVIEW, _("Review by moderator")),
  21. (RESTRICT_DISALLOW, _("Disallowed")),
  22. )
  23. class WarningLevelManager(models.Manager):
  24. def dict(self):
  25. return self.get_levels_from_threadstore()
  26. def get_levels_from_threadstore(self):
  27. levels = threadstore.get(CACHE_NAME, 'nada')
  28. if levels == 'nada':
  29. levels = self.get_levels_from_cache()
  30. threadstore.set(CACHE_NAME, levels)
  31. return levels
  32. def get_levels_from_cache(self):
  33. levels = cache.get(CACHE_NAME, 'nada')
  34. if levels == 'nada':
  35. levels = self.get_levels_from_database()
  36. cache.set(CACHE_NAME, levels)
  37. return levels
  38. def get_levels_from_database(self):
  39. levels = [(0, None)]
  40. for level, obj in enumerate(self.order_by('level')):
  41. levels.append((level + 1, obj))
  42. return OrderedDict(levels)
  43. @python_2_unicode_compatible
  44. class WarningLevel(models.Model):
  45. name = models.CharField(max_length=255)
  46. level = models.PositiveIntegerField(default=1, db_index=True)
  47. length_in_minutes = models.PositiveIntegerField(default=0)
  48. restricts_posting_replies = models.PositiveIntegerField(
  49. default=RESTRICT_NO)
  50. restricts_posting_threads = models.PositiveIntegerField(
  51. default=RESTRICT_NO)
  52. objects = WarningLevelManager()
  53. def __str__(self):
  54. return self.name
  55. def save(self, *args, **kwargs):
  56. if not self.pk:
  57. self.set_level()
  58. super(WarningLevel, self).save(*args, **kwargs)
  59. cache.delete(CACHE_NAME)
  60. def delete(self, *args, **kwargs):
  61. super(WarningLevel, self).delete(*args, **kwargs)
  62. cache.delete(CACHE_NAME)
  63. @property
  64. def has_restrictions(self):
  65. return self.restricts_posting_replies or self.restricts_posting_threads
  66. @property
  67. def is_replying_moderated(self):
  68. return self.restricts_posting_replies == RESTRICT_MODERATOR_REVIEW
  69. @property
  70. def is_replying_disallowed(self):
  71. return self.restricts_posting_replies == RESTRICT_DISALLOW
  72. @property
  73. def is_starting_threads_moderated(self):
  74. return self.restricts_posting_threads == RESTRICT_MODERATOR_REVIEW
  75. @property
  76. def is_starting_threads_disallowed(self):
  77. return self.restricts_posting_threads == RESTRICT_DISALLOW
  78. def set_level(self):
  79. try:
  80. self.level = WarningLevel.objects.latest('level').level + 1
  81. except WarningLevel.DoesNotExist:
  82. self.level = 1
  83. class UserWarning(models.Model):
  84. user = models.ForeignKey(settings.AUTH_USER_MODEL,
  85. related_name="warnings")
  86. reason = models.TextField(null=True, blank=True)
  87. given_on = models.DateTimeField(default=timezone.now)
  88. giver = models.ForeignKey(settings.AUTH_USER_MODEL,
  89. null=True, blank=True,
  90. on_delete=models.SET_NULL,
  91. related_name="warnings_given")
  92. giver_username = models.CharField(max_length=255)
  93. giver_slug = models.CharField(max_length=255)
  94. is_canceled = models.BooleanField(default=False)
  95. canceled_on = models.DateTimeField(null=True, blank=True)
  96. canceler = models.ForeignKey(settings.AUTH_USER_MODEL,
  97. null=True, blank=True,
  98. on_delete=models.SET_NULL,
  99. related_name="warnings_canceled")
  100. canceler_username = models.CharField(max_length=255)
  101. canceler_slug = models.CharField(max_length=255)
  102. def cancel(self, canceler):
  103. self.is_canceled = True
  104. self.canceled_on = timezone.now()
  105. self.canceler = canceler
  106. self.canceler_username = canceler.username
  107. self.canceler_slug = canceler.slug
  108. self.save(update_fields=(
  109. 'is_canceled',
  110. 'canceled_on',
  111. 'canceler',
  112. 'canceler_username',
  113. 'canceler_slug',
  114. ))
  115. def is_expired(self, valid_for):
  116. return timezone.now() > self.given_on + timedelta(minutes=valid_for)