Mydia v0.10.0-beta2 — The Usenet & Parser Release
It's been two months since v0.9.0 and a lot has happened under the hood. This beta wraps up two long-running rollouts — the Usenet feature-parity push (10 issues, 9 merged units) and the Release Parser v3 rewrite (8 units, 245-case parity) — alongside a serious round of architectural cleanup that's been quietly making the codebase easier to live in.
Tagged as beta because the surface area is large and we want a wider testing window before cutting v0.10.0 final.
🎬 The Big Stories
Usenet, finally feature-complete
When the Usenet pipeline shipped a few months back, it worked — but it wasn't a peer of the torrent path. This release closes the gap. Mydia now:
- Parses
usenetdateandnzb_grabsfrom Newznab/Prowlarr/NZBHydra2 responses, so the ranker can actually reason about NZB freshness and popularity instead of pretending NZB results were torrents with zero seeders. - Filters releases by minimum post age (per-indexer setting), so you can avoid grabbing brand-new posts that haven't propagated yet.
- Ranks NZB results properly with a dedicated scoring branch instead of torrent heuristics.
- Routes downloads by content type — separate SABnzbd/NZBGet categories for movies vs TV vs anime, instead of the old one-category-per-client setup.
- Maps quality to a 5-tier priority profile per client, so you can push 4K to high priority and SD to low without touching the client.
- Detects stalled downloads at 99% and surfaces them with a badge in the Downloads view rather than polling forever.
- Blacklists failed releases so the next search doesn't pick the same broken NZB again.
- Accepts SABnzbd + NZBGet completion webhooks as a fast-path signal on top of the existing poll loop.
MediaImportis now idempotent so duplicate triggers from webhook + poll are safe.
Internally, SABnzbd (665 LOC) and NZBGet (517 LOC) now share a unified DownloadStatus struct and adapter helpers, with table-driven state mapping tests against frozen JSON fixtures from real API responses.
Closes #119, #120, #121, #122, #123, #124, #125, #126, #127, #128, #129.
Release Parser v3
The old FileParser.V2 was a regex-soup with edge cases that bit us in real-world torrent titles. v3 is a clean tokenizer → classifier → resolver pipeline with a regression corpus harvested from Sonarr and Radarr. All 14 call sites have been migrated, V2 has been deleted, and the parser is now 245-case parity tested against the corpus.
The tokenizer is byte-safe (it was Unicode bugs in the old parser that caused the file-parser-unicode-byte-offset fix), and the quality extractor finally handles weird release groups, parenthesized sub-expressions, and word-form Season 1 Episode 5 titles that V2 missed.
Auto-rename on import (TRaSH Guides format)
You can now opt into automatic file renaming on import using the TRaSH Guides naming format. Per-library toggle, exposed in library settings and through GraphQL.
Jellyfin NFO export
NFO writer module that emits Jellyfin-compatible .nfo files on import and refresh. Per-library opt-in plus a bulk export mix task for back-filling existing media. Handy if you're running Mydia alongside Jellyfin and want metadata to follow your files.
Issues tab revamp
The Downloads → Issues tab is now a proper three-section layout: unmatched, partial pack, failed. Manual match, manual resolution, and dismiss are all first-class actions instead of buried buttons. Season packs with unresolved files now do partial imports — the matched episodes land, the rest stay flagged.
Player CTA in the sidebar
The sidebar now surfaces the bundled web player with a prominent label and a CTA banner — so first-time users actually discover that /player is a thing.
🛠 Reliability & correctness
- qBittorrent: multipart uploads, post-add verification, 5.x compatibility, and a less-aggressive "missing" detector that doesn't flap on slow refreshes.
- Season pack redownload loop: fixed — packs no longer requeue every hour. Trackerless torrents are now detected structurally instead of by string matching.
- Title mismatch filter: search results where the parsed title doesn't match the target are rejected upfront. Unicode normalization (NFD) is consistent across the search path so accents don't cause false negatives.
- Crash reporting: Logger backend now installs cleanly on Elixir 1.15+, and the admin toggle actually works.
- Configurable metadata language for TMDB/TVDB requests, per install.
- Test suite is ~42% faster (221s → 127s) and Docker CI builds dropped from 2h+ to ~15min.
🧱 Architectural cleanup
A lot of this release is invisible to users but matters for everyone contributing or reading the code:
- AdminConfigLive split into eight focused LiveViews (
AdminSettingsLive,AdminIndexersLive,AdminQualityProfilesLive,AdminLibraryPathsLive,AdminMediaServersLive,AdminDownloadClientsLive,AdminSystemLive,AdminRemoteAccessLive). The monolith is gone. - Settings and Downloads contexts split into facade + sub-modules.
- MediaLive.Show extracted into focused event modules (
SearchEvents,FileEvents,SubtitleEvents, plus five more). - Type safety overhaul:
@specand@type tannotations across all 43 Ecto schemas, all context module public functions, and 14 Oban workers (with typedArgsstructs).MediaFile.metadatais now aFileMetadatastruct, not a plain map. QueryHelpers.Filterablemacro for declarative query filters, rolled out across collections, accounts, and downloads.- Component organization conventions documented (three-tier system: core / domain / feature-local).
⚙️ Infra
- Iroh upgraded to 0.97 for the P2P core.
- Docker CI: replaced Blacksmith with standard GitHub Actions for layer caching.
- CI postgres containers no longer leak between precommit runs.
🐛 Notable fixes
- Series rescan no longer imports wrong files / deletes metadata on refresh.
- SQLite FK corruption during table recreation: fixed.
- Word-form
Season Two Episode Fivefilenames now import correctly. - File parser uses byte offsets for regex slicing, fixing Unicode title mismatches.
Req.TransportErrorfrom FlareSolverr and indexer connections no longer crashes the page.- Paused torrents at 100% are correctly classified as completed.
📦 Try it
docker pull ghcr.io/getmydia/mydia:0.10.0-beta2
# Postgres variant
docker pull ghcr.io/getmydia/mydia:0.10.0-beta2-pg
# Or the rolling beta tag
docker pull ghcr.io/getmydia/mydia:betaPlayer builds for Android, macOS, Windows, and Linux are attached below.
Feedback welcome — open issues at getmydia/mydia. The plan is to bake this for a couple of weeks, fold in any regressions, then cut v0.10.0 final.
Full Changelog: v0.9.0...v0.10.0-beta2