Add project branding and poster footers

This commit is contained in:
Your Name
2026-08-04 17:06:48 +05:00
parent ad66f2ed73
commit a8db1b379e
10 changed files with 134 additions and 15 deletions
+42 -3
View File
@@ -43,17 +43,34 @@ VK_OAUTH_VERIFIER_COOKIE = "vk_oauth_verifier"
VK_OAUTH_STATE_COOKIE = "vk_oauth_state"
BASE_DIR = Path(__file__).resolve().parent
PROJECT_ROOT = BASE_DIR.parents[1]
FAVICON_PATH = Path(settings.admin_favicon_path).resolve() if settings.admin_favicon_path.strip() else PROJECT_ROOT / "favi.png"
templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
app = FastAPI(title=settings.display_site_title)
LOCAL_TZ = ZoneInfo("Asia/Yekaterinburg")
MODEL_CACHE: dict[str, Any] = {"key": "", "at": 0.0, "models": []}
UPLOAD_ROOT = Path("uploads").resolve()
BRANDING_DIR = UPLOAD_ROOT / "branding"
EDITOR_MEDIA_DIR = UPLOAD_ROOT / "editor_media"
BRANDING_DIR.mkdir(parents=True, exist_ok=True)
EDITOR_MEDIA_DIR.mkdir(parents=True, exist_ok=True)
app.mount("/uploads", StaticFiles(directory=str(UPLOAD_ROOT)), name="uploads")
def favicon_path() -> Path:
uploaded = BRANDING_DIR / "favicon.png"
if uploaded.is_file():
return uploaded
if settings.admin_favicon_path.strip():
return Path(settings.admin_favicon_path).resolve()
return PROJECT_ROOT / "favi.png"
def favicon_version() -> int:
try:
return int(favicon_path().stat().st_mtime)
except OSError:
return 0
def public_origin(request: Request) -> str:
configured = settings.vk_oauth_origin.strip().rstrip("/")
if configured:
@@ -72,12 +89,12 @@ def oauth_redirect_uri(request: Request, path: str) -> str:
@app.get("/favi.png")
async def favicon_png():
return FileResponse(FAVICON_PATH)
return FileResponse(favicon_path())
@app.get("/favicon.ico")
async def favicon_ico():
return FileResponse(FAVICON_PATH, media_type="image/png")
return FileResponse(favicon_path(), media_type="image/png")
PROVIDER_OPTIONS = [
{"value": "openrouter", "label": "OpenRouter"},
@@ -176,6 +193,7 @@ CATEGORY_TITLES = {
"TG Reactor": "TG-реактор",
"VK Poster": "VK-постер",
"MAX Poster": "MAX-постер",
"Publishing": "Публикации",
"Daily Report": "Ежедневный отчет",
"Parser": "Парсер",
"Uploader": "Аплоадер",
@@ -191,6 +209,7 @@ CATEGORY_ORDER = {
"VK Poster": 50,
"MAX Poster": 51,
"Site Poster": 52,
"Publishing": 53,
"Daily Report": 55,
"Parser": 60,
"VK": 70,
@@ -252,6 +271,7 @@ SETTING_ORDER = {
"tg_poster_recent_window",
"tg_poster_category_repeat_penalty",
"tg_poster_source_repeat_penalty",
"tg_poster_footer_text",
],
"TG Reactor": [
"tg_reactor_bot_tokens",
@@ -282,6 +302,10 @@ SETTING_ORDER = {
"vk_poster_category_repeat_penalty",
"vk_poster_source_repeat_penalty",
"vk_poster_dry_run",
"vk_poster_footer_text",
],
"Publishing": [
"publication_common_tags",
],
"MAX Poster": [
"max_poster_bot_token",
@@ -475,6 +499,7 @@ def base_context(request: Request, user: dict | None, **extra: Any) -> dict[str,
"app_env": settings.app_env,
"app_title": settings.display_admin_title,
"site_title": settings.display_site_title,
"favicon_version": favicon_version(),
"site_poster_provider_options": SITE_POSTER_PROVIDER_OPTIONS,
}
ctx.update(extra)
@@ -3888,6 +3913,20 @@ async def settings_save(request: Request, csrf_token: str = Form(...), key: str
return redirect("/workers")
@app.post("/branding/favicon")
async def branding_favicon_save(request: Request, csrf_token: str = Form(...), favicon_file: UploadFile = File(...)):
user = await get_current_user(request)
if not user:
return redirect("/login")
require_csrf(user, csrf_token)
content = await favicon_file.read()
if not content.startswith(b"\x89PNG\r\n\x1a\n") or len(content) > 1024 * 1024:
return redirect("/workers")
(BRANDING_DIR / "favicon.png").write_bytes(content)
await audit(user["id"], "branding.favicon_update", "branding", None, {"filename": favicon_file.filename})
return redirect("/workers")
@app.get("/logs", response_class=HTMLResponse)
async def logs_page(
request: Request,