From 190975c8e0798bf4a0410cfb639557f54605227a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 Oct 2026 16:53:08 +0000 Subject: [PATCH 1/2] Initial plan From 0ff07066e829848def33080cf17299792b81571b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:04:42 +0000 Subject: [PATCH 2/2] docs: cover Seerr rules and media paths Co-authored-by: enoch85 <4511254+enoch85@users.noreply.github.com> --- docs/Glossary.md | 22 +++++++++++++++++++ docs/Rules.mdx | 9 ++++++-- docs/api/media-server.md | 7 ++++-- .../openapi-spec/maintainerr_api_specs.yaml | 4 ++-- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/docs/Glossary.md b/docs/Glossary.md index 70316216d..b17311c03 100644 --- a/docs/Glossary.md +++ b/docs/Glossary.md @@ -2123,6 +2123,28 @@ Indicates whether the media was requested in Seerr. - Availability: movies, shows, seasons, episodes - Type: boolean +#### Watchlisted by (username) + +:::info +List of Seerr users who have the movie or show in their watchlist. For seasons and episodes, this checks the parent show's watchlist. + +::: + +- Key: Seerr.watchlist_isListedByUsers +- Availability: movies, shows, seasons, episodes +- Type: text[] + +#### Is Watchlisted + +:::info +Indicates whether any Seerr user has the movie or show in their watchlist. For seasons and episodes, this checks the parent show's watchlist. + +::: + +- Key: Seerr.watchlist_isWatchlisted +- Availability: movies, shows, seasons, episodes +- Type: boolean + --- ### Ombi diff --git a/docs/Rules.mdx b/docs/Rules.mdx index 0f1c1a5f4..df28db2c4 100644 --- a/docs/Rules.mdx +++ b/docs/Rules.mdx @@ -69,6 +69,10 @@ Troubleshooting tips: ::: +:::note Seerr Watchlist Rules +`Watchlisted by` (`Seerr.watchlist_isListedByUsers`) and `Is Watchlisted` (`Seerr.watchlist_isWatchlisted`) check the watchlists of all users returned by Seerr. They work with every media server; Plex users' watchlists are read through their linked plex.tv accounts. A season or episode uses its show's watchlist because Seerr tracks watchlisted titles, not individual seasons or episodes. If Maintainerr cannot read the Seerr user list or any watchlist response, the result is unknown for that run rather than an empty list. +::: + ## Creating rules ### General @@ -171,7 +175,7 @@ Season delete actions unmonitor the season in Sonarr and delete its episode file Episode delete actions share the season folder with other episodes, so the folder is never removed by this action. No leftover folder cleanup is offered for episode rules. -Maintainerr finds the episode in Sonarr by its TVDB episode id when exactly one Sonarr episode has it, so a library numbered differently from Sonarr, such as absolute or DVD order, still acts on the right episode. Otherwise it matches by season and episode number, or by air date. When one file holds several episodes, all of them are unmonitored before the file is deleted, so Sonarr does not download it again. If any of them cannot be unmonitored, the file is kept. +Maintainerr first matches a Sonarr episode by the media file when its path identifies one file containing exactly one episode. If there is no unique file match, it falls back to a unique TVDB episode id, then to season and episode numbers or air date. When Sonarr's episode or file list cannot be read, episode-level rules stay unknown and episode actions skip the item rather than risk using the wrong episode. When one file holds several episodes, all of them are unmonitored before the file is deleted, so Sonarr does not download it again. If any of them cannot be unmonitored, the file is kept. ### Sportarr actions @@ -470,7 +474,8 @@ Both walkthroughs work unchanged for daily series: - Daily shows that use one season per year rank those year-seasons like any other season. - Some servers store daily episodes with only an air date and no episode - number. Those episodes are matched to Sonarr by broadcast date, so + number. Maintainerr first matches them by file when it identifies one + episode; otherwise it can match them to Sonarr by broadcast date, so `Episode position by air date (1 = latest)` still resolves. When two episodes of a date-only show share the same broadcast day, the newer one's rank is used, which errs on the side of keeping media. diff --git a/docs/api/media-server.md b/docs/api/media-server.md index 5e4b2d17a..17da4e7f5 100644 --- a/docs/api/media-server.md +++ b/docs/api/media-server.md @@ -125,6 +125,7 @@ Response: "addedAt": "2026-01-01T00:00:00.000Z", "providerIds": { "tmdb": ["550"] }, "mediaSources": [{ "id": "1", "sizeBytes": 0 }], + "path": "/media/movies/Example title (2026)/Example title.mkv", "library": { "id": "1", "title": "Movies" }, "maintainerrExclusionType": "global", "maintainerrIsManual": true, @@ -137,7 +138,7 @@ Response: } ``` -Items carry the full media item shape except `path`, which is only populated by the single-item metadata route. On top of the media server's own fields, this route adds Maintainerr state: `maintainerrExclusionId`, `maintainerrExclusionType` which is `specific` or `global`, `maintainerrIsManual`, and `maintainerrCollections`, the titles of every collection the item belongs to. +Items include the media server's path when that backend provides it. Movies and episodes return the media file; shows and seasons return the folder. Plex listings provide it only for movies and episodes, and Plex seasons have no path. On top of the media server's own fields, this route adds Maintainerr state: `maintainerrExclusionId`, `maintainerrExclusionType` which is `specific` or `global`, `maintainerrIsManual`, and `maintainerrCollections`, the titles of every collection the item belongs to. | Status | Cause | | ------ | ------------------------------------------------------------------------------------------- | @@ -230,6 +231,8 @@ Response: There is no way to choose which library is bootstrapped. It is always the first one the media server returned. The embedded page is always filtered to that library's own type, so a show library returns shows and never seasons or episodes. +The embedded content items can include `path`, as described for the paged content route. + A `sort` of `manual` or `excluded` pays the full-library sweep described above, at page load. ### `GET /api/media-server/search/{query}` @@ -279,7 +282,7 @@ Response: There is no way to tell a missing item from a failed read here. -`path` is the server's own filesystem path for that one item: movies and episodes return the media file, while shows and seasons return the folder. Only this single-item route populates it, and a Plex season has no path of its own. +`path` is the server's own filesystem path for that one item: movies and episodes return the media file, while shows and seasons return the folder. The paged content route and its embedded page in `overview/bootstrap` can also return it; other listing routes do not guarantee it. A Plex season has no path of its own. :::caution Watch fields are per-user and cached `viewCount`, `lastViewedAt` and `userRating` are scoped to the single Jellyfin or Emby user Maintainerr is configured with, and are cached for 5 minutes. Do not use them to drive watch or deletion decisions. Use `GET /api/media-server/meta/{id}/seen` for that. diff --git a/static/openapi-spec/maintainerr_api_specs.yaml b/static/openapi-spec/maintainerr_api_specs.yaml index b92ab2cbc..22bc0b7b1 100644 --- a/static/openapi-spec/maintainerr_api_specs.yaml +++ b/static/openapi-spec/maintainerr_api_specs.yaml @@ -1322,7 +1322,7 @@ paths: type: string responses: '200': - description: '' + description: The paged items can include the media server's filesystem path when the backend provides it. Plex listings provide it only for movies and episodes. tags: - MediaServer /api/media-server/library/{id}/content/search/{query}: @@ -1429,7 +1429,7 @@ paths: application/json: schema: type: object - description: Single-item media metadata. Only this route populates `path`, which is the media server's own filesystem path for the item. + description: Single-item media metadata. `path` is the media server's own filesystem path for the item. The paged library content route and overview bootstrap content can also include it. properties: path: type: string