Add scheduled sync, disk space awareness, and subtitle downloads
- auto-sync daemon: background thread checks every hour and syncs followed channels for users with sync_interval_hours set (6/12/24h options) - disk stats: /api/stats now returns total/used/free/download bytes; Stats page shows a disk usage bar - subtitles: subtitle_langs setting (e.g. "en,sv") passed through all download paths; yt-dlp writes .srt files alongside the video - Settings page: sync interval dropdown + subtitle languages input Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -71,6 +71,8 @@ def on_startup():
|
||||
"ALTER TABLE user_settings ADD COLUMN feed_weight_affinity REAL DEFAULT 5.0",
|
||||
"ALTER TABLE user_settings ADD COLUMN feed_weight_channel REAL DEFAULT 5.0",
|
||||
"ALTER TABLE user_settings ADD COLUMN use_oauth2 INTEGER DEFAULT 0",
|
||||
"ALTER TABLE user_settings ADD COLUMN sync_interval_hours INTEGER DEFAULT 0",
|
||||
"ALTER TABLE user_settings ADD COLUMN subtitle_langs TEXT DEFAULT ''",
|
||||
"""CREATE TABLE IF NOT EXISTS search_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
@@ -151,9 +153,47 @@ def on_startup():
|
||||
|
||||
# Backfill descriptions for videos that don't have them yet (runs in background)
|
||||
import threading
|
||||
from .routers.channels import _enrich_missing_task
|
||||
from .routers.channels import _enrich_missing_task, _index_channels_batch
|
||||
threading.Thread(target=_enrich_missing_task, args=(3,), daemon=True).start()
|
||||
|
||||
def _auto_sync_daemon():
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from sqlalchemy import text as _text
|
||||
while True:
|
||||
time.sleep(3600)
|
||||
try:
|
||||
db = SessionLocal()
|
||||
try:
|
||||
users_due = db.execute(
|
||||
_text("SELECT user_id, sync_interval_hours FROM user_settings WHERE sync_interval_hours > 0")
|
||||
).mappings().all()
|
||||
for row in users_due:
|
||||
uid = row["user_id"]
|
||||
cutoff = datetime.utcnow() - timedelta(hours=row["sync_interval_hours"])
|
||||
ch_ids = [
|
||||
r["id"] for r in db.execute(
|
||||
_text("""
|
||||
SELECT c.id FROM channels c
|
||||
JOIN user_channels uc ON c.id = uc.channel_id
|
||||
WHERE uc.user_id = :uid AND uc.status = 'followed'
|
||||
AND (c.crawled_at IS NULL OR c.crawled_at < :cutoff)
|
||||
ORDER BY COALESCE(c.crawled_at, '1970-01-01') ASC
|
||||
"""),
|
||||
{"uid": uid, "cutoff": cutoff},
|
||||
).mappings().all()
|
||||
]
|
||||
if ch_ids:
|
||||
threading.Thread(
|
||||
target=_index_channels_batch, args=(ch_ids, uid), daemon=True
|
||||
).start()
|
||||
finally:
|
||||
db.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
threading.Thread(target=_auto_sync_daemon, daemon=True).start()
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
def health():
|
||||
|
||||
Reference in New Issue
Block a user