Add project branding and poster footers
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user