fix(rules): inherit parent show for Streamystats watchlist at season/episode level (#3127)#3133
Merged
enoch85 merged 1 commit intoJun 19, 2026
Conversation
…episode level (#3127) A Streamystats list holds the show item ID, so the item-only `isInWatchlist` / `watchlistedByUsers` props return empty at the season/episode level, wrongly matching a watchlisted show's seasons in destructive rules. - add `isInWatchlist_including_parent` and `watchlistedByUsers_including_parent` (show-only, season/episode), mirroring the Jellyfin `sw_favoritedBy_including_parent` precedent - resolve the parent chain via the media server's `getMetadata` (same path the other getters use); skip (undefined) when metadata can't be fetched rather than falling back to an item-only check - base props left item-only; union/dedupe via the shared `definedUniqueValues`
cf0032a to
c6abb79
Compare
maintainerr-automation Bot
added a commit
that referenced
this pull request
Jun 20, 2026
* build(deps-dev): bump vitest from 4.1.8 to 4.1.9 (#3116) Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.8 to 4.1.9. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-version: 4.1.9 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps-dev): bump @tailwindcss/vite from 4.3.0 to 4.3.1 (#3117) Bumps [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) from 4.3.0 to 4.3.1. - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.1/packages/@tailwindcss-vite) --- updated-dependencies: - dependency-name: "@tailwindcss/vite" dependency-version: 4.3.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps-dev): bump @typescript-eslint/eslint-plugin (#3118) Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 8.61.0 to 8.61.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.61.1/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.61.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump react-router-dom from 7.17.0 to 7.18.0 (#3119) Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 7.17.0 to 7.18.0. - [Release notes](https://github.com/remix-run/react-router/releases) - [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md) - [Commits](https://github.com/remix-run/react-router/commits/[email protected]/packages/react-router-dom) --- updated-dependencies: - dependency-name: react-router-dom dependency-version: 7.18.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump nodemailer from 9.0.0 to 9.0.1 (#3120) Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 9.0.0 to 9.0.1. - [Release notes](https://github.com/nodemailer/nodemailer/releases) - [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md) - [Commits](nodemailer/nodemailer@v9.0.0...v9.0.1) --- updated-dependencies: - dependency-name: nodemailer dependency-version: 9.0.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump rolldown from 1.1.1 to 1.1.2 (#3122) Bumps [rolldown](https://github.com/rolldown/rolldown/tree/HEAD/packages/rolldown) from 1.1.1 to 1.1.2. - [Release notes](https://github.com/rolldown/rolldown/releases) - [Changelog](https://github.com/rolldown/rolldown/blob/main/CHANGELOG.md) - [Commits](https://github.com/rolldown/rolldown/commits/v1.1.2/packages/rolldown) --- updated-dependencies: - dependency-name: rolldown dependency-version: 1.1.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps-dev): bump typescript-eslint from 8.61.0 to 8.61.1 (#3126) Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.61.0 to 8.61.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.61.1/packages/typescript-eslint) --- updated-dependencies: - dependency-name: typescript-eslint dependency-version: 8.61.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump better-sqlite3 from 12.10.0 to 12.11.1 (#3124) Bumps [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) from 12.10.0 to 12.11.1. - [Release notes](https://github.com/WiseLibs/better-sqlite3/releases) - [Commits](WiseLibs/better-sqlite3@v12.10.0...v12.11.1) --- updated-dependencies: - dependency-name: better-sqlite3 dependency-version: 12.11.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(ui): adopt ESLint 10 via @eslint-react (#3121) Replace eslint-plugin-react (no ESLint 10 support) with @eslint-react/eslint-plugin and bump eslint/@eslint/js to v10 across workspaces; drop the legacy FlatCompat React config. Adopt the v10-compatible modern rules (ref-as-prop instead of forwardRef, use() for context, <Context> providers, hook/ref naming, set-state-in-effect) and re-enable the reverse-tabnabbing check. Leave no-array-index-key off (documented): the codebase has legitimate id-less ordered lists where it only forces disables or fragile keys. Also fix a listener leak in useClickOutside (capture flag mismatch). Raise the supported Node floor to 22 (drop Node 20; @eslint-react requires Node 22+) and align the devcontainer to production (Node 26). Disable the @eslint-react hook rules that duplicate eslint-plugin-react-hooks so each issue is reported once. * build(deps-dev): bump @faker-js/faker from 9.9.0 to 10.5.0 (#3123) * build(deps-dev): bump @faker-js/faker from 9.9.0 to 10.5.0 Bumps [@faker-js/faker](https://github.com/faker-js/faker) from 9.9.0 to 10.5.0. - [Release notes](https://github.com/faker-js/faker/releases) - [Changelog](https://github.com/faker-js/faker/blob/next/CHANGELOG.md) - [Commits](faker-js/faker@v9.9.0...v10.5.0) --- updated-dependencies: - dependency-name: "@faker-js/faker" dependency-version: 10.5.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]> * test: transform faker esm in server jest --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: enoch85 <[email protected]> * fix(servarr): fail closed on transient Sonarr/Radarr lookup failures (#3125) (#3128) getWithoutCache swallows transport/5xx errors to `undefined` without throwing, so getSeriesByTvdbId/getMovieByTmdbId collapsed a transient failure into `null` ("not tracked") via the empty-response check, leaving the helpers' catch-path `undefined` unreachable for HTTP failures. The comparator only treats strict `=== undefined` as transient, so the misclassified `null` bypassed the transient-removal guard: the item was dropped from the collection, then re-added next run when the lookup succeeded — the churn reported in #3125. The Sonarr action handler likewise read the transient miss as "not in Sonarr" and fell through to a media-server delete. - Distinguish `response === undefined` (transient -> `undefined`, fail closed) from an empty array (`null`, confirmed not tracked) in both arr helpers. - Add the missing `=== undefined` fail-closed branch to the Radarr getter. - Fail the Sonarr action handler closed on a transient lookup (return false, so the item is retried next run) instead of deleting it from disk. - Cover the helper contract, the Radarr getter, and the action-handler paths. Also drops a dead buildSeasonList helper and a no-op `await` on `new Date()`. * build(deps-dev): bump knip from 6.16.1 to 6.17.1 (#3130) Bumps [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip) from 6.16.1 to 6.17.1. - [Release notes](https://github.com/webpro-nl/knip/releases) - [Commits](https://github.com/webpro-nl/knip/commits/[email protected]/packages/knip) --- updated-dependencies: - dependency-name: knip dependency-version: 6.17.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump sharp from 0.35.1 to 0.35.2 (#3131) Bumps [sharp](https://github.com/lovell/sharp) from 0.35.1 to 0.35.2. - [Release notes](https://github.com/lovell/sharp/releases) - [Commits](lovell/sharp@v0.35.1...v0.35.2) --- updated-dependencies: - dependency-name: sharp dependency-version: 0.35.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(rules): inherit parent show for Streamystats watchlist at season/episode level (#3127) (#3133) A Streamystats list holds the show item ID, so the item-only `isInWatchlist` / `watchlistedByUsers` props return empty at the season/episode level, wrongly matching a watchlisted show's seasons in destructive rules. - add `isInWatchlist_including_parent` and `watchlistedByUsers_including_parent` (show-only, season/episode), mirroring the Jellyfin `sw_favoritedBy_including_parent` precedent - resolve the parent chain via the media server's `getMetadata` (same path the other getters use); skip (undefined) when metadata can't be fetched rather than falling back to an item-only check - base props left item-only; union/dedupe via the shared `definedUniqueValues` * fix(collections): heal empty Jellyfin/Emby collections (#3129) (#3134) * fix(collections): heal empty Jellyfin/Emby collections (#3129) Jellyfin/Emby BoxSets are not auto-deleted when they go empty, and they drain when underlying items are re-imported with new ids while the local DB keeps the rows. The empty-collection heal in checkAutomaticMediaServerLink was Plex-only, so such collections sat empty on the server with no path to recover. Extend the heal to Jellyfin/Emby: re-add rule-owned DB items missing from the BoxSet (repopulate in place, keeping the BoxSet id stable), and delete a confirmed-empty non-shared collection so it does not linger. The destructive path is gated on the media server's reported child count (a successful read that distinguishes empty from a transient enumeration failure, which returns [] per the read contract), plus an empty live read, no rule-owned item to re-add, and the collection not being shared, so a populated or repopulatable collection is never removed. * fix(rules): skip the manual import on the run that links an automatic collection When handleCollection links a freshly created automatic collection to a pre-existing, same-named media server collection, the post-handle state looks "already linked", so the membership-provenance guard (#2663) — which reads the link state in the sync phase — never skipped and imported that collection's existing contents as manual. Capture the link state BEFORE the run so the run that establishes the link skips the import. Honest about scope: this only suppresses the first-run flood. On a later run the collection is already linked, so the import runs and pre-existing, rule-unselected items get tracked as manual then. Distinguishing adoption-time contents from items the user adds to the BoxSet afterwards needs persisted provenance, which is out of scope here. * build(deps-dev): bump @types/node from 22.19.21 to 26.0.0 (#3132) * build(deps-dev): bump @types/node from 22.19.21 to 26.0.0 Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.19.21 to 26.0.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 26.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]> * fix(ui): raise tsconfig lib/target to ES2022 for Array.prototype.at --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: enoch85 <[email protected]> * fix(collections): don't resurrect a deleted collection's media-server link (#3135) When handling the last item empties an automatic collection, removeFromCollection deletes the media-server collection and clears mediaServerId in the DB. handleMedia discarded that result, then saveCollection-ed its stale snapshot and rewrote the dead mediaServerId back onto the row. The next rule run then finds a dangling link it can only resolve via a getCollection 404 before the heal clears it. Continue from removeFromCollection's returned collection so the post-handle save carries the cleared link forward — matching what the rule executor already does. --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: maintainerr-automation[bot] <261505141+maintainerr-automation[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: enoch85 <[email protected]>
Contributor
|
🎉 This PR is included in version 3.15.2 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
doonga
pushed a commit
to greyrock-labs/home-ops
that referenced
this pull request
Jun 20, 2026
…➔ 3.15.2) (#349) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/maintainerr/maintainerr](https://github.com/Maintainerr/Maintainerr) | patch | `3.15.1` → `3.15.2` | --- ### Release Notes <details> <summary>Maintainerr/Maintainerr (ghcr.io/maintainerr/maintainerr)</summary> ### [`v3.15.2`](https://github.com/Maintainerr/Maintainerr/blob/HEAD/CHANGELOG.md#3152-2026-06-20) [Compare Source](Maintainerr/Maintainerr@v3.15.1...v3.15.2) #### Highlights - Fixed transient failure handling for Sonarr and Radarr lookups, preventing data loss during rule evaluations under heavy load ([#​3125](Maintainerr/Maintainerr#3125), [#​3128](Maintainerr/Maintainerr#3128), [#​3139](Maintainerr/Maintainerr#3139)). - Resolved issues with Jellyfin/Emby automatic collections, ensuring proper handling of empty collections and preventing resurrection of deleted media-server links ([#​3129](Maintainerr/Maintainerr#3129), [#​3134](Maintainerr/Maintainerr#3134), [#​3135](Maintainerr/Maintainerr#3135), [#​3137](Maintainerr/Maintainerr#3137)). - Improved Streamystats watchlist handling by inheriting parent show information for season/episode-level rules, preventing unintended deletions or unmonitoring ([#​3127](Maintainerr/Maintainerr#3127), [#​3133](Maintainerr/Maintainerr#3133)). #### Fixes - Fixed transient failure handling for Sonarr and Radarr lookups, ensuring fail-closed behavior to prevent data loss during rule evaluations under heavy load ([#​3125](Maintainerr/Maintainerr#3125), [#​3128](Maintainerr/Maintainerr#3128), [#​3139](Maintainerr/Maintainerr#3139)). - Resolved issues with Jellyfin/Emby automatic collections: - Fixed empty collections not healing properly for Jellyfin/Emby servers ([#​3129](Maintainerr/Maintainerr#3129), [#​3134](Maintainerr/Maintainerr#3134)). - Prevented resurrection of deleted media-server links when handling empty collections ([#​3135](Maintainerr/Maintainerr#3135)). - Removed redundant empty-collection delete logic for Jellyfin/Emby, retaining only the repopulation path ([#​3137](Maintainerr/Maintainerr#3137)). - Improved Streamystats watchlist handling by inheriting parent show information for season/episode-level rules, preventing unintended deletions or unmonitoring ([#​3127](Maintainerr/Maintainerr#3127), [#​3133](Maintainerr/Maintainerr#3133)). #### Dependencies - Updated 12 dependencies, including [@​types/node](https://github.com/types/node), sharp, [@​faker-js/faker](https://github.com/faker-js/faker), and typescript-eslint. </details> --- ### Configuration 📅 **Schedule**: (in timezone America/New_York) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjQuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIyNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.greyrock.io/greyrock-labs/home-ops/pulls/349
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3127.
A Streamystats watchlist holds the show item ID, so the existing item-only
isInWatchlist/watchlistedByUsersprops return empty when a rule is evaluated at the season/episode level. ANOT_CONTAINS <user>protection rule then wrongly matches a watchlisted show's seasons and sweeps them into deletion/unmonitoring.isInWatchlist_including_parentandwatchlistedByUsers_including_parent(show-only,season/episode), mirroring the existing Jellyfinsw_favoritedBy_including_parentprecedent.getMetadata— the same canonical path the Jellyfin/Emby/Plex getters use — so parent IDs come from the mapper's hierarchy resolution (SeriesIdfor seasons, not the library-folderparentId). Gated on the server-agnostictypeso a movie is never rolled up.undefined, transient) when metadata can't be fetched, rather than falling back to an item-only check that could let a protected item match a destructive rule.definedUniqueValueshelper.