Skip to content

Repository files navigation

lehrer-lyrics

Lehrer lyrics in all their glory, one song to brighten your day.

CI codecov License: MIT Python 3.14+ Ruff uv ty prek

A project created with FastAPI cloud CLI -> docs.

Scraper CLI

A dev-only CLI (lehrer-scrape) with four commands that form a pipeline:

uv sync --group dev

# 1. Scrape song pages → song-urls.json
uv run lehrer-scrape scrape

# 2. Download PDFs → .cache/pdf/
uv run lehrer-scrape download-pdfs

# 3. Convert lyrics PDFs to Markdown → .cache/markdown/  (requires Ollama)
uv run lehrer-scrape pdf-to-markdown                     # local Ollama
uv run lehrer-scrape pdf-to-markdown --cloud             # Ollama cloud (prompts for API key)

# 4. Build SQLite database → lehrer_lyrics/service/songs.db  (commit to repo)
uv run lehrer-scrape build-db

See docs/lehrer-scrape.md for full CLI and module documentation.

Service

A FastAPI app (lehrer_lyrics/service/main.py) that serves one Tom Lehrer song per day.

How it works:

  • On startup, all songs are loaded once from lehrer_lyrics/service/songs.db (a SQLite database built by lehrer-scrape build-db) and cached in memory.
  • Each request to GET / picks today's song by seeding Python's random.Random with the current date in the Europe/Berlin timezone — everyone sees the same song all day, and it changes deterministically at midnight Berlin time.
  • Lyrics are stored as zlib-compressed Markdown blobs in the database. They are decompressed and rendered to HTML (with nl2br for line-break preservation) on the first request of each day, then cached.
  • If the database is empty the service falls back to a bundled "A Christmas Carol" file.
  • Static assets (CSS) are served from /static.

About

Tom Lehrer lyrics to help you going from adolescence to senility, bypassing maturity.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages