diff --git a/app/blueprints/report/__init__.py b/app/blueprints/report/__init__.py
index e2765c51..f3634430 100644
--- a/app/blueprints/report/__init__.py
+++ b/app/blueprints/report/__init__.py
@@ -19,10 +19,10 @@ from flask_babel import lazy_gettext
from flask_login import current_user
from flask_wtf import FlaskForm
from werkzeug.utils import redirect
-from wtforms import TextAreaField, SubmitField, URLField, StringField, RadioField
+from wtforms import TextAreaField, SubmitField, URLField, StringField, RadioField, SelectField
from wtforms.validators import InputRequired, Length, Optional
-from app.models import User, UserRank, Report, db, AuditSeverity, Thread
+from app.models import User, UserRank, Report, db, AuditSeverity, Thread, ReportCategory
from app.tasks.webhooktasks import post_discord_webhook
from app.utils import is_no, abs_url_samesite, normalize_line_endings, rank_required, add_audit_log, abs_url_for, \
add_replies, random_string
@@ -31,6 +31,8 @@ bp = Blueprint("report", __name__)
class ReportForm(FlaskForm):
+ category = SelectField(lazy_gettext("Category"), [InputRequired()], choices=ReportCategory.choices(with_none=True), coerce=ReportCategory.coerce)
+
url = URLField(lazy_gettext("URL"), [Optional()])
title = StringField(lazy_gettext("Subject / Title"), [InputRequired(), Length(10, 300)])
message = TextAreaField(lazy_gettext("Message"), [Optional(), Length(0, 10000)], filters=[normalize_line_endings])
@@ -50,8 +52,12 @@ def report():
form = ReportForm(formdata=request.form) if current_user.is_authenticated else None
if form and request.method == "GET":
+ try:
+ form.category.data = ReportCategory.coerce(request.args.get("category"))
+ except KeyError:
+ pass
form.url.data = url
- form.message.data = request.args.get("message", "")
+ form.title.data = request.args.get("title", "")
if form and form.validate_on_submit():
report = Report()
diff --git a/app/models/__init__.py b/app/models/__init__.py
index 0946ef63..cb4596e4 100644
--- a/app/models/__init__.py
+++ b/app/models/__init__.py
@@ -13,8 +13,7 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-
-
+from flask_babel import LazyString
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy_searchable import make_searchable
@@ -130,6 +129,58 @@ class AuditLogEntry(db.Model):
raise Exception("Permission {} is not related to audit log entries".format(perm.name))
+class ReportCategory(enum.Enum):
+ ACCOUNT_DELETION = "account_deletion"
+ COPYRIGHT = "copyright"
+ USER_CONDUCT = "user_conduct"
+ ILLEGAL_HARMFUL = "illegal_harmful"
+ APPEAL = "appeal"
+ OTHER = "other"
+
+ def __str__(self):
+ return self.name
+
+ @property
+ def title(self) -> LazyString:
+ if self == ReportCategory.ACCOUNT_DELETION:
+ return lazy_gettext("Account deletion")
+ elif self == ReportCategory.COPYRIGHT:
+ return lazy_gettext("Copyright infringement / DMCA")
+ elif self == ReportCategory.USER_CONDUCT:
+ return lazy_gettext("User behaviour, bullying, or abuse")
+ elif self == ReportCategory.ILLEGAL_HARMFUL:
+ return lazy_gettext("Illegal or harmful content")
+ elif self == ReportCategory.APPEAL:
+ return lazy_gettext("Appeal")
+ elif self == ReportCategory.OTHER:
+ return lazy_gettext("Other")
+ else:
+ raise Exception("Unknown report category")
+
+ @classmethod
+ def get(cls, name):
+ try:
+ return ReportCategory[name.upper()]
+ except KeyError:
+ return None
+
+ @classmethod
+ def choices(cls, with_none):
+ ret = [(choice, choice.title) for choice in cls]
+
+ if with_none:
+ ret.insert(0, (None, ""))
+
+ return ret
+
+ @classmethod
+ def coerce(cls, item):
+ if item is None or (isinstance(item, str) and item.upper() == "NONE"):
+ return None
+ return item if type(item) == ReportCategory else ReportCategory[item.upper()]
+
+
+
class Report(db.Model):
id = db.Column(db.String(24), primary_key=True)
@@ -141,6 +192,7 @@ class Report(db.Model):
thread_id = db.Column(db.Integer, db.ForeignKey("thread.id"), nullable=True)
thread = db.relationship("Thread", foreign_keys=[thread_id])
+ category = db.Column(db.Enum(ReportCategory), nullable=False)
url = db.Column(db.String, nullable=True)
title = db.Column(db.Unicode(300), nullable=False)
message = db.Column(db.UnicodeText, nullable=False)
diff --git a/app/templates/report/report.html b/app/templates/report/report.html
index 1e627e0a..5bd2e64a 100644
--- a/app/templates/report/report.html
+++ b/app/templates/report/report.html
@@ -28,6 +28,7 @@