Conversation
…tored add - New Listenarr.Domain.Notifications.NotificationTriggers: central catalog of the full book lifecycle (acquisition + library-management) trigger names, with display metadata + default-enabled set (single source of truth vs. magic strings). - GET /api/v1/notifications/triggers serves the catalog (frontend will render from it). - Fire book-wanted (in addition to book-added) when a monitored book is added, on both the service and API add paths. First increment of the comprehensive lifecycle-notification feature. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ion pipeline Expand notifications from the four historical triggers to a backend-served catalog covering the whole acquisition + library lifecycle, so integrations (Discord/NTFY/Slack/custom scripts) can subscribe to any stage. New trigger fire points (all gated by the global enabled-trigger set): - book-wanted / book-added LibraryAddService + LibraryAddWorkflow (add + monitored) - book-grabbed / book-downloading DownloadService (at client submission) - book-download-completed / book-download-failed DownloadMonitorService - book-imported ImportFinalizationService (post-commit) - book-import-failed DownloadProcessingJobProcessor (terminal failure incl. retry exhaustion) - book-available ScanJobProcessor (existing; now uses the constant) - book-completed MoveJobProcessor (post-move/organize) - book-renamed RenameService (per successful rename) - book-deleted LibraryDeleteWorkflow (single-item delete) Foundation: - NotificationTriggers catalog (id/label/description/order) is the single source of truth; NotificationsController exposes GET /notifications/triggers. - IBookLifecycleNotifier facade resolves settings and dispatches to the configured webhook + enabled-trigger gate (best-effort; swallows non-fatal errors). - ApplicationSettings default now derives from NotificationTriggers.DefaultEnabled, intentionally the historical four so upgrades emit no new notification types unless the user opts in. - Discord content builder is data-driven, giving every trigger a friendly message instead of a raw "[trigger]" fallback. - book-upgraded reserved (documented) but not catalogued: no reliable upgrade-completion signal exists in the import path yet. Frontend: NotificationsTab consumes GET /notifications/triggers (single source of truth) with a seeded fallback; trigger list/order/labels/icons follow the catalog. Tests: catalog integrity, controller endpoint, notifier dispatch/error-swallowing, and per-trigger Discord content phrasing. Backend build + architecture gates green; fe type-check green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ing files Completes the reserved book-upgraded trigger. The import processor now takes a pre-import file count for the audiobook (before ImportDownloadFilesAsync mutates anything); a successful import into a book that already had files is a replacement/upgrade rather than a first import. That boolean is persisted on the job (alongside SourceRetained, so it survives the FilesImported checkpoint on a resume) and threaded into ImportFinalizationService.FinalizeAsync, which fires book-upgraded right after book-imported. - NotificationTriggers: book-upgraded is now catalogued (order 55, between Imported and Available) so the settings UI can subscribe to it. Left out of DefaultEnabled (opt-in), consistent with the back-compat policy. - No grab-time quality decision is persisted, so this is the "replaced an existing book's files" proxy rather than a strict quality comparison — which for Listenarr's automatic acquisition (it only re-grabs on an allowed upgrade) is an upgrade in practice. Documented as such. Tests: FinalizeAsync fires book-upgraded when wasUpgrade is true and not on a first import; catalog test updated to assert book-upgraded is now catalogued. Build + arch gates green; 103 download-processing/notification tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Summary
Expands notifications from the four historical triggers to a backend-served catalog covering the whole acquisition + library lifecycle, so integrations (Discord / NTFY / Slack / custom scripts) can subscribe to any stage of a book's journey. The backend is the single source of truth; the settings UI reads the catalog instead of hardcoding trigger lists.
Trigger fire points
All gated by the global enabled-trigger set (
ApplicationSettings.EnabledNotificationTriggers) via a smallIBookLifecycleNotifierfacade.book-added/book-wantedLibraryAddService+LibraryAddWorkflow(on add;book-wantedwhen monitored)book-grabbed/book-downloadingDownloadService(at client submission)book-download-completed/book-download-failedDownloadMonitorServicebook-importedImportFinalizationService(post-commit)book-import-failedDownloadProcessingJobProcessor(terminal failure, incl. retry exhaustion)book-availableScanJobProcessor(existing; now uses the shared constant)book-completedMoveJobProcessor(post-move/organize)book-renamedRenameService(per successful rename)book-deletedLibraryDeleteWorkflow(single-item delete)Foundation
NotificationTriggerscatalog (id / label / description / order) — single source of truth.GET /notifications/triggersserves it.IBookLifecycleNotifierresolves settings and dispatches to the configured webhook + enabled-trigger gate; best-effort (swallows non-fatal errors, re-throws cancellation).NotificationTriggers.DefaultEnabled— intentionally the historical four (book-added,book-downloading,book-available,book-completed) so an upgrade emits no new notification types unless the user opts in.[trigger]fallback.book-upgradedis reserved (documented constant) but deliberately not catalogued: the import path has no reliable upgrade-completion signal yet (a replacement is indistinguishable from a first import), and this PR avoids advertising a trigger that never fires.Frontend
NotificationsTab.vuefetchesGET /notifications/triggersand drives the trigger list / order / labels / icons from it, with a seeded fallback so the form still renders if the request fails.Tests
IsKnown, reserved-upgraded not catalogued)Backend build + architecture gates green (file-focus + test-class conventions);
fetype-check green.Notes
🤖 Generated with Claude Code