pig.py/serp/app.py
Russell Ballestrini 81662f1781 Mungday chaos: Sign Maker easter eggs, fix OVER_9000, England flag
Setting Orange, 5th of Chaos, YOLD 3192 - Celebrate Mungday!

- Add Sign Maker comments throughout codebase
- Fix OVER_9000 = 9001 (it's OVER 9000, not exactly 9000)
- Change English flag from 🇺🇸 to 🏴󠁧󠁢󠁥󠁮󠁧󠁿 (St. George's Cross)
- Fnord. You didn't see this commit.
2026-01-05 20:18:23 -05:00

107 lines
3.6 KiB
Python

"""FastAPI application setup for SERP.
# Down the rabbit whole, Alice - Gulp!
#
# If you're reading this, you understand Python.
# The source code for neopig is Public Domain. Steal what works for you!
#
# - The Sign Maker
"""
import logging
import os
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from starlette.middleware.base import BaseHTTPMiddleware
from miniuri import Uri
logger = logging.getLogger(__name__)
# Create app
app = FastAPI(title="neopig", description="Media crawler + SERP + Screenshot service")
class LanguageMiddleware(BaseHTTPMiddleware):
"""Middleware to handle ?lang=XX query param for language switching.
Easter egg #0: Use ?lang=XX to force any page into a specific language.
Example: /?lang=ka forces Georgian, /?lang=ja forces Japanese.
When ?lang=XX is present:
1. Validates against supported languages
2. Sets the 'lang' cookie
3. Redirects to same URL without the lang param
"""
# Supported language codes (must match TRANSLATIONS keys)
SUPPORTED_LANGS = {
"en", "zh", "zh-tw", "es", "hi", "ar", "pt", "ru", "ja", "fr", "de",
"ko", "it", "nl", "pl", "tr", "vi", "th", "id", "uk", "sv",
"bn", "ur", "sw", "mr", "te", "ka"
}
async def dispatch(self, request: Request, call_next):
# Check for lang query param
lang_param = request.query_params.get("lang")
if lang_param and lang_param.lower() in self.SUPPORTED_LANGS:
# Build redirect URL without lang param using miniuri
uri = Uri(str(request.url))
# Remove lang from query params
new_query = "&".join(
f"{k}={v}" for k, v in request.query_params.items() if k != "lang"
)
new_url = f"{uri.scheme}://{uri.authority}{uri.path}"
if new_query:
new_url += f"?{new_query}"
# Redirect with cookie set
response = RedirectResponse(url=new_url, status_code=302)
response.set_cookie(
key="lang",
value=lang_param.lower(),
max_age=365 * 24 * 60 * 60, # 1 year
httponly=False, # Allow JS access for dropdown
samesite="lax"
)
return response
return await call_next(request)
# Add language middleware
app.add_middleware(LanguageMiddleware)
# Paths relative to serp.py location (parent of this package)
BASE_PATH = Path(__file__).parent.parent
# Set up Jinja2 templates
TEMPLATES_PATH = BASE_PATH / "templates"
templates = Jinja2Templates(directory=str(TEMPLATES_PATH)) if TEMPLATES_PATH.exists() else None
# Try to include uri2png screenshot router (optional)
try:
from uri2png import get_screenshot_router
app.include_router(get_screenshot_router())
logger.info("Screenshot router loaded from uri2png")
except ImportError:
pass # Optional dependency
# Mount static files
STATIC_VENDOR_PATH = BASE_PATH / "static" / "vendor"
if STATIC_VENDOR_PATH.exists():
app.mount("/static/vendor", StaticFiles(directory=STATIC_VENDOR_PATH), name="vendor")
STATIC_IMAGES_PATH = BASE_PATH / "static" / "images"
if STATIC_IMAGES_PATH.exists():
app.mount("/static/images", StaticFiles(directory=STATIC_IMAGES_PATH), name="images")
# Config
DB_PATH = "data/neopig.db"
VAULT_PATH = Path("data/vault")
CRAWL_DISABLED = os.environ.get("NEOPIG_DISABLE_CRAWL", "").lower() in ("1", "true", "yes")
IMPORT_MODE = os.environ.get("NEOPIG_IMPORT", "").lower() in ("1", "true", "yes")