Commit Graph
151 Commits
Author SHA1 Message Date
timothy c4ad4a73ba Merge pull request 'fix(497): reconcile music-video metadata collections on Jellyfin rescan' (#499) from fix/497-musicvideo-metadata-update into main
Build ErsatzTV Image / CI image pin matches docker/ci (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 7m15s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 14m27s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 17m30s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m50s
2026-07-20 16:53:41 +00:00
timothyandtimothy 2cf90fb44f feat(489): support Jellyfin mixed-content libraries (#493)
Build ErsatzTV Image / CI image pin matches docker/ci (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Has started running
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has started running
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been cancelled
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been cancelled
Jellyfin libraries typed `mixed` were dropped by JellyfinApiClient.Project's
`_ => None` with no log line, so music and standup content could not be
ingested without a local-library workaround that bypassed Jellyfin entirely.

Adds LibraryMediaKind.Mixed, maps "mixed"/absent/blank CollectionType onto it,
and gives SynchronizeJellyfinLibraryByIdHandler a Mixed arm composing the three
existing per-kind scanners. Jellyfin classifies items server-side via
includeItemTypes, so the passes see disjoint sets; reconciliation is type-scoped
and cannot cross-delete. No new scanner and no DB migration -- MediaItem is TPT
keyed on LibraryPathId, so heterogeneous contents were already legal.

Segregation falls out of the model: a library is a place (one path <-> one
Jellyfin library <-> one ErsatzTV library), so music/standup cannot leak into
Movies or TV Shows.

Also removes the silent-success `_ => Unit.Default` from both scanner
dispatchers, which returned Right for an unhandled kind and stamped LastScan as
though a scan had run, and rejects Mixed for local libraries at the API.

Deliberately Jellyfin-only: local scanners share one video extension list and
would claim each other's files, and LibraryFolder etags are keyed by
LibraryPathId with no notion of kind.

Verified by live E2E against a real Jellyfin, including the interaction with
#494's reconciliation sweep. Four cold review rounds, all MERGEABLE.

fixes #489

Co-authored-by: Timothy <timothy.look@gmail.com>
Co-committed-by: Timothy <timothy.look@gmail.com>
2026-07-20 16:34:51 +00:00
timothyandClaude Opus 4.8 c633b89ad9 fix(497): reconcile music-video metadata collections on Jellyfin rescan
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 9s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m12s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 51s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m25s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 7s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m56s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 15m37s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 19m3s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
JellyfinMusicVideoLibraryScanner.UpdateMetadata copied only scalar fields
for an EXISTING music video, so genres/tags/studios/artists edited in
Jellyfin never reached ErsatzTV — the update path silently dropped every
child collection (only the Add path ever persisted them). Root cause is
inherited from upstream: unlike the movie/episode Jellyfin path, which
reconciles collections inside the tracked repository GetOrAdd,
MusicVideoRepository.GetOrAdd is AsNoTracking and the scanner never
reconciled the collections itself.

Fix mirrors PlexMovieLibraryScanner.UpdateMetadata's remove-stale +
add-new idiom, reconciling exactly the collections that BOTH the Add path
persists AND GetOrAdd eager-loads: Genres, Tags, Studios, Artists. Guids
(add-persisted but not eager-loaded — would duplicate) and Directors
(eager-loaded but not add-persisted for music videos) are deliberately
out of scope.

Movie/Episode paths do NOT have this gap (they reconcile in the tracked
repo GetOrAdd), so no separate fix is needed there.

Test is an interaction test (substituted repos, canned existing item)
verifying the exact reconcile calls; proven non-vacuous. The real-DB
double-scan approach can't drive this: the in-memory harness shares one
SQLite connection across contexts and mid-scan GetOrAdd's First()-nav
path predicate mis-resolves once the existing item carries metadata
children — a harness-only quirk (prod uses per-context pooled
connections).

fixes #497

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 18:32:29 +02:00
timothyandtimothy 5b0d8b5d09 fix(494): reconcile removed music videos in Jellyfin scanner (#495)
Build ErsatzTV Image / CI image pin matches docker/ci (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 7m32s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 14m8s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 17m25s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m10s
fix(494): reconcile removed music videos in Jellyfin scanner (#495)

JellyfinMusicVideoLibraryScanner did add/update only, so a music video or
artist deleted on the Jellyfin side lingered forever. Add a library-scoped
trash sweep (TrashMissingMusicVideos) gated by the #477 empty-fetch guard.

fixes #494

Co-authored-by: Timothy <timothy.look@gmail.com>
Co-committed-by: Timothy <timothy.look@gmail.com>
2026-07-20 15:22:15 +00:00
timothyandClaude Opus 4.8 aa32fd78dd fix(477): guard media-server library sweeps against successful-but-empty fetches
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 5s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 9s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 7s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m23s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 7s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 7s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 15m20s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 18m18s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
A successful fetch returning zero items made existing.Except([]) flag the ENTIRE
library FileNotFound in one scan — feeding EmptyTrashHandler's permanent delete
and emptying every affected collection (dead channels). Add a shared
MediaServerReconciliationGuard that skips (and logs a Warning) the sweep when
incoming==0 while items exist, wired into the three library-level sweeps
(Television shows / Movie / OtherVideo).

An empty incoming set is indistinguishable at scan time from a mid-restore /
emptied-upstream error (both report a zero total), so this deliberately overrides
#476's degenerate "last item removed => empty incoming => flag" case. #476's
cascade still fires for partial deletions (survivors present); its characterization
test moves from an empty incoming to a survivor+removed partial-deletion case.

Tests: policy table (MediaServerReconciliationGuardTests) + per-scanner integration
proving the wiring (empty incoming + non-empty existing flags/reindexes nothing).
Proven non-vacuous by neutralizing the guard. Nested TV season/episode sweeps left
unguarded (bounded blast radius); ratio-threshold + projection-failure detection
deferred to a follow-up. docs/decisions.md updated.

Fixes #477

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 23:28:27 +02:00
timothyandClaude Opus 4.8 61bd374494 fix(476): cascade FileNotFound from removed shows/seasons to descendants
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 7s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 24s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 7s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m52s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 5m36s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 8s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 9s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 19m14s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
The media-server television scanner reconciles removed items at three levels
via existing.Except(incoming), but the season and episode sweeps live inside
the per-parent loops (ScanSeasons inside the show loop, ScanEpisodes inside the
season loop). Those loops only iterate parents present in the incoming list, so
a show (or season) that is gone from the media server is never visited and its
descendants are never swept — they keep their last state. On Jellyfin/Emby that
is RemoteOnly, which PlayoutBuilder does NOT skip even with PlayoutSkipMissingItems
on, so every orphaned episode keeps getting scheduled as a guaranteed tune-in
failure (the #473 reproduction; 717 stale prod rows across 10 removed shows).

Fix: cascade the flag by parent MediaItem.Id. Two provider-agnostic repo helpers
(Season.ShowId / Episode.SeasonId are on the base tables) flag descendants and the
scanner drives them after each parent sweep — show → seasons → episodes, and
season → episodes for the show-present case. Shared abstract base fixes
Jellyfin/Plex/Emby at once; Movie/OtherVideo are flat and have no such gap.

Tests: a Scanner.Tests case asserts the scanner cascades through the (substituted)
repository (non-vacuous — fails if the cascade calls are removed), and Integration
tests exercise the real cascade SQL against the schema, proving it flags only the
targeted subtree and no-ops on empty input.

fixes #476

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 21:49:33 +02:00
timothyandtimothy ebb9a40dc3 fix(410): log scan cancellation below ERROR (user-initiated, not a failure) (#453)
Build ErsatzTV Image / CI image pin matches docker/ci (push) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / decisions.md append-only (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Has started running
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Has been cancelled
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Has been cancelled
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been cancelled
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been cancelled
Co-authored-by: Timothy <timothy.look@gmail.com>
Co-committed-by: Timothy <timothy.look@gmail.com>
2026-07-18 16:18:02 +00:00
timothy 986ccfaf6c fix(264): log local path scan errors (review finding) + map Scanner.Tests
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 7s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 6s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 8s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 8s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 47s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 5m28s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 3m29s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m3s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Adversarial review (MERGEABLE, no blockers) raised two items worth
folding in rather than deferring:

Medium — ScanLocalLibraryHandler silently swallowed path scan errors,
while the three remote scanners it mirrors all log result.LeftToSeq().
That mattered less when a failed path only skipped the path-level
LastScan, but the previous commit makes a failed path suppress the
library-level scan time too — so the user would see exactly the #264
symptom ("Never scanned") with nothing in the log explaining why. That
is a diagnosis dead-end of the same class as the bug being fixed, so
log it here rather than file a follow-up. No test: the sibling
Synchronize*LibraryByIdHandlerTests don't assert on logging either, and
LogError is an extension method that NSubstitute can't cleanly verify.

Low — docs/testing.md bills itself as the authoritative map of what each
test project covers but omitted ErsatzTV.Scanner.Tests entirely (1471
pre-existing tests). This PR adds a file to that project, so add the row
and include it in the per-PR verification gate.
2026-07-17 14:27:50 +02:00
timothy 5c8dd64acf fix(264): record library-level LastScan after a successful local scan
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 6s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 7s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 8s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 8s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 40s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 6m10s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 5m36s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 11m11s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Local libraries permanently showed "Never scanned" in the SPA libraries
hub regardless of successful scans, even as item counts updated.

Root cause: ScanLocalLibraryHandler wrote only the path-level
LibraryPath.LastScan (which gates the per-path refresh interval) and
never the library-level Library.LastScan. The read API
(GetAllMediaSourcesForApiHandler) populates the hub's scan-time badge
from Library.LastScan, so that value stayed null forever. The three
remote scanners (Jellyfin/Emby/Plex) already set the library-level
value; only the local scanner did not. Both sides predate #202 — the
SPA hub merely made the missing value visible.

Mirror the remote scanners' semantics: record the library-level scan
time only when the scan actually ran and every path that ran succeeded,
so a skipped (unforced, interval not elapsed) or partially-failed scan
does not claim a successful scan time.

Also de-BOM the touched handler per the fix-as-you-touch charset gate
(#311).

fixes #264
2026-07-17 14:18:14 +02:00
timothyandCodex 8f90cea5cc feat(analyzers): enable incremental latest-All enforcement
Centralize SDK and threading analyzers, baseline the .NET 10 All rule inventory at suggestion severity, and promote S3981 repo-wide. Fix the always-true worker count predicate and cover the idle/active branches.

Fixes #15

Co-Authored-By: Codex <codex@openai.com>
2026-07-16 21:52:27 +02:00
timothy 5560790bcb feat(jellyfin): sync music video libraries refs #42
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 3m53s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m4s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
2026-06-30 19:33:06 +02:00
timothyandClaude Opus 4.8 77a28fcefc build: adopt Central Package Management (Directory.Packages.props)
Move all 154 PackageReference versions (96 distinct packages) out of the 14
project files into a single central Directory.Packages.props with
ManagePackageVersionsCentrally=true. No version changes — every package was
already pinned identically across projects (no conflicts detected), so this is a
pure relocation: updates become one-line and cross-project version drift is
structurally impossible.

Also copy Directory.Packages.props into the Docker image build before restore:
with CPM the csproj carry no versions, so the image's `dotnet restore` fails
without the central manifest (verified: NU1015 across every project).

Restore + Release build verified locally, plus a simulation of the image's
restore layer under linux-x64 (0 errors; only the pre-existing
NCalcSync/SQLitePCLRaw advisories remain, demoted to warnings, tracked in #8).

Part of #14.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 01:07:52 +02:00
Jason DoveandGitHub 0d301df5e8 remove external dependencies (bugsnag, trakt) (#2840)
* remove bugsnag

* remove trakt client id (that will expire)
2026-02-26 10:43:48 -06:00
Jason DoveandGitHub 0c30c47ba9 nvidia - decode 10-bit h264 in software (#2833)
* output progress/speed even when copying video

* nvidia - decode 10-bit h264 in software

* fixes

* fix tests
2026-02-20 23:00:15 -06:00
Jason DoveandGitHub 08cbf59527 lower gop size and keyframe interval (#2832)
* lower gop size and keyframe interval

* update changelog

* fix build using latest dotnet sdk

* fixes
2026-02-19 13:35:27 -06:00
Jason DoveandGitHub 794d209941 use latest authorization method with jellyfin api (#2821)
* use latest authorization method with jellyfin api

* temp pin dotnet sdk version to 10.0.102

* fix parameter name
2026-02-12 08:29:47 -06:00
Jason DoveandGitHub a0f5d8d5d5 detect more local movie artwork (#2804)
* expand test coverage

* support "backdrop" files as local movie fanart fallback
2026-01-27 16:35:28 -06:00
Jason DoveandGitHub 353f029452 fix null ref scanning other videos with nfo file (#2797)
* fix null ref scanning other videos with nfo file

* also fix movie null ref
2026-01-25 11:34:06 -06:00
Jason DoveandGitHub 7f361d1ea9 update dependencies (#2780)
* update messaging

* update dependencies
2026-01-16 13:57:25 -06:00
Jason DoveandGitHub a2d023ee69 local scanner artwork cleanup (#2778)
* move plex artwork removal to its own repository

* clean up old local movie artwork

* clien up old music video/artist artwork

* clean up old remote stream artwork

* clean up old song artwork

* clean up old show artwork; properly update season artwork
2026-01-16 10:23:26 -06:00
Jason DoveandGitHub 36f44f14bb fix other video artwork in xmltv (#2777) 2026-01-15 22:42:16 -06:00
Jason DoveandGitHub 89bb3759de more jf episode scanning improvements (#2753)
* more jf episode scanning improvements

* bump log level on important message

* add transaction
2026-01-03 12:43:26 -06:00
Jason DoveandGitHub 7c82ecdfff use separate load queries for jf episode inserts and updates (#2751) 2026-01-02 16:28:19 -06:00
Jason DoveandGitHub 80f6e468eb collect and print timings during jellyfin show library scans (#2748)
* collect and print timings during jellyfin show library scans

* update p99
2026-01-01 20:02:24 -06:00
Jason DoveandGitHub 474e647d6d more jellyfin performance improvements (#2747)
* fix slow db and api logging so it also works in scanner project

* don't request people from jellyfin by default
2025-12-31 22:28:15 -06:00
Jason DoveandGitHub b2caf8ee8d fix remote stream indexing due to missing titles (#2739) 2025-12-30 08:51:06 -06:00
Jason DoveandGitHub 2f0cd1eb6c update dependencies (#2726) 2025-12-19 13:56:26 -06:00
Jason DoveandGitHub 6bd49ffcec add remote stream metadata (#2690)
* add remote stream metadata

* use ifilesystem for last write time

* clean up unused inheritance

* optimize channel data query

* revert removeartwork change

* properly handle remote stream artwork in orphaned artwork check
2025-12-01 12:48:03 -06:00
Jason DoveandGitHub 7bd8cefe2e more dotnet 10 updates (#2676)
* update more libraries to dotnet 10

* fix dockerfiles

* fix numeric types
2025-11-29 15:47:08 -06:00
Jason DoveandGitHub 6c635a4be9 upgrade to dotnet 10 (#2667)
* upgrade to dotnet 10

* remove packages that would be pruned

* properly fix tests
2025-11-26 10:49:01 -06:00
Jason DoveandGitHub 9d637cdd54 update dependencies (#2661) 2025-11-25 16:06:48 -06:00
Jason DoveandGitHub ec0d8ea6ac work around sequential schedule validation limit (#2655)
* remove readalltext

* remove unused method

* remove fileexists

* remove folderexists

* remove readalllines

* remove fake local file system

* show playlist name in playout build errors

* add basic sequential schedule validator tests

* work around sequential schedule validation limit
2025-11-24 12:08:43 -06:00
Jason DoveandGitHub d88e721d2f optimize database calls related to search index (#2645) 2025-11-13 13:27:37 -06:00
Jason DoveandGitHub 132466b3d3 add avisynth script support to all local libraries (#2612)
* detect avisynth demuxer

* cache ffmpeg capabilities

* check for working avisynth

* scan avs files in all local libraries

* update changelog
2025-11-07 20:48:54 -06:00
Jason DoveandGitHub 629b3d7d9f fix effective block tests (#2600)
* fix effective block tests running on github

* update dependencies

* pass tz again

* use tzconvert for time zones in tests

* temporary logging

* maybe fix

* test cleanup
2025-11-05 06:48:49 -06:00
Jason DoveandGitHub 545db4db9b update dependencies (#2565)
* logging cleanup

* update dependencies
2025-10-24 09:17:45 -05:00
Jason DoveandGitHub e590298b93 add deep scans for external collections (#2562) 2025-10-23 19:32:38 -05:00
Jason DoveandGitHub f7c699248c fix collection and network scanners (#2557) 2025-10-22 08:59:06 -05:00
Jason DoveandGitHub 626048f9c3 change how scanner and main process communicate (#2555)
* report scanner progress using api

* process scanner search index updates through api

* update changelog

* update dependencies
2025-10-21 15:08:49 -05:00
Jason DoveandGitHub 6404dee646 update dependencies (#2539) 2025-10-15 08:41:38 -05:00
Jason DoveandGitHub c03f81a465 add block playout troubleshooting tool (#2512)
* rename yaml validation to sequential schedule validation

* some better exception handling

* add block playout troubleshooting page

* add paged block playout history

* add history details

* update changelog
2025-10-10 20:50:01 -05:00
Jason DoveandGitHub 64bb1b0d61 fix classic schedule flood bug (#2414)
* clean up some logging

* fix classic schedule flood bug
2025-09-14 02:36:50 +00:00
Jason DoveandGitHub f124554fba add some debug logging for music video scanning (#2408) 2025-09-12 16:56:29 +00:00
Jason DoveandGitHub 4e065fe922 update dependencies (#2406) 2025-09-11 18:04:48 +00:00
cb78b21d1c add support for aif, aifc, aiff (#2325)
* adds .aiff to supported audio file extension in local folder scanner

* add support for aif, aifc, aiff

---------

Co-authored-by: Jason Dove <1695733+jasongdove@users.noreply.github.com>
2025-09-07 19:24:43 +00:00
Jason DoveandGitHub 9462156148 fix mysql playout builds (#2352)
* more cancellation tokens and fixes

* so much cancellation token

* fix mysql playout builds
2025-08-27 18:09:56 +00:00
Jason DoveandGitHub 1c07df5bc3 use cancellation tokens in many places (#2350)
* use cancellation tokens everywhere

* more cancellation tokens
2025-08-27 03:20:35 +00:00
Jason DoveandGitHub 5d081ceeff fix editorconfig and run code cleanup (#2324)
* fix formatting rules

* reformat ersatztv

* reformat ersatztv.application

* reformat ersatztv.core

* refactor ersatztv.core.tests

* reformat ersatztv.ffmpeg

* reformat ersatztv.ffmpeg.tests

* reformat ersatztv.infrastructure

* cleanup infra mysql

* cleanup infra sqlite

* cleanup infra tests

* cleanup ersatztv.scanner

* cleanup ersatztv.scanner.tests

* sln cleanup

* update dependencies
2025-08-16 14:44:48 +00:00
d0af507bef add ability to deep scan just a single tv show for Plex, Emby, and Jellyfin (#2318)
* add ability to deep scan just a single tv show for Plex, Emby, and Jellyfin

Including "/api/libraries/{id:int}/scan-show" REST API endpoint to
trigger.

* restrict plex search results to the intended library

* restrict scanning to media server libraries that are marked to sync with etv

* fix previous commit

* also guard library scan api

* add scan buttons to show ui

* scan single plex show by id

* scan jellyfin and emby single shows by id

* update changelog

---------

Co-authored-by: Jeff Slutter <MrMustard@gmail.com>
Co-authored-by: Jason Dove <1695733+jasongdove@users.noreply.github.com>
2025-08-14 16:07:56 +00:00
f626954eb7 add external chapter file scanning (#2317)
* add external chapter file scanning

Support Matroska chapter xml files next to media file with extension .xml or .chapters

* only update chapters in db

---------

Co-authored-by: Jeff Slutter <MrMustard@gmail.com>
Co-authored-by: Jason Dove <1695733+jasongdove@users.noreply.github.com>
2025-08-14 03:34:47 +00:00