diff --git a/board/admin.py b/board/admin.py
index f4c6a25..691ee72 100644
--- a/board/admin.py
+++ b/board/admin.py
@@ -1,6 +1,6 @@
from django.contrib import admin
from django.utils.safestring import mark_safe
-from board.models import Board, Post, ReportReason, Report
+from board.models import Board, Post, ReportReason, ReportRecord
@admin.register(Board)
@@ -18,9 +18,13 @@ class ReportReasonAdmin(admin.ModelAdmin):
pass
-@admin.register(Report)
-class ReportAdmin(admin.ModelAdmin):
- readonly_fields = ("post", "reason", "ip")
+@admin.register(ReportRecord)
+class ReportRecordAdmin(admin.ModelAdmin):
+ ordering = (
+ "-urgent",
+ "-weight",
+ )
+ readonly_fields = ("post",)
list_display = ("post_thumbnail", "post_body")
save_as = False
@@ -32,7 +36,12 @@ class ReportAdmin(admin.ModelAdmin):
def post_body(self, obj):
html = ""
+ if obj.urgent:
+ html += '
'
+ else:
+ html += "
"
if obj.post.subject:
html += f"
{obj.post.subject}"
html += f"
{obj.post.text}
"
+ html += "
"
return mark_safe(html)
diff --git a/board/forms.py b/board/forms.py
index b04d735..0a0b7b3 100644
--- a/board/forms.py
+++ b/board/forms.py
@@ -1,6 +1,7 @@
from django.conf import settings
+from django.db import transaction
from django.forms import ModelForm
-from board.models import Post, Report
+from board.models import Post, Report, ReportRecord
from hcaptcha.fields import hCaptchaField
@@ -50,6 +51,8 @@ class ReportForm(ModelForm):
This requires the board and the IP address to be specified.
"""
+ # uses report_form.html
+
class Meta:
model = Report
fields = ["reason"]
@@ -57,4 +60,14 @@ class ReportForm(ModelForm):
def __init__(self, *args, op, board, ip, **kwargs):
super(ReportForm, self).__init__(*args, **kwargs)
self.instance.ip = ip
- self.instance.post = op
+ self.op = op
+
+ def clean(self):
+ # Get or create the record before creating the model
+ with transaction.atomic():
+ try:
+ record = ReportRecord.objects.get(post=self.op)
+ except ReportRecord.DoesNotExist:
+ record = ReportRecord.objects.create(post=self.op)
+ self.instance.record = record
+ return super(ReportForm, self).clean()
diff --git a/board/models.py b/board/models.py
index 371963d..8dd3757 100644
--- a/board/models.py
+++ b/board/models.py
@@ -1,11 +1,11 @@
from datetime import timedelta
import os
from pathlib import Path
-from django.db import models
-from django.db.models import signals
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
+from django.db import models
+from django.db.models import signals
from django.dispatch import receiver
from django.urls import reverse
from django.utils import timezone
@@ -218,15 +218,51 @@ class ReportReason(models.Model):
return self.reason
-class Report(models.Model):
+class ReportRecord(models.Model):
# Post that this report is for
- post = models.ForeignKey("Post", on_delete=models.CASCADE)
+ post = models.OneToOneField("Post", on_delete=models.CASCADE)
+ # Report weight
+ weight = models.IntegerField(default=0)
+ # If this report is urgent or not
+ urgent = models.BooleanField(default=False)
+
+ # def urgent(self) -> bool:
+ # return self.report_set().aggregate(
+
+
+class Report(models.Model):
+ """
+ There are two reasons why this model exists:
+
+ 1. In the report view in the Django admin, there is probably not a good way
+ to specially modify the list of reports. Since we don't want to see every
+ single report, we need a way to limit this *in data* rather than in code.
+ We accomplish this by having:
+ - Report model, which is all reports unique to users.
+ - ReportRecord model, which is the collection of all reports unique to posts.
+ 2. We want to keep a log of all reports created by users, in case we think
+ they are abusing the system.
+ """
+
+ # The report that was made by this user
+ record = models.ForeignKey("ReportRecord", on_delete=models.CASCADE)
# Reason for this report
reason = models.ForeignKey("ReportReason", on_delete=models.SET_NULL, null=True)
# IP address of the reporter
ip = models.GenericIPAddressField()
+@receiver(signals.post_save, sender=Report)
+def report_created(sender, instance, created, **kwargs):
+ if created:
+ # get the total weight, this is probably going to be more reliable than
+ # adding the weight every time
+ weights = [report.reason.weight for report in instance.record.report_set.all()]
+ instance.record.weight = sum(weights)
+ instance.record.urgent |= instance.reason.urgent
+ instance.record.save()
+
+
class Ban(models.Model):
# IP address of the reporter
ip = models.GenericIPAddressField()
@@ -239,7 +275,7 @@ class Ban(models.Model):
# The time that this ban was created.
created = models.DateTimeField(auto_now_add=True)
# Expiration date of this ban.
- expires = models.DateTimeField(auto_now_add=True)
+ expires = models.DateTimeField()
class BanTemplate(models.Model):
@@ -249,4 +285,5 @@ class BanTemplate(models.Model):
duration = models.DurationField()
def create_ban(self, ip: str) -> Ban:
- return Ban.objects.create(ip=ip, ban_reason=self.ban_reason)
+ expires = timezone.now() + self.duration
+ return Ban.objects.create(ip=ip, ban_reason=self.ban_reason, expires=expires)
diff --git a/board/templates/admin/board/reportrecord/change_list.html b/board/templates/admin/board/reportrecord/change_list.html
new file mode 100644
index 0000000..e7c073c
--- /dev/null
+++ b/board/templates/admin/board/reportrecord/change_list.html
@@ -0,0 +1,13 @@
+{% extends "admin/change_list.html" %}
+{% block extrastyle %}
+{{ block.super }}
+
+{% endblock extrastyle %}
\ No newline at end of file
diff --git a/board/views.py b/board/views.py
index e829d81..a42b856 100644
--- a/board/views.py
+++ b/board/views.py
@@ -4,7 +4,7 @@ from django.shortcuts import render, get_object_or_404
from django.views.generic import DetailView
from django.views.generic.edit import CreateView
from django.urls import reverse, reverse_lazy
-from board.models import Post, Board, Report
+from board.models import Post, Board, Report, ReportRecord
from board.forms import PostForm, ReplyForm, ReportForm
__all__ = ("BoardView", "PostView", "ReportView")