Schedules automod task

This commit is contained in:
Mouse Reeve 2022-02-26 10:13:44 -08:00
parent 95e9119817
commit 2a436800c4
8 changed files with 105 additions and 14 deletions

View file

@ -8,6 +8,7 @@ from django.forms import ModelForm, PasswordInput, widgets, ChoiceField
from django.forms.widgets import Textarea from django.forms.widgets import Textarea
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_celery_beat.models import IntervalSchedule
from bookwyrm import models from bookwyrm import models
from bookwyrm.models.fields import ClearableFileInputWithWarning from bookwyrm.models.fields import ClearableFileInputWithWarning
@ -556,3 +557,9 @@ class AutoModRuleForm(CustomForm):
class Meta: class Meta:
model = models.AutoMod model = models.AutoMod
fields = ["string_match", "flag_users", "flag_statuses", "created_by"] fields = ["string_match", "flag_users", "flag_statuses", "created_by"]
class IntervalScheduleForm(CustomForm):
class Meta:
model = IntervalSchedule
fields = ["every", "period"]

View file

@ -54,6 +54,7 @@ class AutoMod(models.Model):
@app.task(queue="low_priority") @app.task(queue="low_priority")
def automod_task(): def automod_task():
"""Create reports""" """Create reports"""
print("TASK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
if not AutoMod.objects.exists(): if not AutoMod.objects.exists():
return return
reporter = AutoMod.objects.first().created_by reporter = AutoMod.objects.first().created_by

View file

@ -90,7 +90,7 @@ INSTALLED_APPS = [
"sass_processor", "sass_processor",
"bookwyrm", "bookwyrm",
"celery", "celery",
'django_celery_beat', "django_celery_beat",
"imagekit", "imagekit",
"storages", "storages",
] ]

View file

@ -1,5 +1,6 @@
{% extends 'settings/layout.html' %} {% extends 'settings/layout.html' %}
{% load i18n %} {% load i18n %}
{% load humanize %}
{% load utilities %} {% load utilities %}
{% block title %} {% block title %}
@ -16,12 +17,46 @@
<p> <p>
{% trans "Auto-moderation rules will create reports for any local user or status with fields matching the provided string." %} {% trans "Auto-moderation rules will create reports for any local user or status with fields matching the provided string." %}
{% trans "Users or statuses that have already been reported (regardless of whether the report was resolved) will not be flagged." %} {% trans "Users or statuses that have already been reported (regardless of whether the report was resolved) will not be flagged." %}
{% trans "At this time, reports are <em>not</em> being generated automatically, and you must manually trigger a scan." %}
</p> </p>
<form name="run-scan" method="POST" action="{% url 'settings-automod-run' %}"> {% if task %}
<dl>
<dt class="is-pulled-left mr-5 has-text-weight-bold">
{% trans "Schedule:" %}
</dt>
<dd>
{{ task.schedule }}
</dd>
<dt class="is-pulled-left mr-5 has-text-weight-bold">
{% trans "Last run:" %}
</dt>
<dd>
{{ task.last_run_at|naturaltime }}
</dd>
<dt class="is-pulled-left mr-5 has-text-weight-bold">
{% trans "Total run count:" %}
</dt>
<dd>
{{ task.total_run_count }}
</dd>
<dt class="is-pulled-left mr-5 has-text-weight-bold">
{% trans "Enabled:" %}
</dt>
<dd>
<span class="tag {% if task.enabled %}is-success{% else %}is-danger{% endif %}">
{{ task.enabled|yesno }}
</span>
</dd>
</dl>
{% else %}
<form name="schedule-scan" method="POST" action="{% url 'settings-automod-schedule' %}">
{% csrf_token %} {% csrf_token %}
<button class="button is-warning">{% trans "Run scan" %}</button> {{ task_form.as_p }}
<button class="button is-warning">{% trans "Schedule scan" %}</button>
</form> </form>
{% endif %}
</div> </div>
{% if success %} {% if success %}

View file

@ -217,11 +217,18 @@ urlpatterns = [
# auto-moderation rules # auto-moderation rules
re_path(r"^settings/automod/?$", views.AutoMod.as_view(), name="settings-automod"), re_path(r"^settings/automod/?$", views.AutoMod.as_view(), name="settings-automod"),
re_path( re_path(
r"^settings/automod/(?P<rule_id>\d+)/delete?$", r"^settings/automod/(?P<rule_id>\d+)/delete/?$",
views.automod_delete, views.automod_delete,
name="settings-automod-delete", name="settings-automod-delete",
), ),
re_path(r"^settings/automod/run?$", views.run_automod, name="settings-automod-run"), re_path(
r"^settings/automod/schedule/?$",
views.schedule_automod_task,
name="settings-automod-schedule",
),
re_path(
r"^settings/automod/run/?$", views.run_automod, name="settings-automod-run"
),
# moderation # moderation
re_path( re_path(
r"^settings/reports/?$", views.ReportsAdmin.as_view(), name="settings-reports" r"^settings/reports/?$", views.ReportsAdmin.as_view(), name="settings-reports"

View file

@ -2,7 +2,7 @@
# site admin # site admin
from .admin.announcements import Announcements, Announcement from .admin.announcements import Announcements, Announcement
from .admin.announcements import EditAnnouncement, delete_announcement from .admin.announcements import EditAnnouncement, delete_announcement
from .admin.automod import AutoMod, automod_delete, run_automod from .admin.automod import AutoMod, automod_delete, run_automod, schedule_automod_task
from .admin.dashboard import Dashboard from .admin.dashboard import Dashboard
from .admin.federation import Federation, FederatedServer from .admin.federation import Federation, FederatedServer
from .admin.federation import AddFederatedServer, ImportServerBlocklist from .admin.federation import AddFederatedServer, ImportServerBlocklist

View file

@ -1,10 +1,12 @@
""" moderation via flagged posts and users """ """ moderation via flagged posts and users """
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.db import transaction
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views import View from django.views import View
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from django_celery_beat.models import PeriodicTask
from bookwyrm import forms, models from bookwyrm import forms, models
@ -24,8 +26,9 @@ class AutoMod(View):
def get(self, request): def get(self, request):
"""view rules""" """view rules"""
data = {"rules": models.AutoMod.objects.all(), "form": forms.AutoModRuleForm()} return TemplateResponse(
return TemplateResponse(request, "settings/automod/rules.html", data) request, "settings/automod/rules.html", automod_view_data()
)
def post(self, request): def post(self, request):
"""add rule""" """add rule"""
@ -35,14 +38,32 @@ class AutoMod(View):
form.save() form.save()
form = forms.AutoModRuleForm() form = forms.AutoModRuleForm()
data = { data = automod_view_data()
"rules": models.AutoMod.objects.all(), data["form"] = form
"form": form,
"success": success,
}
return TemplateResponse(request, "settings/automod/rules.html", data) return TemplateResponse(request, "settings/automod/rules.html", data)
@require_POST
@permission_required("bookwyrm.moderate_user", raise_exception=True)
@permission_required("bookwyrm.moderate_post", raise_exception=True)
def schedule_automod_task(request):
"""scheduler"""
form = forms.IntervalScheduleForm(request.POST)
if not form.is_valid():
data = automod_view_data()
data["task_form"] = form
return TemplateResponse(request, "settings/automod/rules.html", data)
with transaction.atomic():
schedule = form.save()
PeriodicTask.objects.get_or_create(
interval=schedule,
name="automod-task",
task="bookwyrm.models.antispam.automod_task",
)
return redirect("settings-automod")
@require_POST @require_POST
@permission_required("bookwyrm.moderate_user", raise_exception=True) @permission_required("bookwyrm.moderate_user", raise_exception=True)
@permission_required("bookwyrm.moderate_post", raise_exception=True) @permission_required("bookwyrm.moderate_post", raise_exception=True)
@ -62,3 +83,18 @@ def run_automod(request):
"""run scan""" """run scan"""
models.automod_task.delay() models.automod_task.delay()
return redirect("settings-automod") return redirect("settings-automod")
def automod_view_data():
"""helper to get data used in the template"""
try:
task = PeriodicTask.objects.get(name="automod-task")
except PeriodicTask.DoesNotExist:
task = None
return {
"task": task,
"task_form": forms.IntervalScheduleForm(),
"rules": models.AutoMod.objects.all(),
"form": forms.AutoModRuleForm(),
}

View file

@ -3,6 +3,7 @@
# pylint: disable=unused-wildcard-import # pylint: disable=unused-wildcard-import
from bookwyrm.settings import * from bookwyrm.settings import *
# pylint: disable=line-too-long
REDIS_BROKER_PASSWORD = requests.utils.quote(env("REDIS_BROKER_PASSWORD", None)) REDIS_BROKER_PASSWORD = requests.utils.quote(env("REDIS_BROKER_PASSWORD", None))
REDIS_BROKER_HOST = env("REDIS_BROKER_HOST", "redis_broker") REDIS_BROKER_HOST = env("REDIS_BROKER_HOST", "redis_broker")
REDIS_BROKER_PORT = env("REDIS_BROKER_PORT", 6379) REDIS_BROKER_PORT = env("REDIS_BROKER_PORT", 6379)
@ -16,6 +17,10 @@ CELERY_DEFAULT_QUEUE = "low_priority"
CELERY_ACCEPT_CONTENT = ["json"] CELERY_ACCEPT_CONTENT = ["json"]
CELERY_TASK_SERIALIZER = "json" CELERY_TASK_SERIALIZER = "json"
CELERY_RESULT_SERIALIZER = "json" CELERY_RESULT_SERIALIZER = "json"
CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler"
CELERY_TIMEZONE = env("TIME_ZONE", "UTC")
FLOWER_PORT = env("FLOWER_PORT") FLOWER_PORT = env("FLOWER_PORT")
INSTALLED_APPS = INSTALLED_APPS + [ INSTALLED_APPS = INSTALLED_APPS + [