# This is free software for the public good of a permacomputer hosted at # permacomputer.com, an always-on computer by the people, for the people. # One which is durable, easy to repair, & distributed like tap water # for machine learning intelligence. # # The permacomputer is community-owned infrastructure optimized around # four values: # # TRUTH First principles, math & science, open source code freely distributed # FREEDOM Voluntary partnerships, freedom from tyranny & corporate control # HARMONY Minimal waste, self-renewing systems with diverse thriving connections # LOVE Be yourself without hurting others, cooperation through natural law # # This software contributes to that vision by archiving the web, preserving digital knowledge before it disappears. # Code is seeds to sprout on any abandoned technology. """FastAPI application setup for SERP. # Side quest 4/21: The rabbit hole goes deeper than you think. # 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, Cookie, Header from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from .i18n import TRANSLATIONS logger = logging.getLogger(__name__) # Create app app = FastAPI(title="neopig", description="Media crawler + SERP + Screenshot service") # Supported language codes SUPPORTED_LANGS = set(TRANSLATIONS.keys()) async def get_language( request: Request, lang: str = Cookie(None), accept_language: str = Header(None) ) -> str: """Dependency: resolve language from ?lang=XX > cookie > Accept-Language. Easter egg #0: Use ?lang=XX to force any page into a specific language. Cookie is set via middleware (LanguageCookieMiddleware). """ # Query param takes priority lang_query = request.query_params.get("lang") if lang_query and lang_query.lower() in SUPPORTED_LANGS: return lang_query.lower() # Cookie next if lang and lang in SUPPORTED_LANGS: return lang # Accept-Language header if accept_language: for part in accept_language.split(','): code = part.split(';')[0].strip().split('-')[0].lower() if code in SUPPORTED_LANGS: return code return "en" from starlette.middleware.base import BaseHTTPMiddleware class LanguageCookieMiddleware(BaseHTTPMiddleware): """Middleware to set lang cookie when ?lang=XX is used.""" async def dispatch(self, request: Request, call_next): response = await call_next(request) # Set cookie if ?lang= query param is present and valid lang_query = request.query_params.get("lang") if lang_query and lang_query.lower() in SUPPORTED_LANGS: response.set_cookie( key="lang", value=lang_query.lower(), max_age=365 * 24 * 60 * 60, httponly=False, samesite="lax" ) return response app.add_middleware(LanguageCookieMiddleware) # 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_CSS_PATH = BASE_PATH / "static" / "css" if STATIC_CSS_PATH.exists(): app.mount("/static/css", StaticFiles(directory=STATIC_CSS_PATH), name="css") 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")