diff --git a/board/forms.py b/board/forms.py index fb24697..519369a 100644 --- a/board/forms.py +++ b/board/forms.py @@ -101,8 +101,27 @@ class ReportForm(ModelForm): record = ReportRecord.objects.get(post=self.op) except ReportRecord.DoesNotExist: record = ReportRecord.objects.create(post=self.op) - if record.report_set.filter(ip=self.instance.ip): + + ip = self.instance.ip + if record.report_set.filter(ip=ip): raise ValidationError(_("You have already reported this post.")) + + # Not sure if it's possible to use the ORM to get a related field of a + # related field - report.record.post.board + board = self.op.board + all_reports = [ + r + for r in Report.objects.filter(ip=ip).order_by("-created") + if r.record.post.board == board + ] + if all_reports: + last_report = all_reports[0] + now = timezone.now() + delta = now - last_report.created + if delta < board.report_cooldown: + raise ValidationError( + _(f"Please wait a few seconds before submitting another report"), + ) self.instance.record = record return super(ReportForm, self).clean() diff --git a/board/models.py b/board/models.py index e1ea7f5..d76260a 100644 --- a/board/models.py +++ b/board/models.py @@ -55,6 +55,9 @@ class Board(models.Model): # The amount of time that users from the same IP address are allowed to make # consecutive posts post_cooldown = models.DurationField(default=timedelta(seconds=60)) + # The amount of time that users from the same IP address are allowed to make + # consecutive reports + report_cooldown = models.DurationField(default=timedelta(seconds=15)) # Auto-sink threshhold. This is the number of replies that a thread can have # before it stops being bumped. autosink = models.IntegerField(default=300) @@ -292,6 +295,8 @@ class Report(models.Model): reason = models.ForeignKey("ReportReason", on_delete=models.CASCADE) # IP address of the reporter ip = models.GenericIPAddressField() + # Time that this report was created + created = models.DateTimeField(auto_now_add=True) @receiver(signals.post_save, sender=Report)