feat: prioritise and blacklist media and overview in setting page of progress in adding info
🏗️ Build Plugin / build (push) Successful in 1m16s
Latest Release / latest-release (push) Successful in 27s
🧪 Test Plugin / test (push) Successful in 20s
🚀 Release Plugin / build-and-release (push) Successful in 24s

This commit is contained in:
2026-07-04 21:08:59 +02:00
parent bb02c0f9b9
commit f6762fcf29
17 changed files with 1211 additions and 16 deletions
+98 -5
View File
@@ -114,11 +114,104 @@ have no truth data yet (neither a managed upload nor a sidecar file):
]
```
Requires an administrator API key. The sample is random and unordered, so
repeated polling naturally spreads work across the backlog without needing
server-side task tracking; an empty array means there's nothing left to do
(or every remaining item is a virtual/missing-path item that JRay can't
process).
Requires an administrator API key. The sample is random, so repeated polling
naturally spreads work across the backlog without needing server-side task
tracking; an empty array means there's nothing left to do (or every remaining
item is a virtual/missing-path item that JRay can't process).
**Prioritise/ignore rules apply here.** Items covered by an **ignore** rule are
never returned. Items covered by a **prioritise** rule are returned ahead of
un-prioritised items (still randomised within each tier). See
[Prioritise / ignore rules](#prioritise--ignore-rules) below. Rules only affect
this work-discovery endpoint — they never change the overlay or the read
endpoints, so an item you ignore for extraction still shows its overlay if truth
data happens to exist for it.
## Prioritise / ignore rules
Admins can steer the work-discovery queue with a small set of **rules**. Each
rule targets a **genre**, a **series**, or a single **item**, and either
**prioritises** (moves matching items to the front of `Tasks/Pending`) or
**ignores** them (hides them from `Tasks/Pending` entirely). This is how you
say "never extract anime", "process this series first", or "skip this one
movie".
Rule resolution for an item picks the **most specific** matching scope:
`Item` overrides `Series`, which overrides `Genre`. A rule is uniquely keyed by
its scope + value, and setting a rule for an existing scope+value **replaces**
it — so a single target can never be both prioritised and ignored. (An item can
still be pulled in two directions across scopes, e.g. a prioritised series in an
ignored genre; specificity resolves that — the series rule wins.)
Rules are persisted to `policy.json` under the plugin's configuration directory.
A rule object:
```json
{ "scope": "Genre", "value": "Anime", "action": "Ignore", "label": "Anime" }
```
- `scope`: `"Genre"`, `"Series"`, or `"Item"`.
- `value`: a genre name (for `Genre`), a series id GUID (for `Series`), or an
item id GUID (for `Item`). Genre matching is case-insensitive.
- `action`: `"Prioritise"` or `"Ignore"`.
- `label`: optional human-readable label shown in the config UI (informational).
All endpoints below require an **Administrator** API key.
### `GET /Plugins/JRay/Policy/Rules`
Returns all configured rules as a JSON array of rule objects.
### `PUT /Plugins/JRay/Policy/Rules`
Adds or replaces a rule (body is a single rule object). Replaces any existing
rule with the same `scope` + `value`. Returns `204`, or `400` if `value` is
empty.
### `DELETE /Plugins/JRay/Policy/Rules?scope={scope}&value={value}`
Removes the rule matching `scope` + `value`. Idempotent, always returns `204`.
## Coverage overview
### `GET /Plugins/JRay/Coverage`
Returns how much of the library has truth data, overall and broken down by
media type (Film vs TV) and by genre. Requires an **Administrator** API key.
```json
{
"total": { "total": 1200, "covered": 300, "pending": 850, "prioritised": 40, "ignored": 50 },
"by_media_type": [
{ "label": "Film", "counts": { "total": 400, "covered": 200, "pending": 190, "prioritised": 10, "ignored": 10 } },
{ "label": "TV", "counts": { "total": 800, "covered": 100, "pending": 660, "prioritised": 30, "ignored": 40 } }
],
"by_genre": [
{ "label": "Anime", "counts": { "total": 120, "covered": 0, "pending": 0, "prioritised": 0, "ignored": 120 } }
]
}
```
Each `counts` object buckets items as: `covered` (has truth data),
`pending` (needs processing and not ignored; `prioritised` is the subset of
`pending` under a prioritise rule), and `ignored` (excluded by an ignore rule).
`total` is the sum. A useful "percent done" is `covered / (total - ignored)`,
so ignoring a genre or series does **not** drag the percentage down — ignored
items are treated as intentionally out of scope.
An item counts toward every genre it carries, so genre rows can overlap and
their totals need not sum to the library total.
### Pickers for the config UI
Three helper endpoints populate the rule editor's dropdowns (all require an
**Administrator** API key, all return `[{ "value": ..., "label": ... }]`):
- `GET /Plugins/JRay/Coverage/Genres` — distinct genres present on movies/episodes.
- `GET /Plugins/JRay/Coverage/Series` — series in the library (`value` is the series id).
- `GET /Plugins/JRay/Coverage/Items?search={term}&limit={n}` — movies/episodes
whose name matches `term` (`value` is the item id; `limit` default 25, max
100). An empty/absent `search` returns `[]`.
## Client: pushing results from a remote extraction worker