diff --git a/VERSION b/VERSION
index 39e898a4f9..ee6cdce3c2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.7.1
+0.6.1
diff --git a/bookwyrm/management/commands/instance_version.py b/bookwyrm/management/commands/instance_version.py
deleted file mode 100644
index ca150d6409..0000000000
--- a/bookwyrm/management/commands/instance_version.py
+++ /dev/null
@@ -1,54 +0,0 @@
-""" Get your admin code to allow install """
-from django.core.management.base import BaseCommand
-
-from bookwyrm import models
-from bookwyrm.settings import VERSION
-
-
-# pylint: disable=no-self-use
-class Command(BaseCommand):
- """command-line options"""
-
- help = "What version is this?"
-
- def add_arguments(self, parser):
- """specify which function to run"""
- parser.add_argument(
- "--current",
- action="store_true",
- help="Version stored in database",
- )
- parser.add_argument(
- "--target",
- action="store_true",
- help="Version stored in settings",
- )
- parser.add_argument(
- "--update",
- action="store_true",
- help="Update database version",
- )
-
- # pylint: disable=unused-argument
- def handle(self, *args, **options):
- """execute init"""
- site = models.SiteSettings.objects.get()
- current = site.version or "0.0.1"
- target = VERSION
- if options.get("current"):
- print(current)
- return
-
- if options.get("target"):
- print(target)
- return
-
- if options.get("update"):
- site.version = target
- site.save()
- return
-
- if current != target:
- print(f"{current}/{target}")
- else:
- print(current)
diff --git a/bookwyrm/migrations/0192_rename_version_sitesettings_available_version.py b/bookwyrm/migrations/0192_rename_version_sitesettings_available_version.py
new file mode 100644
index 0000000000..db67b4e925
--- /dev/null
+++ b/bookwyrm/migrations/0192_rename_version_sitesettings_available_version.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.23 on 2024-01-02 19:36
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("bookwyrm", "0191_merge_20240102_0326"),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name="sitesettings",
+ old_name="version",
+ new_name="available_version",
+ ),
+ ]
diff --git a/bookwyrm/migrations/0194_merge_20240203_1619.py b/bookwyrm/migrations/0194_merge_20240203_1619.py
new file mode 100644
index 0000000000..a5c18e3006
--- /dev/null
+++ b/bookwyrm/migrations/0194_merge_20240203_1619.py
@@ -0,0 +1,13 @@
+# Generated by Django 3.2.23 on 2024-02-03 16:19
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("bookwyrm", "0192_rename_version_sitesettings_available_version"),
+ ("bookwyrm", "0193_merge_20240203_1539"),
+ ]
+
+ operations = []
diff --git a/bookwyrm/models/site.py b/bookwyrm/models/site.py
index 8075b64345..201a499e55 100644
--- a/bookwyrm/models/site.py
+++ b/bookwyrm/models/site.py
@@ -10,8 +10,11 @@
from django.utils import timezone
from model_utils import FieldTracker
+from bookwyrm.connectors.abstract_connector import get_data
from bookwyrm.preview_images import generate_site_preview_image_task
from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES, STATIC_FULL_URL
+from bookwyrm.settings import RELEASE_API
+from bookwyrm.tasks import app, MISC
from .base_model import BookWyrmModel, new_access_code
from .user import User
from .fields import get_absolute_url
@@ -45,7 +48,7 @@ class SiteSettings(SiteModel):
default_theme = models.ForeignKey(
"Theme", null=True, blank=True, on_delete=models.SET_NULL
)
- version = models.CharField(null=True, blank=True, max_length=10)
+ available_version = models.CharField(null=True, blank=True, max_length=10)
# admin setup options
install_mode = models.BooleanField(default=False)
@@ -245,3 +248,14 @@ def preview_image(instance, *args, **kwargs):
if len(changed_fields) > 0:
generate_site_preview_image_task.delay()
+
+
+@app.task(queue=MISC)
+def check_for_updates_task():
+ """See if git remote knows about a new version"""
+ site = SiteSettings.objects.get()
+ release = get_data(RELEASE_API, timeout=3)
+ available_version = release.get("tag_name", None)
+ if available_version:
+ site.available_version = available_version
+ site.save(update_fields=["available_version"])
diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html
index 4c109c7e17..d43b3bade0 100644
--- a/bookwyrm/templates/settings/dashboard/dashboard.html
+++ b/bookwyrm/templates/settings/dashboard/dashboard.html
@@ -45,6 +45,10 @@
{% trans "Works" %}
{% include 'settings/dashboard/warnings/update_version.html' with warning_level="warning" fullwidth=True %}
{% endif %}
+ {% if schedule_form %}
+ {% include 'settings/dashboard/warnings/check_for_updates.html' with warning_level="success" fullwidth=True %}
+ {% endif %}
+
{% if missing_privacy or missing_conduct %}
{% if missing_privacy %}
diff --git a/bookwyrm/templates/settings/dashboard/warnings/check_for_updates.html b/bookwyrm/templates/settings/dashboard/warnings/check_for_updates.html
new file mode 100644
index 0000000000..00f3208244
--- /dev/null
+++ b/bookwyrm/templates/settings/dashboard/warnings/check_for_updates.html
@@ -0,0 +1,24 @@
+{% extends 'settings/dashboard/warnings/layout.html' %}
+{% load i18n %}
+
+{% block warning_link %}#{% endblock %}
+
+{% block warning_text %}
+
+
+
+{% endblock %}
+
diff --git a/bookwyrm/templates/settings/layout.html b/bookwyrm/templates/settings/layout.html
index dcaaaeb38a..70c7ef0f47 100644
--- a/bookwyrm/templates/settings/layout.html
+++ b/bookwyrm/templates/settings/layout.html
@@ -85,6 +85,10 @@
{% url 'settings-celery' as url %}
{% trans "Celery status" %}
+
+ {% url 'settings-schedules' as url %}
+ {% trans "Scheduled tasks" %}
+
{% url 'settings-email-config' as url %}
{% trans "Email Configuration" %}
diff --git a/bookwyrm/templates/settings/schedules.html b/bookwyrm/templates/settings/schedules.html
new file mode 100644
index 0000000000..20ced4b30a
--- /dev/null
+++ b/bookwyrm/templates/settings/schedules.html
@@ -0,0 +1,127 @@
+{% extends 'settings/layout.html' %}
+{% load i18n %}
+{% load humanize %}
+{% load utilities %}
+
+{% block title %}
+{% trans "Scheduled tasks" %}
+{% endblock %}
+
+{% block header %}
+{% trans "Scheduled tasks" %}
+{% endblock %}
+
+{% block panel %}
+
+
+
{% trans "Tasks" %}
+
+
+
+
+ {% trans "Name" %}
+ |
+
+ {% trans "Celery task" %}
+ |
+
+ {% trans "Date changed" %}
+ |
+
+ {% trans "Last run at" %}
+ |
+
+ {% trans "Schedule" %}
+ |
+
+ {% trans "Schedule ID" %}
+ |
+
+ {% trans "Enabled" %}
+ |
+
+ {% for task in tasks %}
+
+
+ {{ task.name }}
+ |
+
+ {{ task.task }}
+ |
+
+ {{ task.date_changed }}
+ |
+
+ {{ task.last_run_at }}
+ |
+
+ {% firstof task.interval task.crontab "None" %}
+ |
+
+ {{ task.interval.id }}
+ |
+
+
+ {% if task.enabled %}
+
+ {% endif %}
+ {{ task.enabled|yesno }}
+
+ {% if task.name != "celery.backend_cleanup" %}
+
+ {% endif %}
+ |
+
+ {% empty %}
+
+
+ {% trans "No scheduled tasks" %}
+ |
+
+ {% endfor %}
+
+
+
+
+
+
{% trans "Schedules" %}
+
+
+
+
+ {% trans "ID" %}
+ |
+
+ {% trans "Schedule" %}
+ |
+
+ {% trans "Tasks" %}
+ |
+
+ {% for schedule in schedules %}
+
+
+ {{ schedule.id }}
+ |
+
+ {{ schedule }}
+ |
+
+ {{ schedule.periodictask_set.count }}
+ |
+
+ {% empty %}
+
+
+ {% trans "No schedules found" %}
+ |
+
+ {% endfor %}
+
+
+
+
+{% endblock %}
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py
index 1a577c84bc..bfa1aacce0 100644
--- a/bookwyrm/urls.py
+++ b/bookwyrm/urls.py
@@ -369,6 +369,11 @@
re_path(
r"^settings/celery/ping/?$", views.celery_ping, name="settings-celery-ping"
),
+ re_path(
+ r"^settings/schedules/(?P\d+)?$",
+ views.ScheduledTasks.as_view(),
+ name="settings-schedules",
+ ),
re_path(
r"^settings/email-config/?$",
views.EmailConfig.as_view(),
diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py
index f11c11dd68..ebc851847a 100644
--- a/bookwyrm/views/__init__.py
+++ b/bookwyrm/views/__init__.py
@@ -5,6 +5,7 @@
from .admin.automod import AutoMod, automod_delete, run_automod
from .admin.automod import schedule_automod_task, unschedule_automod_task
from .admin.celery_status import CeleryStatus, celery_ping
+from .admin.schedule import ScheduledTasks
from .admin.dashboard import Dashboard
from .admin.federation import Federation, FederatedServer
from .admin.federation import AddFederatedServer, ImportServerBlocklist
diff --git a/bookwyrm/views/admin/automod.py b/bookwyrm/views/admin/automod.py
index 9a32dd9eec..58818ad9bf 100644
--- a/bookwyrm/views/admin/automod.py
+++ b/bookwyrm/views/admin/automod.py
@@ -6,7 +6,7 @@
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.http import require_POST
-from django_celery_beat.models import PeriodicTask
+from django_celery_beat.models import PeriodicTask, IntervalSchedule
from bookwyrm import forms, models
@@ -54,7 +54,7 @@ def schedule_automod_task(request):
return TemplateResponse(request, "settings/automod/rules.html", data)
with transaction.atomic():
- schedule = form.save(request)
+ schedule, _ = IntervalSchedule.objects.get_or_create(**form.cleaned_data)
PeriodicTask.objects.get_or_create(
interval=schedule,
name="automod-task",
diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py
index 9d256fc6c2..21b19bf166 100644
--- a/bookwyrm/views/admin/dashboard.py
+++ b/bookwyrm/views/admin/dashboard.py
@@ -6,16 +6,18 @@
from packaging import version
from django.contrib.auth.decorators import login_required, permission_required
+from django.db import transaction
from django.db.models import Q
+from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views import View
+from django_celery_beat.models import PeriodicTask, IntervalSchedule
from csp.decorators import csp_update
-from bookwyrm import models, settings
-from bookwyrm.connectors.abstract_connector import get_data
+from bookwyrm import forms, models, settings
from bookwyrm.utils import regex
@@ -59,21 +61,36 @@ def get(self, request):
== site._meta.get_field("privacy_policy").get_default()
)
- # check version
+ if site.available_version and version.parse(
+ site.available_version
+ ) > version.parse(settings.VERSION):
+ data["current_version"] = settings.VERSION
+ data["available_version"] = site.available_version
- try:
- release = get_data(settings.RELEASE_API, timeout=3)
- available_version = release.get("tag_name", None)
- if available_version and version.parse(available_version) > version.parse(
- settings.VERSION
- ):
- data["current_version"] = settings.VERSION
- data["available_version"] = available_version
- except: # pylint: disable= bare-except
- pass
+ if not PeriodicTask.objects.filter(name="check-for-updates").exists():
+ data["schedule_form"] = forms.IntervalScheduleForm(
+ {"every": 1, "period": "days"}
+ )
return TemplateResponse(request, "settings/dashboard/dashboard.html", data)
+ def post(self, request):
+ """Create a schedule task to check for updates"""
+ schedule_form = forms.IntervalScheduleForm(request.POST)
+ if not schedule_form.is_valid():
+ raise schedule_form.ValidationError(schedule_form.errors)
+
+ with transaction.atomic():
+ schedule, _ = IntervalSchedule.objects.get_or_create(
+ **schedule_form.cleaned_data
+ )
+ PeriodicTask.objects.get_or_create(
+ interval=schedule,
+ name="check-for-updates",
+ task="bookwyrm.models.site.check_for_updates_task",
+ )
+ return redirect("settings-dashboard")
+
def get_charts_and_stats(request):
"""Defines the dashboard charts"""
diff --git a/bookwyrm/views/admin/schedule.py b/bookwyrm/views/admin/schedule.py
new file mode 100644
index 0000000000..c654dca9aa
--- /dev/null
+++ b/bookwyrm/views/admin/schedule.py
@@ -0,0 +1,31 @@
+""" Scheduled celery tasks """
+from django.contrib.auth.decorators import login_required, permission_required
+from django.shortcuts import redirect
+from django.template.response import TemplateResponse
+from django.utils.decorators import method_decorator
+from django.views import View
+from django_celery_beat.models import PeriodicTask, IntervalSchedule
+
+
+@method_decorator(login_required, name="dispatch")
+@method_decorator(
+ permission_required("bookwyrm.edit_instance_settings", raise_exception=True),
+ name="dispatch",
+)
+# pylint: disable=no-self-use
+class ScheduledTasks(View):
+ """Manage automated flagging"""
+
+ def get(self, request):
+ """view schedules"""
+ data = {}
+ data["tasks"] = PeriodicTask.objects.all()
+ data["schedules"] = IntervalSchedule.objects.all()
+ return TemplateResponse(request, "settings/schedules.html", data)
+
+ # pylint: disable=unused-argument
+ def post(self, request, task_id):
+ """un-schedule a task"""
+ task = PeriodicTask.objects.get(id=task_id)
+ task.delete()
+ return redirect("settings-schedules")
diff --git a/update.sh b/update.sh
deleted file mode 100755
index 727ce1b24f..0000000000
--- a/update.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-# determine inital and target versions
-initial_version="`./bw-dev runweb python manage.py instance_version --current`"
-target_version="`./bw-dev runweb python manage.py instance_version --target`"
-
-initial_version="`echo $initial_version | tail -n 1 | xargs`"
-target_version="`echo $target_version | tail -n 1 | xargs`"
-if [[ "$initial_version" = "$target_version" ]]; then
- echo "Already up to date; version $initial_version"
- exit
-fi
-
-echo "---------------------------------------"
-echo "Updating from version: $initial_version"
-echo ".......... to version: $target_version"
-echo "---------------------------------------"
-
-function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
-
-# execute scripts between initial and target
-for version in `ls -A updates/ | sort -V `; do
- if version_gt $initial_version $version; then
- # too early
- continue
- fi
- if version_gt $version $target_version; then
- # too late
- continue
- fi
- echo "Running tasks for version $version"
- ./updates/$version
-done
-
-./bw-dev runweb python manage.py instance_version --update
-echo "✨ ----------- Done! --------------- ✨"