feat(watch): group added/removed contexts per watch entry (#912)

* feat(watch): group added/removed contexts per watch entry

- watch entries: regex string or {pattern, on:
[channels|group_added|group_removed]}
- one playlist.watch.changed per refresh with WatchChange list;
playlist.groups.changed aliased
- Telegram/ntfy message length limits
- web UI: Mapping and Watch sub pages, new Mapping icon
- ClusterFlags on create_bitset!, bitflags removed

BREAKING CHANGE: playlist.watch.changed templates must use the new
watch.* fields

* feat(watch): group added/removed contexts per watch entry

- watch entries: regex string or {pattern, on:
[channels|group_added|group_removed]}
- one playlist.watch.changed per refresh with WatchChange list;
playlist.groups.changed aliased
- Telegram/ntfy message length limits
- web UI: Mapping and Watch sub pages, new Mapping icon
- ClusterFlags on create_bitset!, bitflags removed

BREAKING CHANGE: playlist.watch.changed templates must use the new
watch.* fields
This commit is contained in:
euzu
2026-10-12 21:05:55 +02:00
committed by GitHub
parent 45c10edd3d
commit b6bab647df
45 changed files with 1981 additions and 546 deletions
+30 -12
View File
@@ -415,11 +415,10 @@ schedules:
## 5. Messaging (`messaging`)
Tuliprox can proactively notify you via Push-Notifications when updates fail, finish, or when specific channels are
added/removed
from a watched group. **Why is this useful?** Because it allows you to instantly detect upstream provider issues or
simply let you
know when new movies are added to your playlist.
Tuliprox can proactively notify you via Push-Notifications when updates fail, finish, when channels are added to or
removed from a watched group, or when watched groups appear or disappear (see
[`watch`](source.md#329-watch-watch)). **Why is this useful?** Because it allows you to instantly detect upstream
provider issues, or simply let you know when new movies or a new event group are added to your playlist.
### 5.1 Configuration & Opt-In
@@ -458,8 +457,7 @@ negative pattern does, so `["*", "!system.info"]` reads the way it looks.
| `system.shutdown` | info | The server is shutting down cleanly. |
| `playlist.update.completed` | info | A playlist update finished; carries per-source statistics. |
| `playlist.update.failed` | error | A playlist update failed. |
| `playlist.watch.changed` | info | Channels were added to or removed from a watched group. |
| `playlist.groups.changed` | info | Groups were added to or removed from a target. |
| `playlist.watch.changed` | info | Channels or groups were added to or removed from a watched target. |
| `playlist.watch.disabled` | warn | A target's watch configuration is set but not working. |
| `playlist.watch.unmatched` | warn | Watch patterns matched no group in the refreshed playlist. |
| `recording.started` | info | A recording started. |
@@ -701,11 +699,31 @@ The legacy keys below continue to work exactly as before, so existing templates
task. It includes data on memory allocation peaks, active worker threads, and non-blocking diagnostic warnings.
* **Access:** Access properties directly via dot-notation (e.g., `{{processing.memory_peak_mb}}`). Use this to
monitor system health and resource consumption during heavy mapping cycles.
* `{{watch}}`: **Change Tracking Data.** Specifically available for the `watch` event kind. It contains a diff-style
object showing exactly which groups or channels were added, removed, or modified compared to the previous state.
* **Access:** Iterate over the change sets using loops. Common keys include `added`, `removed`, and `modified`.
* **Example:** Use `{{#each watch.added}} • {{name}} {{/each}}` to list all new channels detected in the monitored
groups.
* `{{watch}}`: **Change Tracking Data.** Available for `playlist.watch.changed`. One event per target and update.
* `watch.target`: the target name.
* `watch.groups_added` / `watch.groups_removed`: `{ items, total, truncated }`, absent when there is none.
* `watch.channels_added` / `watch.channels_removed`: list of `{ group, items, total, truncated }`, absent when
there is none.
* `watch.changes`: the raw list; each entry has a `kind` (`groups_added`, `groups_removed`, `channels_added`,
`channels_removed`).
* `items` may be shorter than `total` (`truncated: true`), or empty when an update changed more than 500 channels.
* **Example:**
```handlebars
{{#if watch.groups_added}}
🆕 New groups:
{{#each watch.groups_added.items}}
• {{this}}
{{/each}}
{{/if}}
{{#each watch.channels_added}}
➕ {{group}} ({{total}}):
{{#each items}}
• {{this}}
{{/each}}
{{/each}}
```
* `{{recording}}`: **DVR Lifecycle Data.** Available for `recording_started`, `recording_completed`, and
`recording_failed`. Common fields are `programme_title`, `channel`, `effective_start`, `effective_end`,
`visibility`, `output_filename`, and `failure_reason` for failed recordings.
+30 -11
View File
@@ -1294,7 +1294,7 @@ sources:
| `output` | List | Yes | | Mandatory list of output formats. A single target can generate multiple output representations (e.g., `xtream`, `m3u`, `strm`, `hdhomerun`) from the same transformed result set. |
| `curation` | Object | No | | Optional target-wide catalog policy with Trakt and/or TMDB Trending sources. Mutually exclusive with legacy `output[].trakt`; see [target-wide curation](#target-wide-curation-curation). |
| `favourites` | List | No | | Duplicates final transformed channels into dedicated favorite groups after processing is complete. This adds curated views without changing the original group structure. |
| `watch` | List | No | | Defines watched group patterns. If matching groups change during updates, Tuliprox emits Messaging events so operational changes become observable automatically. |
| `watch` | List | No | | Watch entries for this target: channel changes in matching groups and/or matching groups that appear or disappear. Changes are reported as Messaging events; see [Watch](#329-watch-watch). |
| `use_memory_cache` | Bool | No | `false` | If enabled, the final compiled playlist is cached in RAM. This reduces disk access and improves delivery speed, especially for M3U downloads, but increases memory consumption. |
---
@@ -2279,25 +2279,44 @@ favourites:
### 3.2.9 Watch (`watch`)
For each target with a *unique name*, you can define watched groups.
It is a list of group patterns Tuliprox monitors for content changes during updates.
For each target with a *unique name*, you can define watch entries. Each entry is a regex matched against final group
names and says which changes to report:
If matching groups gain or lose channels, Tuliprox emits a Messaging event such as:
| `on` value | Reported change |
|:----------------|:---------------------------------------------------------------|
| `channels` | Channels added to or removed from a matching group. |
| `group_added` | A matching group appeared that was not in the previous update. |
| `group_removed` | A group that matched in the previous update is gone. |
* channels added
* channels removed
An entry is either a plain string, which means `on: [channels]`, or a map with `pattern` and `on`:
```yaml
watch:
- group: '^Sports'
- group: '^Movies'
# Short form: channel changes in all German sports groups.
- "^DE Sport.*"
# Report new 4K/UHD groups only.
- pattern: "(?i)\\b(4K|UHD)\\b"
on: [group_added]
# Report every group that disappears.
- pattern: ".*"
on: [group_removed]
# Event groups: appearing, disappearing and their channel changes.
- pattern: "^Event.*|^PPV.*"
on: [channels, group_added, group_removed]
```
The first update of a target only records the current state; changes are reported from the second update on. All
changes of one update arrive as a single `playlist.watch.changed` event.
A `playlist.watch.unmatched` warning is sent for entries that watch `channels` (without `group_added`) and match no
group. Entries waiting for a group to appear, or reporting only removals, never trigger it.
#### `watch` Parameters
| Parameter | Type | Required | Default | Technical Impact & Background |
|:----------|:---------------|:--------:|:--------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `group` | String (Regex) | Yes | | Regex pattern matched against final group names. This allows Tuliprox to detect meaningful content changes in selected areas of the playlist and notify operators automatically through the configured messaging backends. |
| Parameter | Type | Required | Default | Technical Impact & Background |
|:----------|:---------------|:--------:|:-------------|:----------------------------------------------------------------------|
| `pattern` | String (Regex) | Yes | | Regex matched against final group names. |
| `on` | List | No | `[channels]` | Any of `channels`, `group_added`, `group_removed`. Must not be empty. |
> **Note:** `watch` is especially useful for monitoring premium groups, VOD collections,
> or unstable provider segments where additions and removals should generate operational alerts.