mirror of
https://github.com/halfwaystudent/douyin-sparkflow.git
synced 2026-09-07 00:17:20 +08:00
fix: harden scheduling and deployment flow
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, Request
|
||||
@@ -12,8 +14,6 @@ from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from starlette.middleware.sessions import SessionMiddleware
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
from core.friends import fetch_account_friends
|
||||
from core.send_state import history_entry_is_strong_confirmed_today, parse_sent_at
|
||||
from core.tasks import run_browser_tasks, task_run_lock
|
||||
@@ -50,9 +50,12 @@ from webui.ops import (
|
||||
run_task_now,
|
||||
run_unsent_retry_now,
|
||||
task_run_lock_status,
|
||||
sync_daily_schedule_from_config,
|
||||
update_daily_schedule,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
TEMPLATES_DIR = BASE_DIR / "templates"
|
||||
@@ -190,12 +193,17 @@ def mark_target_unconfirmed(account, target_name, *, reason="manual_reset_possib
|
||||
|
||||
def login_desktop_api_url():
|
||||
settings = get_app_settings(force_reload=True)
|
||||
return str(settings.get("login_desktop_api_url") or "http://127.0.0.1:18090").rstrip("/")
|
||||
configured = os.getenv("SPARKFLOW_LOGIN_DESKTOP_API_URL") or settings.get("login_desktop_api_url")
|
||||
return str(configured or "http://127.0.0.1:18090").rstrip("/")
|
||||
|
||||
|
||||
def login_desktop_public_url(request: Request) -> str:
|
||||
settings = get_app_settings(force_reload=True)
|
||||
configured_url = str(settings.get("login_desktop_public_url") or "").strip()
|
||||
configured_url = str(
|
||||
os.getenv("SPARKFLOW_LOGIN_DESKTOP_PUBLIC_URL")
|
||||
or settings.get("login_desktop_public_url")
|
||||
or ""
|
||||
).strip()
|
||||
if configured_url:
|
||||
return configured_url
|
||||
|
||||
@@ -274,13 +282,27 @@ def public_app_settings():
|
||||
|
||||
def create_app():
|
||||
settings = get_app_settings()
|
||||
app = FastAPI(title="DouYin Spark Flow Admin")
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_app):
|
||||
result = sync_daily_schedule_from_config()
|
||||
if result.returncode != 0:
|
||||
logger.warning("Failed to synchronize the configured daily schedule: %s", result.stderr)
|
||||
yield
|
||||
|
||||
secure_cookie = str(os.getenv("SPARKFLOW_SESSION_COOKIE_SECURE") or "").strip().lower() in {
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
}
|
||||
app = FastAPI(title="DouYin Spark Flow Admin", lifespan=lifespan)
|
||||
app.add_middleware(
|
||||
SessionMiddleware,
|
||||
secret_key=settings["session_secret"],
|
||||
max_age=settings["session_max_age_seconds"],
|
||||
same_site="lax",
|
||||
https_only=False,
|
||||
https_only=secure_cookie,
|
||||
)
|
||||
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
|
||||
DEBUG_ARTIFACTS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@ from pathlib import Path
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from core.send_state import history_entry_is_strong_confirmed_today, parse_sent_at
|
||||
from utils.config import get_app_settings, get_config, get_userData, normalize_unique_id, repo_root, save_config
|
||||
from utils.config import get_app_settings, get_config, get_userData, repo_root, save_config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -423,6 +423,8 @@ def refresh_proxy():
|
||||
|
||||
def restart_proxy():
|
||||
try:
|
||||
if running_in_container():
|
||||
return run_command(["docker", "restart", "mihomo"], timeout=120)
|
||||
return run_command(compose_command("restart", "proxy"), timeout=120)
|
||||
except Exception as exc:
|
||||
logger.error("restart_proxy failed: %s", exc)
|
||||
@@ -566,6 +568,43 @@ def update_daily_schedule(time_string):
|
||||
return _empty_result(stderr=str(exc))
|
||||
|
||||
|
||||
def sync_daily_schedule_from_config():
|
||||
config = get_config(force_reload=True)
|
||||
window = dict(config.get("dailySendWindow") or {})
|
||||
if not window.get("enabled"):
|
||||
return subprocess.CompletedProcess(
|
||||
args=["sync-daily-schedule"],
|
||||
returncode=0,
|
||||
stdout="schedule disabled; existing crontab left unchanged",
|
||||
stderr="",
|
||||
)
|
||||
|
||||
try:
|
||||
time_string = _format_window_schedule(window)
|
||||
current = read_crontab()
|
||||
updated = replace_douyin_cron_schedule(current, time_string)
|
||||
if updated == current:
|
||||
return subprocess.CompletedProcess(
|
||||
args=["sync-daily-schedule"], returncode=0, stdout="already synchronized", stderr=""
|
||||
)
|
||||
if running_in_container() and HOST_CRONTAB_PATH.parent.exists():
|
||||
HOST_CRONTAB_PATH.write_text(updated, encoding="utf-8")
|
||||
return subprocess.CompletedProcess(
|
||||
args=["sync-daily-schedule"], returncode=0, stdout="host spool updated", stderr=""
|
||||
)
|
||||
return subprocess.run(
|
||||
["crontab", "-"],
|
||||
input=updated,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
check=False,
|
||||
timeout=10,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.error("sync_daily_schedule_from_config failed: %s", exc)
|
||||
return _empty_result(stderr=str(exc))
|
||||
|
||||
|
||||
def current_daily_schedule():
|
||||
config = get_config(force_reload=True)
|
||||
window = dict(config.get("dailySendWindow") or {})
|
||||
|
||||
Reference in New Issue
Block a user