Initial design for MediaShelf
Software design for a Plex library analytics and reclaim-reporting tool. v1 is report-only: no deletion, no filesystem access, Plex API as the sole data source. Movies at item level, TV rolled up to season level. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GVbG48GAXfCZatcmX123Ra
This commit is contained in:
commit
fdcddc8149
4 changed files with 1105 additions and 0 deletions
30
.env.example
Normal file
30
.env.example
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
# MediaShelf configuration — copy to .env and fill in.
|
||||||
|
# NEVER commit .env. PLEX_TOKEN is a secret.
|
||||||
|
|
||||||
|
MEDIASHELF_SECRET_KEY=change-me
|
||||||
|
LOG_LEVEL=INFO
|
||||||
|
TZ=America/Regina
|
||||||
|
|
||||||
|
# --- Plex connection ---
|
||||||
|
PLEX_BASE_URL=http://192.168.1.10:32400
|
||||||
|
PLEX_TOKEN=your-plex-token-here
|
||||||
|
PLEX_VERIFY_SSL=true
|
||||||
|
PLEX_TIMEOUT_S=30
|
||||||
|
PLEX_PAGE_SIZE=500
|
||||||
|
PLEX_REQUEST_DELAY_MS=0
|
||||||
|
|
||||||
|
# --- Storage ---
|
||||||
|
DATABASE_PATH=/data/mediashelf.db
|
||||||
|
|
||||||
|
# --- Scanning ---
|
||||||
|
SCAN_SCHEDULE_CRON=0 4 * * *
|
||||||
|
SCAN_FULL_SWEEP_CRON=0 3 * * 0
|
||||||
|
SCAN_ON_STARTUP=false
|
||||||
|
SCAN_LOCK_TIMEOUT_S=7200
|
||||||
|
|
||||||
|
# --- Reclaim score tuning ---
|
||||||
|
SCORE_STALE_HORIZON_DAYS=730
|
||||||
|
SCORE_AGE_HORIZON_DAYS=1095
|
||||||
|
SCORE_POPULAR_AT=3
|
||||||
|
SCORE_GRACE_DAYS=30
|
||||||
|
SCORE_RECENT_DAYS=90
|
||||||
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
.env
|
||||||
|
*.db
|
||||||
|
*.db-wal
|
||||||
|
*.db-shm
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
.pytest_cache/
|
||||||
|
.coverage
|
||||||
|
htmlcov/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
*.egg-info/
|
||||||
|
data/
|
||||||
|
.DS_Store
|
||||||
47
README.md
Normal file
47
README.md
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
# MediaShelf
|
||||||
|
|
||||||
|
A self-hosted web app for figuring out which of the thousands of files in a Plex library
|
||||||
|
are actually worth keeping.
|
||||||
|
|
||||||
|
MediaShelf scans a Plex Media Server over its HTTP API, builds a local snapshot of every
|
||||||
|
movie and TV season, and joins together the facts Plex already knows but never shows side
|
||||||
|
by side — date added, size on disk, file path, owning library, watch count, and last
|
||||||
|
watched — into a sortable, filterable, chartable grid with a tunable **reclaim score**
|
||||||
|
that ranks deletion candidates.
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
**v1 is report-only.** MediaShelf does not delete, move, or modify anything. It produces
|
||||||
|
a ranked list, saved rule sets, and CSV export. Deletion is designed for in the roadmap
|
||||||
|
but deliberately not built, so the scanner and the scoring model can be trusted before
|
||||||
|
anything destructive is wired up.
|
||||||
|
|
||||||
|
Nothing is implemented yet — this repository currently holds the design.
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
- Full-library ingest from Plex, no agent on the Plex host, no filesystem mounts
|
||||||
|
- Movies at item level, TV rolled up to **season** level
|
||||||
|
- Watch data pulled from the server-wide playback history, so plays by *every* Plex
|
||||||
|
account are counted — not just the token owner's
|
||||||
|
- Sort and filter on every metric; charts for size by library, additions over time,
|
||||||
|
watched vs. unwatched by size, and size vs. last-watched
|
||||||
|
- A weighted reclaim score with live sliders, and grace rules so it never recommends
|
||||||
|
something you added last week
|
||||||
|
- Named, re-runnable saved views — *"unwatched, older than 2 years, over 10 GB"*
|
||||||
|
- CSV export of any view
|
||||||
|
|
||||||
|
## Planned stack
|
||||||
|
|
||||||
|
Python + Flask, SQLite (WAL), vanilla JS front-end, single container deployed as a
|
||||||
|
Portainer stack behind Nginx Proxy Manager.
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
- **v2** — two-stage quarantine-then-purge deletion, with authentication, a path
|
||||||
|
allowlist, and an audit log
|
||||||
|
- **v3** — Emby and Jellyfin support behind the existing `MediaProvider` abstraction
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [`docs/design.md`](docs/design.md) — the full software design
|
||||||
1012
docs/design.md
Normal file
1012
docs/design.md
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue