arnaucube
arnaucube/jellyfin-toolsPublic Self-hosted repository
jellyfin-tools/jellyfin-year-review/README.md
jellyfin-year-review/README.mdRaw
  1# jellyfin-year-review
  2
  3Run these commands from the project directory.
  4
  5## Translate the webapp
  6
  7Edit [`web/src/lib/translations.json`](web/src/lib/translations.json). It includes
  8Catalan (`ca`) and English (`en`). Set the top-level `language` to select the
  9language used by the webapp. Catalan is selected by default:
 10
 11```json
 12{
 13  "language": "ca",
 14  "languages": {
 15    "ca": {
 16      "locale": "ca",
 17      "direction": "ltr",
 18      "strings": {
 19        "Sign out": "Tanca la sessió"
 20      }
 21    },
 22    "en": {
 23      "locale": "en",
 24      "direction": "ltr",
 25      "strings": {
 26        "Sign out": "Sign out"
 27      }
 28    }
 29  }
 30}
 31```
 32
 33This example shows only one string; keep the full catalogs in the actual file.
 34To use English, change only `"language": "ca"` to `"language": "en"`.
 35An unknown language reports a configuration error.
 36
 37To add another language, copy a catalog under `languages` with a new language
 38code. Under its `strings`, keep the English keys and translate the values.
 39Keep placeholders such as `{year}`, `{name}`, and `{count}` unchanged; you can
 40move them within the sentence. `\n` adds a line break in the sign-in heading.
 41Each catalog's `locale` controls numbers, dates, and the page language; it does
 42not select the catalog. Set `direction` to `rtl` for right-to-left languages,
 43or keep `ltr`.
 44
 45The file covers interface text, accessibility labels, months and weekdays,
 46viewing profiles, and known server errors and review warnings. Usernames, media
 47titles, and other source data stay as supplied. To translate custom source or
 48coverage descriptions and genre labels, add their exact original text as a key.
 49Missing entries fall back to the original text. Values are plain text, not HTML.
 50
 51Run `npm --prefix web run test:unit` to check translations and placeholders,
 52then `npm --prefix web run build` and restart the serving process. For Docker,
 53rebuild the image using the Compose command below. Language selection and
 54translation edits apply to everyone using that build; no review data needs to
 55be regenerated.
 56
 57## 1. Generate review data
 58
 59Requires Go 1.27.2, `psql`, and native Jellystat history. Copy `.env.example` to
 60`.env` and configure:
 61
 62- `JELLYFIN_URL` (reachable from this machine) and `JELLYFIN_API_KEY`.
 63- `PGHOST`, `PGDATABASE`, `PGUSER`, and `PGPASSWORD` for read-only Jellystat access.
 64- `REVIEW_TIMEZONE`. Posters come from Jellyfin, with TVmaze as a fallback for
 65  TV shows (no additional API key).
 66
 67Set `PGPASSWORD='your-postgresql-password'` in `.env` (keep the quotes).
 68Keep `.env` private (`chmod 600 .env`), then run:
 69
 70```sh
 71./scripts/generate-review.sh 2025
 72```
 73
 74The script reports its progress, loads `.env`, exports history, and generates
 75`data/`. If it reports a missing `psql`, install the PostgreSQL client on this
 76machine (for Debian/Ubuntu: `sudo apt install postgresql-client`). Change the year
 77to generate another recap. Optionally set `REVIEW_COVERAGE` to describe your
 78collection window and known gaps.
 79
 80## 2. Export Jellyfin users
 81
 82With Python 3.9+ on the Jellyfin 12.2 host:
 83
 84```sh
 85python3 scripts/export-jellyfin-auth.py --database /path/to/jellyfin.db --output auth/users.json
 86```
 87
 88Use the actual database path with read access to its WAL/SHM files. The export
 89contains private password verifiers, never plaintext passwords. Rerun after
 90password or account changes. Only supported built-in accounts can log in offline.
 91
 92## 3. Serve the webapp
 93
 94On the serving host, place the project, generated `data/`, and private
 95`auth/users.json` together. **Upload `data/` and `auth/` separately:** the normal
 96code-upload rsync excludes them. Do not upload the Jellyfin database or API keys.
 97
 98Run either option as the non-root user who owns `data/` and `auth/`.
 99First set permissions and the public origin:
100
101```sh
102chmod 700 data auth
103chmod 600 auth/users.json
104
105export APP_ORIGIN=https://review.example.com
106```
107
108With Docker Compose:
109
110```sh
111export REVIEW_UID="$(id -u)" REVIEW_GID="$(id -g)"
112docker compose -f compose.offline.yaml up -d --build
113```
114
115Without Docker (requires Go 1.27.2 and Node.js 24+ to build):
116
117```sh
118npm --prefix web ci
119npm --prefix web run build
120go build -buildvcs=false -o ./review ./cmd/review
121
122./review serve --listen 127.0.0.1:8080 \
123  --data ./data --web ./web/build \
124  --auth-mode offline --auth-file ./auth/users.json
125```
126
127The server runs in the foreground; Node.js is only needed for the frontend build.
128
129Point your HTTPS reverse proxy at `127.0.0.1:8080`; `APP_ORIGIN` must match the
130public origin exactly, without a trailing slash. Compose reads settings from
131`.env`; without Docker, export `APP_ORIGIN` each time you start the server.
132
133Users log in with their exported Jellyfin credentials. Serving requires no
134Jellyfin connection. See [offline setup](docs/offline-auth.md) for secure transfer
135and atomic credential-refresh instructions.