Skip to content

feat: anime quality profile and server selection for Seerr#95

Merged
retardgerman merged 20 commits intomainfrom
dev
Apr 14, 2026
Merged

feat: anime quality profile and server selection for Seerr#95
retardgerman merged 20 commits intomainfrom
dev

Conversation

@retardgerman
Copy link
Copy Markdown
Contributor

@retardgerman retardgerman commented Apr 9, 2026

Summary

  • Adds 4 new config keys for anime-specific Radarr/Sonarr routing: DEFAULT_QUALITY_PROFILE_ANIME, DEFAULT_QUALITY_PROFILE_ANIME_MOVIE, DEFAULT_SERVER_ANIME, DEFAULT_SERVER_ANIME_MOVIE
  • Anime is detected automatically via TMDB genre 16 (Animation) + Japanese original language — same heuristic Jellyseerr uses internally
  • Falls back to standard movie/TV defaults if no anime config is set, so existing setups are unaffected
  • isAnime: true is included in the Jellyseerr request payload when anime is detected, allowing Jellyseerr to route to its own anime-configured instance
  • Dashboard: all 4 anime selects are populated when clicking "Load Seerr Options" (Sonarr profiles/servers for anime TV, Radarr for anime movies)

AI-assisted documentation. Code logic manually verified.

Closes #94

retardgerman and others added 20 commits April 5, 2026 13:33
Adds separate configurable quality profiles and Radarr/Sonarr servers
for anime content (TV series and movies). Anime is detected automatically
using TMDB genre 16 (Animation) + Japanese original language, matching
Jellyseerr's own heuristic. Falls back to the standard movie/TV defaults
if no anime-specific config is set.

- 4 new config keys: DEFAULT_QUALITY_PROFILE_ANIME, DEFAULT_QUALITY_PROFILE_ANIME_MOVIE, DEFAULT_SERVER_ANIME, DEFAULT_SERVER_ANIME_MOVIE
- isAnime flag threaded through interactions → botUtils → seerr.js and included in the Jellyseerr request payload
- Dashboard: anime quality/server selects populated alongside existing ones when loading Seerr options
Adds a manual "Anime" checkbox to each library row in the Library
Channel Mapping section. Users can explicitly tag a Jellyfin library
as anime — explicit and robust, works with any library naming.

Config format updated from { libraryId: channelId } to
{ libraryId: { channel, isAnime } } with full backward compatibility.
Resolvers in libraryResolver.js handle both old and new formats.
New getLibraryAnimeFlag() helper exported for downstream use.
- Add console.error to all previously empty/silent catch blocks in script.js
  (library channel dropdown populate, library config parse on render,
  library config parse on save, autostart check)
- Add warn log in resolveTargetChannel when null is resolved despite
  library being in the notification list
- Refactor jellyfinWebhook.js inline library resolution to use shared
  getLibraryChannels() / resolveTargetChannel() / getLibraryAnimeFlag()
  from libraryResolver.js — eliminates logic duplication with poller/ws
- Wire getLibraryAnimeFlag() into all three notification sources
  (webhook, poller, WebSocket) and pass isAnimeLibrary through to
  processAndSendNotification — flag is now fully in the pipeline,
  logged at info level, ready for downstream use
Array-format JELLYFIN_NOTIFICATION_LIBRARIES was previously expanded
inline in the webhook but not in getLibraryChannels(). Now that all
three paths use the shared helper, the conversion lives there so
legacy configs work consistently across webhook, poller, and WebSocket.
- jellyfinPoller / jellyfinWebSocket: log error when targetChannelId
  resolves to null so skipped notifications are visible in logs
- jellyfinWebhook: warn in buildJellyfinUrl fallback path so
  misconfigured JELLYFIN_BASE_URL is surfaced
- web/script.js: add console.error/warn/debug to every previously
  empty catch block (version fetch, bot status, session check, webhook
  secret, localStorage cache, Seerr user load, mapping reload, role
  load, logs-page bot status) — no control flow changes, logging only
- Logout catch: add console.error + showToast so user gets feedback
- loadDiscordGuilds / loadDiscordChannels: add console.error with context
- loadRoles catch: add UI fallback (allowlist/blocklist error message)
  in addition to the existing console.error
- updateConnectionStatus: add console.warn to both Seerr and Jellyfin
  catch blocks for diagnostics
- TMDB fetch catch: include error message in the log line
Replace hardcoded English string with translation key.
Adds logout_failed to en/de/sv locale files and template.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
en/de/sv/template were all missing config.default_anime_quality,
default_anime_quality_help, default_anime_movie_quality,
default_anime_movie_quality_help, default_anime_server,
default_anime_server_help, default_anime_movie_server,
default_anime_movie_server_help — causing raw key names to render
in the dashboard.

Also backfills missing quality/server/load_profiles_servers keys in
sv and template that were never added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sv.json was missing next_steps_title/next_step_1-3 in config.
template.json was missing the same plus episode_channel,
episode_channel_help, season_channel, season_channel_help,
use_default_channel.

de.json is complete relative to en.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…system

Add ~80 new i18n keys covering debounce, library channel mapping, embed
customization, user mapping, role permissions, misc settings, embed colors,
and app settings sections. Wire all keys into index.html via data-i18n
attributes and update script.js to use t() for dynamically set strings
(bot control buttons, quality/server dropdowns, channel selects, anime
library labels).
The slash-command path correctly detected isAnime and passed it to
parseQualityAndServerOptions and sendRequest, but the button handler
did not. Users clicking the request button bypassed anime-specific
quality profiles and server selection entirely.
- botUtils.js: replace empty catch blocks with debug/warn logging
- interactions.js: upgrade tag-fetch failures from debug to warn;
  add user-facing reply in outer interaction catch block
- script.js: check fallbackResponse.ok in loadTranslations; show
  toast on translation load failure; show toast on autostart check
  failure; add console.error + error detail to saveConfig and
  add-mapping catches; add response.ok checks before JSON parse in
  refresh-users handler
- jellyfinWebSocket.js: log stale map size after refresh failure
- jellyfinWebhook.js: include parse error in buildJellyfinUrl warning
@retardgerman retardgerman merged commit d172b12 into main Apr 14, 2026
5 checks passed
retardgerman added a commit that referenced this pull request Apr 14, 2026
* chore: error handling, CI audit, legacy .env migration removal
* fix: npm audit fix for dev branch, bump CI to Node 20
* feat: anime quality profile and server selection for Seerr
Adds separate configurable quality profiles and Radarr/Sonarr servers
for anime content (TV series and movies). Anime is detected automatically
using TMDB genre 16 (Animation) + Japanese original language, matching
Jellyseerr's own heuristic. Falls back to the standard movie/TV defaults
if no anime-specific config is set.
- 4 new config keys: DEFAULT_QUALITY_PROFILE_ANIME, DEFAULT_QUALITY_PROFILE_ANIME_MOVIE, DEFAULT_SERVER_ANIME, DEFAULT_SERVER_ANIME_MOVIE
- isAnime flag threaded through interactions → botUtils → seerr.js and included in the Jellyseerr request payload
- Dashboard: anime quality/server selects populated alongside existing ones when loading Seerr options
* chore: bump version to 1.5.0 + CHANGELOG for anime quality profiles
* chore: CHANGELOG 1.5.0 — add all dev branch changes
* fix: npm audit fix for dev branch, bump CI to Node 20
* feat: anime library toggle in notification mapping UI
Adds a manual "Anime" checkbox to each library row in the Library
Channel Mapping section. Users can explicitly tag a Jellyfin library
as anime — explicit and robust, works with any library naming.
Config format updated from { libraryId: channelId } to
{ libraryId: { channel, isAnime } } with full backward compatibility.
Resolvers in libraryResolver.js handle both old and new formats.
New getLibraryAnimeFlag() helper exported for downstream use.
* fix: Update .gitignore
* fix: address silent-failure-hunter findings from anime library toggle
- Add console.error to all previously empty/silent catch blocks in script.js
  (library channel dropdown populate, library config parse on render,
  library config parse on save, autostart check)
- Add warn log in resolveTargetChannel when null is resolved despite
  library being in the notification list
- Refactor jellyfinWebhook.js inline library resolution to use shared
  getLibraryChannels() / resolveTargetChannel() / getLibraryAnimeFlag()
  from libraryResolver.js — eliminates logic duplication with poller/ws
- Wire getLibraryAnimeFlag() into all three notification sources
  (webhook, poller, WebSocket) and pass isAnimeLibrary through to
  processAndSendNotification — flag is now fully in the pipeline,
  logged at info level, ready for downstream use
* fix: handle legacy array format in getLibraryChannels()
Array-format JELLYFIN_NOTIFICATION_LIBRARIES was previously expanded
inline in the webhook but not in getLibraryChannels(). Now that all
three paths use the shared helper, the conversion lives there so
legacy configs work consistently across webhook, poller, and WebSocket.
* fix: eliminate all remaining silent catch blocks
- jellyfinPoller / jellyfinWebSocket: log error when targetChannelId
  resolves to null so skipped notifications are visible in logs
- jellyfinWebhook: warn in buildJellyfinUrl fallback path so
  misconfigured JELLYFIN_BASE_URL is surfaced
- web/script.js: add console.error/warn/debug to every previously
  empty catch block (version fetch, bot status, session check, webhook
  secret, localStorage cache, Seerr user load, mapping reload, role
  load, logs-page bot status) — no control flow changes, logging only
* fix: address remaining silent catch blocks and error logging gaps
- Logout catch: add console.error + showToast so user gets feedback
- loadDiscordGuilds / loadDiscordChannels: add console.error with context
- loadRoles catch: add UI fallback (allowlist/blocklist error message)
  in addition to the existing console.error
- updateConnectionStatus: add console.warn to both Seerr and Jellyfin
  catch blocks for diagnostics
- TMDB fetch catch: include error message in the log line
* fix: i18n logout error toast via t('errors.logout_failed')
Replace hardcoded English string with translation key.
Adds logout_failed to en/de/sv locale files and template.
* chore: update CHANGELOG for v1.5.0 — anime toggle + error handling
* fix: add missing anime quality/server i18n keys to all locales
en/de/sv/template were all missing config.default_anime_quality,
default_anime_quality_help, default_anime_movie_quality,
default_anime_movie_quality_help, default_anime_server,
default_anime_server_help, default_anime_movie_server,
default_anime_movie_server_help — causing raw key names to render
in the dashboard.
Also backfills missing quality/server/load_profiles_servers keys in
sv and template that were never added.
* fix: add missing i18n keys to sv and template locales
sv.json was missing next_steps_title/next_step_1-3 in config.
template.json was missing the same plus episode_channel,
episode_channel_help, season_channel, season_channel_help,
use_default_channel.
de.json is complete relative to en.json.
* feat(i18n): wire all remaining dashboard strings through translation system
Add ~80 new i18n keys covering debounce, library channel mapping, embed
customization, user mapping, role permissions, misc settings, embed colors,
and app settings sections. Wire all keys into index.html via data-i18n
attributes and update script.js to use t() for dynamically set strings
(bot control buttons, quality/server dropdowns, channel selects, anime
library labels).
* fix: apply anime detection in button-request flow
The slash-command path correctly detected isAnime and passed it to
parseQualityAndServerOptions and sendRequest, but the button handler
did not. Users clicking the request button bypassed anime-specific
quality profiles and server selection entirely.
* fix: address all silent-failure-hunter findings
- botUtils.js: replace empty catch blocks with debug/warn logging
- interactions.js: upgrade tag-fetch failures from debug to warn;
  add user-facing reply in outer interaction catch block
- script.js: check fallbackResponse.ok in loadTranslations; show
  toast on translation load failure; show toast on autostart check
  failure; add console.error + error detail to saveConfig and
  add-mapping catches; add response.ok checks before JSON parse in
  refresh-users handler
- jellyfinWebSocket.js: log stale map size after refresh failure
- jellyfinWebhook.js: include parse error in buildJellyfinUrl warning
---------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Anime and Anime Films as categories

1 participant