Add settings and live sidebar counts
This commit is contained in:
parent
2a99edeec3
commit
a809bde16c
16 changed files with 696 additions and 51 deletions
|
|
@ -1,11 +1,13 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import UTC, datetime
|
||||
from enum import IntEnum
|
||||
from importlib import resources
|
||||
from importlib.resources.abc import Traversable
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from peewee import (
|
||||
BooleanField,
|
||||
|
|
@ -29,6 +31,8 @@ DATABASE_PRAGMAS = {
|
|||
"temp_store": "memory",
|
||||
}
|
||||
SCHEMA_GLOB = "*.sql"
|
||||
MAX_CONCURRENT_JOBS_SETTING_KEY = "max_concurrent_jobs"
|
||||
DEFAULT_MAX_CONCURRENT_JOBS = 1
|
||||
|
||||
database = SqliteDatabase(None, pragmas=DATABASE_PRAGMAS)
|
||||
|
||||
|
|
@ -78,17 +82,85 @@ def initialize_database(db_path: str | Path | None = None) -> Path:
|
|||
connection = database.connection()
|
||||
for path in schema_paths():
|
||||
connection.executescript(path.read_text(encoding="utf-8"))
|
||||
_ensure_schema(connection)
|
||||
finally:
|
||||
database.close()
|
||||
|
||||
return resolved_path
|
||||
|
||||
|
||||
def _ensure_schema(connection: Any) -> None:
|
||||
connection.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS app_setting (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
job_columns = {
|
||||
row[1] for row in connection.execute("PRAGMA table_info('job')").fetchall()
|
||||
}
|
||||
if "convert_images" not in job_columns:
|
||||
connection.execute(
|
||||
"""
|
||||
ALTER TABLE job
|
||||
ADD COLUMN convert_images INTEGER NOT NULL DEFAULT 1
|
||||
CHECK (convert_images IN (0, 1))
|
||||
"""
|
||||
)
|
||||
if "convert_video" not in job_columns:
|
||||
connection.execute(
|
||||
"""
|
||||
ALTER TABLE job
|
||||
ADD COLUMN convert_video INTEGER NOT NULL DEFAULT 1
|
||||
CHECK (convert_video IN (0, 1))
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def source_slug_exists(slug: str) -> bool:
|
||||
with database.connection_context():
|
||||
return Source.select().where(Source.slug == slug).exists()
|
||||
|
||||
|
||||
def save_setting(key: str, value: Any) -> None:
|
||||
payload = json.dumps(value, sort_keys=True)
|
||||
with database.connection_context():
|
||||
with database.atomic():
|
||||
setting = AppSetting.get_or_none(AppSetting.key == key)
|
||||
if setting is None:
|
||||
AppSetting.create(key=key, value=payload)
|
||||
return
|
||||
setting.value = payload
|
||||
setting.save()
|
||||
|
||||
|
||||
def load_setting(key: str, default: Any) -> Any:
|
||||
with database.connection_context():
|
||||
setting = AppSetting.get_or_none(AppSetting.key == key)
|
||||
if setting is None:
|
||||
return default
|
||||
try:
|
||||
return json.loads(setting.value)
|
||||
except json.JSONDecodeError:
|
||||
return default
|
||||
|
||||
|
||||
def load_max_concurrent_jobs() -> int:
|
||||
value = load_setting(MAX_CONCURRENT_JOBS_SETTING_KEY, DEFAULT_MAX_CONCURRENT_JOBS)
|
||||
try:
|
||||
parsed = int(value)
|
||||
except (TypeError, ValueError):
|
||||
return DEFAULT_MAX_CONCURRENT_JOBS
|
||||
return parsed if parsed >= 1 else DEFAULT_MAX_CONCURRENT_JOBS
|
||||
|
||||
|
||||
def load_settings_form() -> dict[str, object]:
|
||||
return {"max_concurrent_jobs": load_max_concurrent_jobs()}
|
||||
|
||||
|
||||
def load_source_form(slug: str) -> dict[str, object] | None:
|
||||
with database.connection_context():
|
||||
source = Source.get_or_none(Source.slug == slug)
|
||||
|
|
@ -103,6 +175,8 @@ def load_source_form(slug: str) -> dict[str, object] | None:
|
|||
"notes": source.notes,
|
||||
"spider_arguments": job.spider_arguments,
|
||||
"enabled": job.enabled,
|
||||
"convert_images": job.convert_images,
|
||||
"convert_video": job.convert_video,
|
||||
"cron_minute": job.cron_minute,
|
||||
"cron_hour": job.cron_hour,
|
||||
"cron_day_of_month": job.cron_day_of_month,
|
||||
|
|
@ -155,6 +229,8 @@ def create_source(
|
|||
cron_day_of_month: str,
|
||||
cron_day_of_week: str,
|
||||
cron_month: str,
|
||||
convert_images: bool = True,
|
||||
convert_video: bool = True,
|
||||
feed_url: str = "",
|
||||
pangea_domain: str = "",
|
||||
pangea_category: str = "",
|
||||
|
|
@ -197,6 +273,8 @@ def create_source(
|
|||
Job.create(
|
||||
source=source,
|
||||
enabled=enabled,
|
||||
convert_images=convert_images,
|
||||
convert_video=convert_video,
|
||||
spider_arguments=spider_arguments,
|
||||
cron_minute=cron_minute,
|
||||
cron_hour=cron_hour,
|
||||
|
|
@ -221,6 +299,8 @@ def update_source(
|
|||
cron_day_of_month: str,
|
||||
cron_day_of_week: str,
|
||||
cron_month: str,
|
||||
convert_images: bool = True,
|
||||
convert_video: bool = True,
|
||||
feed_url: str = "",
|
||||
pangea_domain: str = "",
|
||||
pangea_category: str = "",
|
||||
|
|
@ -246,6 +326,8 @@ def update_source(
|
|||
|
||||
job = Job.get(Job.source == source)
|
||||
job.enabled = enabled
|
||||
job.convert_images = convert_images
|
||||
job.convert_video = convert_video
|
||||
job.spider_arguments = spider_arguments
|
||||
job.cron_minute = cron_minute
|
||||
job.cron_hour = cron_hour
|
||||
|
|
@ -375,6 +457,14 @@ class BaseModel(Model):
|
|||
database = database
|
||||
|
||||
|
||||
class AppSetting(BaseModel):
|
||||
key = TextField(primary_key=True)
|
||||
value = TextField()
|
||||
|
||||
class Meta:
|
||||
table_name = "app_setting"
|
||||
|
||||
|
||||
class Source(BaseModel):
|
||||
created_at = DateTimeField(default=utc_now)
|
||||
updated_at = DateTimeField(default=utc_now)
|
||||
|
|
@ -419,6 +509,8 @@ class Job(BaseModel):
|
|||
created_at = DateTimeField(default=utc_now)
|
||||
updated_at = DateTimeField(default=utc_now)
|
||||
enabled = BooleanField()
|
||||
convert_images = BooleanField(default=True)
|
||||
convert_video = BooleanField(default=True)
|
||||
spider_arguments = TextField(default="")
|
||||
cron_minute = TextField()
|
||||
cron_hour = TextField()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue