api/app/main.py
2026-03-31 14:21:55 +02:00

119 lines
3.6 KiB
Python

import os
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
from scalar_fastapi import get_scalar_api_reference
from app.routes import discovery, reviews, stats
ROOT_PATH = os.environ.get("ROOT_PATH", "")
DESCRIPTION = """
Hi, this is a read-only API exposing 20+ years of my personal media reviews of movies, books,
and television since 2001.
## What this API does
This API provides structured access to a personal media review database. Every
review includes a date, category, title, creator, genre, rating, and optional
written commentary.
## Rating scale
Ratings use a **-3.0 to 3.0** scale:
| Rating | Meaning |
|--------|---------|
| 3.0 | Masterpiece, tears flowed |
| 2.0 | Great, I was glowing for a day |
| 1.0 | Good enough use of my time |
| 0.0 | Meh, a void of space |
| -1.0 | Below average, should have spent this time knitting |
| -2.0 | Bad, I want someone to pay me for this |
| -3.0 | Terrible, I felt like I needed to use toilet paper after |
## Getting started
- Browse available categories, genres, and creators via the **Discovery**
endpoints
- Fetch reviews with filtering and pagination via **GET /reviews**
- Explore aggregate statistics via the **Statistics** endpoints
- Get a surprise recommendation via **GET /reviews/random**
## About
This API is a portfolio project demonstrating API design and documentation
skills. Built with [FastAPI](https://fastapi.tiangolo.com/) and documented
with [Scalar](https://scalar.com/).
"""
CUSTOM_CSS = """
.darklight-reference-promo { display: none !important; }
.darklight-reference { display: none !important; }
.light-mode {
--scalar-color-1: #343434;
--scalar-color-2: #666666;
--scalar-color-3: #979797;
--scalar-color-accent: #C9C9C9;
--scalar-background-1: #FAFAFA;
--scalar-background-2: #FFFFFF;
--scalar-background-3: #FFFFFF;
--scalar-background-accent: #FFFFFF;
--scalar-border-color: transparent;
}
@font-face {
font-display: swap;
font-family: 'DM Sans';
font-style: normal;
font-weight: 100 700;
src: url('https://gugulet.hu/technical/git/g_it/site/raw/branch/main/content/assets/fonts/dm-sans.ttf') format('truetype');
}
@font-face {
font-display: swap;
font-family: 'DM Mono';
font-style: normal;
font-weight: 100 700;
src: url('https://gugulet.hu/technical/git/g_it/site/raw/branch/main/content/assets/fonts/dm-mono.ttf') format('truetype');
}
:root {
--scalar-font: 'DM Sans', sans-serif;
--scalar-font-code: 'DM Mono', monospace;
}
"""
app = FastAPI(
title="Reviews API",
description=DESCRIPTION,
version="1.0.0",
docs_url=None,
redoc_url=None,
)
@app.get("/ref", include_in_schema=False)
async def scalar_docs():
return get_scalar_api_reference(
openapi_url=f"{ROOT_PATH}/openapi.json",
title=app.title,
force_dark_mode_state="light",
hide_dark_mode_toggle=True,
with_default_fonts=False,
scalar_favicon_url="https://gugulet.hu/technical/git/g_it/site/raw/branch/main/content/assets/media/face-favicon-512x512.png",
default_open_all_tags=False,
custom_css=CUSTOM_CSS,
)
app.include_router(reviews.router)
app.include_router(discovery.router)
app.include_router(stats.router)
@app.get("/", include_in_schema=False)
def root_redirect():
return RedirectResponse(url=f"{ROOT_PATH}/ref")
@app.get("/health", tags=["System"])
def health_check():
"""Verify the API is running."""
return {"status": "ok"}