Pass forceRefresh=true to getAllPlexUserIds() from the four batch entry
points so each run reads the user's current Plex sharing settings rather
than a snapshot left by the previous run.
Fixes#577
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
* feat: refresh overlay of a single item
* fix(overlay): add single item overlay refresh to frontend (in test item search feature)
---------
Co-authored-by: Tom Wheeler <thomas.wheeler.tcw@gmail.com>
Store rating keys for per-user Seerr collections to enable home screen ordering, and fix visibility
form to hide unavailable options for user and server owner collections
Plex webhooks are multipart/form-data with a `payload` text field
and a `thumb` JPEG file. `upload.none()` rejects file fields,
throwing `MulterError: Unexpected field` on every webhook that
includes a thumbnail.
Switch to `upload.single('thumb')` so multer accepts the image
(discarded after the request, only `payload` is used).
Fixes#565
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
The orphan file scanner only matched {edition-Trailer}, but
removePlaceholder accepts {edition-Placeholder} and {edition-Coming Soon}
too (legacy formats from before the Dec 2025 rename). Legacy files were
never garbage-collected and accumulated in the placeholder root.
Fixes#575
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
Maintainerr >= 3.4.0 changed GET /api/collections to return only 2 preview items per collection. T
he new /api/collections/overlay-data endpoint returns the full media list.
Falls back to the legacy endpoint for Maintainerr <= 3.3.x compatibility.
Co-authored-by: timelordx <timelordx@users.noreply.github.com>
When refreshTop250Cache() fails (e.g. WAF timeout), lastRefresh was
never set, so needsRefresh() returned true on every subsequent call.
This caused a ~30s WAF timeout per item across the entire library.
Set lastRefresh on failure with a 5-minute backoff so it retries once
per window instead of per item.
Fixes#546
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
Coming Soon, Countdown, Far Future Release Date, and Releasing Tomorrow
overlays persisted after content was grabbed before its official release
date. Added downloaded == false to all affected preset template conditions.
Returning Soon templates intentionally excluded — they track future
seasons on shows that already have downloaded content.
Ref: agregarr/agregarr#554
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
SVG files uploaded as icons are saved without sanitisation. Embedded
script tags, event handlers, foreignObject elements, and javascript:
URIs in SVG content enable stored XSS.
Adds sanitizeSvg() that strips dangerous elements and attributes
before saving. Applied via uploadIcon() so template imports are
also covered.
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
PlaceholderDiscovery re-verified TV items via isPlaceholderItem() which
returns false during library-level scans (no Children metadata in Plex
response). The marker file on disk already proves it's an Agregarr-created
placeholder, so trust that instead of re-checking a broken API path.
Also: find S00E00 by episode index not array position, and use async
placeholder detection in the orphan scan for definitive TV identification.
Ref #414
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
vm2 is listed as a dependency but never imported anywhere in the
codebase. It has been deprecated and has multiple sandbox escape
CVEs. Removing it.
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
Longstanding Plex bug not respecting label restrictions for Collections on Home/Recommended has been
fixed in PMS Beta 1.43.1.10540, confirmed working with Agregarr. Also removes previous easter egg
which enabled the option (intended for use when the project was going to be a PR for Overseerr,
allowing use of the option without waiting for an update)
fix#112
Maintainerr v3 renamed `plexId` (number) to `mediaServerId` (string)
in their API response. The overlay context builder compared against the
old field, silently failing to match any media items so daysUntilAction
never populated.
Read `mediaServerId` with fallback to `plexId`, compare as strings.
Supports both Maintainerr v2 and v3.
Fixes#501
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
Plex returns seasons as Children.Directory (not Children.Metadata)
when using ?includeChildren=1. All placeholder detection code only
checked Children.Metadata, so isPlaceholderItem() always returned
false for TV shows — skipping title fixes and triggering false
cleanup of valid placeholders.
Added Metadata || Directory fallback across all detection paths,
type casts, and getChildrenMetadata() API helper.
Fixes#414
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
When an item isn't yet visible in Plex, indexOf returns -1 and
splice(-1, 1) removes the last element of the tracking array,
corrupting all subsequent move decisions.
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
Add pagination loop to process all library items instead of only the first 50. Use
plexApi.getLibraries() instead of OverlayLibraryConfig so libraries without overlays are included.
#433
The overlay test endpoint checks every collection for item membership
sequentially. With ~150 collections at ~250ms each, the request takes
~37 seconds and the frontend times out.
Batched the getCollectionItems() calls with Promise.all at concurrency
10, matching the pattern in OverlayLibraryService. Brings the check
down to ~4 seconds for 150 collections.
Fixes#468
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
lookupByMal() iterates all ~25k anime ID rows to find a MAL ID match.
MAL sources can fetch thousands of items, each calling lookupByMal(),
so preview requests time out before returning results.
Added a _byMal Map index built during loadAnimeIds(), matching the
existing _byAniDB pattern. Lookups are now O(1) instead of O(n).
Fixes#480
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
* FIX: ADD-OR dropdown was not letting you change it to OR
* FIX: make it so that TMDB cast,crew,people filters show the name with the ID
* FIX: add name when adding person on TMDB as an ID number
* FIX: TMDB custom collection now saves settings on update
* FIX: after deleting a TMDB custom collection, you could not make a new one with the same name
* FIX: hydration was not working on large groups of IDs
* fix: move IMDb rating position out of conflict with top banner tiles
* fix: move dolby vision, hdr position down to prevent conflict with new imdb position
* - Updated `hideIndividualItems` description in settings to clarify support for both Coming Soon and TMDB auto_franchise collections.
- Improved `ComingSoonCollectionSync` to filter items based on media type and apply collection exclusions.
- Added logic to set collection mode when `hideIndividualItems` is enabled, ensuring individual items are hidden in the library tab.
- Adjusted UI components to reflect changes in collection mode options for TMDB and Coming Soon collections.
* fix(comingsoon): guard missingItems before quick-sync storage
.find() only returned the first TV/movie library with placeholders
enabled, silently skipping any additional libraries. Replace with
.filter() + Set to discover and process placeholders across all
libraries.
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
* feat: separate placeholder filters independent of auto-request filters
Add placeholderMinimumYear, placeholderMinimumImdbRating,
placeholderMinimumRottenTomatoesRating,
placeholderMinimumRottenTomatoesAudienceRating, and
placeholderFilterSettings to CollectionConfig and
MultiSourceCollectionConfig.
buildPlaceholderFilterConfig() helper swaps placeholder values into
standard filter fields so MissingItemFilterService works unchanged.
Updated BaseCollectionSync and MultiSourceOrchestrator call sites.
Collapsible "Placeholder Filters" section in collection edit form
reuses FilterWithMode/KeywordFilterWithMode. Auto-expands when
editing configs with existing values.
Fixed pre-existing gap: keywords missing from
MultiSourceCollectionConfig.filterSettings type.
---------
Co-authored-by: bitr8 <bitr8@users.noreply.github.com>
Co-authored-by: Tom Wheeler <thomas.wheeler.tcw@gmail.com>