Revise alert parameters and ghost requester logic

- UNFULFILLED_MIN_AGE_DAYS → UNFULFILLED_MIN_AGE_HOURS (default 12h)
  so new requests don't sit a full 3 days before alerting
- Incomplete Download threshold: 90% → 100% (any missing episode fires)
- PENDING_MIN_AGE_DAYS: 7 → 2
- Ghost Requester reworked: instead of checking lifetime plays = 0,
  now checks whether the user's last Tautulli activity predates their
  last N (default 5) approved requests — catches people who request
  but don't watch their recent content
- Removed Frequent Declines alert
- Add tautulliLastSeen to UserStat to support the ghost rework
- Update README to reflect all changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-12 11:34:55 -04:00
parent a8a03b59d5
commit 8fe61cdeb8
4 changed files with 102 additions and 131 deletions

View File

@@ -62,7 +62,7 @@ Alerts are generated on every stats refresh and persisted in `data/alerts.json`
### Content alerts
These are keyed per piece of media, not per user. If multiple users requested the same item, they're grouped into a single alert.
These are keyed per piece of media, not per user. If multiple users requested the same item they're grouped into a single alert.
---
@@ -72,26 +72,26 @@ These are keyed per piece of media, not per user. If multiple users requested th
| Parameter | Default | Description |
|---|---|---|
| `UNFULFILLED_MIN_AGE_DAYS` | `3` | Minimum days since approval before alerting. Prevents noise on brand-new requests. |
| `UNFULFILLED_MIN_AGE_HOURS` | `12` | Hours since approval before alerting. Prevents noise on brand-new requests. |
- Skipped entirely if Radarr reports `isAvailable: false` (unreleased) or Sonarr reports `status: "upcoming"`.
- **Auto-resolves** when the file appears (i.e. `sizeOnDisk > 0`).
- Skipped if Radarr reports `isAvailable: false` (unreleased) or Sonarr reports `status: "upcoming"`.
- **Auto-resolves** when the file appears.
- Manual close cooldown: **3 days**.
---
#### Incomplete Download
> An ended TV series has been partially downloaded (less than 90% of episodes on disk).
> An ended TV series is missing one or more episodes.
| Parameter | Default | Description |
|---|---|---|
| `UNFULFILLED_MIN_AGE_DAYS` | `3` | Same minimum age as above. |
| Completion threshold | `90%` | Series below this are flagged. Hardcoded. |
| `UNFULFILLED_MIN_AGE_HOURS` | `12` | Hours since approval before alerting. |
| Completion threshold | `100%` | Any missing episode on a finished series triggers this alert. |
- Only fires for series with `status: "ended"` in Sonarr. Continuing shows are excluded because missing episodes may simply not have aired yet.
- Percentage is calculated as `episodeFileCount / totalEpisodeCount`, not Sonarr's `percentOfEpisodes` (which counts against monitored episodes only and would be inaccurate here).
- **Auto-resolves** when completion reaches 90%+.
- Only fires for series with `status: "ended"` in Sonarr. Continuing shows are excluded because missing episodes may not have aired yet.
- Completion is calculated as `episodeFileCount / totalEpisodeCount` (not Sonarr's `percentOfEpisodes`, which measures against monitored episodes only).
- **Auto-resolves** when all episodes are on disk.
- Manual close cooldown: **3 days**.
---
@@ -102,10 +102,10 @@ These are keyed per piece of media, not per user. If multiple users requested th
| Parameter | Default | Description |
|---|---|---|
| `PENDING_MIN_AGE_DAYS` | `7` | Minimum days a request must be pending before alerting. |
| `PENDING_MIN_AGE_DAYS` | `2` | Days a request must be pending before alerting. |
- One alert per request item, not per user.
- Skipped if the content is unreleased (same availability checks as above).
- Skipped if the content is unreleased.
- **Auto-resolves** when the request is approved or declined.
- Manual close cooldown: **3 days**.
@@ -115,7 +115,7 @@ These are keyed per piece of media, not per user. If multiple users requested th
These fire once per user. Ghost Requester takes priority over Low Watch Rate — a user will only ever have one behavior alert open at a time. Both require the user to be "established" (at least one request older than `USER_MIN_AGE_DAYS`) to avoid flagging new users.
> Requires Tautulli to be configured (except Frequent Declines).
> Requires Tautulli to be configured.
| Parameter | Default | Description |
|---|---|---|
@@ -125,11 +125,13 @@ These fire once per user. Ghost Requester takes priority over Low Watch Rate —
#### Ghost Requester
> A user has made several requests but has never watched anything on Plex.
> A user hasn't watched anything on Plex since before their last N approved requests were made.
Rather than checking lifetime play counts, this looks at recency: if a user's last Plex activity predates all of their most recent N approved requests, they're not watching what they're requesting.
| Parameter | Default | Description |
|---|---|---|
| `MIN_REQUESTS_GHOST` | `5` | Minimum total requests before flagging. |
| `GHOST_RECENT_REQUESTS` | `5` | Number of recent approved requests to evaluate. Also the minimum required before the alert can fire. |
- Manual close cooldown: **14 days**.
@@ -148,20 +150,6 @@ These fire once per user. Ghost Requester takes priority over Low Watch Rate —
---
#### Frequent Declines
> A user has had multiple requests declined in a rolling window.
| Parameter | Default | Description |
|---|---|---|
| `MIN_DECLINES` | `3` | Minimum declined requests in the lookback window. |
| `DECLINE_LOOKBACK_DAYS` | `60` | Rolling window in days. |
- Does not require Tautulli.
- Manual close cooldown: **14 days**.
---
### System alerts
#### No Tautulli Watch Data