mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 04:40:09 +00:00
Add reported-issues, Goodreads sync & notifs
Introduce user-reported-issues and Goodreads shelf sync features and wire them into notifications. Adds Prisma migrations and schema changes (ReportedIssue, GoodreadsShelf, GoodreadsBookMapping), API endpoints for reporting (POST /audiobooks/[asin]/report-issue) and admin management (list, resolve/dismiss, replace), and an admin UI section to view/dismiss/replace reported issues. Adds a new notification event (issue_reported) with updates to notification schemas, docs and provider handling, plus a notification-events constants file. Refactors request creation to use createRequestForUser service, adds a Goodreads sync processor/service/hooks/UI modals, a scrape-resilience util, and related tests and minor integration updates.
This commit is contained in:
@@ -7,7 +7,7 @@ Sends notifications for audiobook request events (pending approval, approved, av
|
||||
|
||||
## Key Details
|
||||
- **Backends:** Apprise (API), Discord (webhooks), ntfy (API), Pushover (API)
|
||||
- **Events:** request_pending_approval, request_approved, request_available, request_error
|
||||
- **Events:** request_pending_approval, request_approved, request_available, request_error, issue_reported
|
||||
- **Encryption:** AES-256-GCM for sensitive config (webhook URLs, API keys, notification URLs)
|
||||
- **Delivery:** Async via Bull job queue (priority 5)
|
||||
- **Failure Handling:** Non-blocking, Promise.allSettled (one backend fails, others succeed)
|
||||
@@ -35,6 +35,7 @@ model NotificationBackend {
|
||||
| request_approved | Admin approves OR auto-approval | Request approved (manual or auto) |
|
||||
| request_available | Plex/ABS scan completes | Audiobook available in library |
|
||||
| request_error | Download/import fails | Request failed at any stage |
|
||||
| issue_reported | User reports issue | User reports problem with available audiobook |
|
||||
|
||||
## Notification Triggers
|
||||
|
||||
@@ -67,6 +68,10 @@ model NotificationBackend {
|
||||
- After `status: 'failed'` or `status: 'warn'` update → request_error
|
||||
- Includes error message in payload
|
||||
|
||||
**Issue Reported (reported-issue.service.ts)**
|
||||
- After user reports issue with available audiobook → issue_reported
|
||||
- Payload: issue ID (as requestId), book title/author, reporter username, reason (as message)
|
||||
|
||||
## Configuration Encryption
|
||||
|
||||
**Encrypted Values:**
|
||||
@@ -91,13 +96,14 @@ model NotificationBackend {
|
||||
- Format: Event title + book details + user + error (if applicable)
|
||||
|
||||
**Discord (Rich Embeds):**
|
||||
- Color-coded by event (yellow=pending, green=approved, blue=available, red=error)
|
||||
- Fields: Title, Author, Requested By, Error (if applicable)
|
||||
- Footer: Request ID
|
||||
- Color-coded by event (yellow=pending, green=approved, blue=available, red=error, orange=issue)
|
||||
- Fields: Title, Author, Requested/Reported By, Error/Reason (if applicable)
|
||||
- Footer: Request/Issue ID
|
||||
- Timestamp: Event time
|
||||
|
||||
**ntfy (JSON with Tags):**
|
||||
- Tags: mailbox_with_mail, white_check_mark, tada, x (rendered as emojis by ntfy)
|
||||
**ntfy (JSON Publishing to Base URL):**
|
||||
- Endpoint: POST to base `serverUrl` (default: https://ntfy.sh), topic in JSON body
|
||||
- Tags: mailbox_with_mail, white_check_mark, tada, x, triangular_flag_on_post (rendered as emojis by ntfy)
|
||||
- Priority: Default (3) for pending/approved, High (4) for available/error
|
||||
- Format: Event title + book details + user + error (if applicable)
|
||||
- Auth: Optional Bearer token via `accessToken` config field
|
||||
@@ -142,7 +148,7 @@ model NotificationBackend {
|
||||
**Modal Features:**
|
||||
- Type-first selection (user clicks "Add Discord" or "Add Pushover")
|
||||
- Password inputs for sensitive values
|
||||
- Event subscription checkboxes (4 events, default: available + error)
|
||||
- Event subscription checkboxes (5 events, default: available + error)
|
||||
- Test button (sends synchronous test notification)
|
||||
- Save button (validates and creates/updates backend)
|
||||
|
||||
|
||||
@@ -175,19 +175,19 @@ interface TorrentInfo {
|
||||
}
|
||||
|
||||
type TorrentState =
|
||||
// Core states
|
||||
// Core states (*DL = download phase, *UP = upload/post-download phase)
|
||||
| 'downloading' | 'uploading'
|
||||
| 'stalledDL' | 'stalledUP'
|
||||
| 'pausedDL' | 'pausedUP'
|
||||
| 'queuedDL' | 'queuedUP'
|
||||
| 'checkingDL' | 'checkingUP'
|
||||
| 'stalledDL' | 'stalledUP' // stalledUP → completed (download done)
|
||||
| 'pausedDL' | 'pausedUP' // pausedUP → completed (download done, paused seeding)
|
||||
| 'queuedDL' | 'queuedUP' // queuedUP → completed (download done)
|
||||
| 'checkingDL' | 'checkingUP' // checkingUP → completed (download done, rechecking)
|
||||
| 'error' | 'missingFiles' | 'allocating'
|
||||
// Forced states (user clicked "Force Resume")
|
||||
| 'forcedDL' | 'forcedUP'
|
||||
| 'forcedDL' | 'forcedUP' // forcedUP → completed (download done)
|
||||
// Metadata fetching
|
||||
| 'metaDL' | 'forcedMetaDL'
|
||||
// qBittorrent v5.0+ (renamed paused → stopped)
|
||||
| 'stoppedDL' | 'stoppedUP'
|
||||
| 'stoppedDL' | 'stoppedUP' // stoppedUP → completed (download done)
|
||||
// Other
|
||||
| 'checkingResumeData' | 'moving';
|
||||
```
|
||||
@@ -241,7 +241,13 @@ type TorrentState =
|
||||
- Adding all 8 missing states to `TorrentState` type union
|
||||
- Adding mappings to both `mapState()` (legacy) and `mapStateToDownloadStatus()` (unified interface)
|
||||
- `forcedUP` → `seeding`/`completed` enables monitor to trigger import
|
||||
- `stoppedDL`/`stoppedUP` → `paused` ensures qBittorrent v5.x compatibility
|
||||
- `stoppedDL` → `paused` ensures qBittorrent v5.x compatibility
|
||||
|
||||
**16. pausedUP/stoppedUP mapped as paused instead of completed** - RDT-Client (and qBittorrent after ratio limits) transitions directly to `pausedUP`/`stoppedUP` without passing through `uploading`/`stalledUP`. The `*UP` suffix means the download phase is complete and the torrent is on the upload side. Both states were incorrectly mapped to `'paused'`, causing the monitor to re-schedule checks indefinitely instead of triggering file organization. Fixed by:
|
||||
- `pausedUP` → `seeding` (unified) / `completed` (legacy) — triggers completion in monitor
|
||||
- `stoppedUP` → `seeding` (unified) / `completed` (legacy) — same fix for qBittorrent v5.x
|
||||
- `pausedDL`/`stoppedDL` remain `paused` — download phase genuinely paused
|
||||
- Key insight: any `*UP` state is post-download; any `*DL` state is pre-completion
|
||||
|
||||
## Tech Stack
|
||||
|
||||
|
||||
Reference in New Issue
Block a user