ci: sync Gitea with upstream v0.8.0 #2

Merged
mcgeezy merged 3 commits from sync/github-v0.8.0 into main 2026-07-23 21:28:08 -05:00
Owner

Imports GitHub main at v0.8.0, including IPTV live-channel browsing, while preserving Gitea Actions, Python Semantic Release, Gitea-only container publishing, installer URLs, and runner networking.

User impact: Adds the v0.8.0 IPTV feature set.
Operator impact: Adds IPTV settings and local /data/iptv.sqlite3 storage; IPTV remains opt-in.
Breaking changes: None.
Tests: ruff check app tests; PYTHONPATH=app pytest -q (470 passed); git diff --check.

Imports GitHub main at v0.8.0, including IPTV live-channel browsing, while preserving Gitea Actions, Python Semantic Release, Gitea-only container publishing, installer URLs, and runner networking. User impact: Adds the v0.8.0 IPTV feature set. Operator impact: Adds IPTV settings and local /data/iptv.sqlite3 storage; IPTV remains opt-in. Breaking changes: None. Tests: ruff check app tests; PYTHONPATH=app pytest -q (470 passed); git diff --check.
mcgeezy added 3 commits 2026-07-23 21:18:25 -05:00
* docs: add IPTV research and milestone roadmap

* feat: add IPTV source catalog

* feat: add IPTV channel browsing and playback

* docs: add IPTV operator guidance

* feat(iptv): modernize channel UI with the glass design system

Rebuild the IPTV shell to match the v0.7.0 glass system used by the
remote and Jellyfin surfaces, and tighten the browse UX.

- Reskin onto shared theme tokens: brand sky/blue accent (replacing the
  bolt-on green), backdrop-blur glass panels/tabs/menus, sentence-case
  tabs, launcher aligned with the Jellyfin launcher.
- Collapse the five-tab nav (My Channels/Favorites/Hidden/Sources/
  Discover) to three (Channels/Sources/Discover); Favorites and Hidden
  become a segmented view control inside Channels.
- Redesign channel tiles: whole logo+title area is the Play target, a
  star toggles favorite, and secondary actions (Play next, Add to
  queue, Hide/Show, Check, reorder) move into a per-tile overflow menu.
  Controls sit in an in-flow column so no interactive elements nest.
- Add a live "On now" indicator on the last-played channel.
- Open Discover automatically on first run (no sources yet).
- Move the destructive "Remove unavailable" action out of the browse
  toolbar into the Sources tab.
- Include iptv.css/iptv.js in the UI asset version stamp so IPTV asset
  changes bust the browser cache.

Playwright-verified across dark/light/phone and all three tabs; smoke
script and pinned UI-markup tests updated to the new selectors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: keep live IPTV playback active during buffering

* fix: show stable live status for IPTV playback

* feat(iptv): restructure the channel shell into three focused pages

Rework the IPTV shell around three purpose-built surfaces so browsing,
finding, and managing channels each have a clear home:

- Channels: your catalog with a Channels|Favorite segmented toggle, the
  now-playing tile highlighted, a Discover shortcut in the head and at the
  foot of the list, and roomier tiles on desktop.
- Discover: browses the full catalog pulled from your sources with search,
  a group filter, a Sources shortcut, and a Refresh control. Favoriting a
  channel updates it in place and keeps your scroll position.
- Sources: an expandable "Add playlist" card, your sources (with Remove and
  Remove-unavailable) on top, and the free provider directory folded in
  below, with already-added providers marked.

Drops the separate Hidden view in favour of favorites-first curation, fixes
the overflow menu so it paints above neighbouring tiles (z-index) and lays
its items out icon-then-label (opting out of the global button span growth),
and shares now-playing/favorite state across the two channel grids.

Updates the Playwright smoke walk for the new IA (menu actions, Discover
channel browse, directory on Sources). 247 pytest pass; verified via remote
Playwright across desktop dark/light and phone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(iptv): link-driven channel shell with favorites-first My channels

Replace the tab bar with a link-and-back navigation model and simplify the
home surface:

- Remove the Channels/Discover/Sources tab nav. My channels is the home;
  Discover and Sources are reached only via links (the Discover button/foot
  link, and Discover's Sources shortcut) and left via a Back control on each
  sub-page. Escape now steps back a level before closing the shell.
- Drop the Channels|Favorite toggle. My channels shows favorites in a
  Favorites section floated to the top (fetched separately so they always
  show), then All channels below; favoriting restructures the list.
- Modernize the search fields into taller glass pills with an accent focus
  glow and a focus-lit search icon.

Updates the Playwright smoke walk (favorites-to-top, link + Back navigation)
and repins test_smoke.py to the favorites section selector. 250 pytest pass;
verified via remote Playwright across desktop dark/light and phone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(iptv): My Channels membership distinct from favorite pinning

Introduce an explicit "added to My Channels" membership so the front page is
a curated list, separate from favorite (pin-to-top):

- Add an `added` column to iptv_channels (backward-compatible ALTER for
  existing DBs; defaults off so new catalog channels are not auto-added), an
  `added_only` query filter, and `added` on the channel PATCH.
- My Channels (front page, now titled) shows only added channels — favorites
  floated to a section on top, then the rest — and its star pins/unpins.
  Favoriting is available only here.
- Discover shows the full catalog; each tile has a + (add to My Channels)
  toggle, a whole-tile play target, and the overflow menu. Adding updates the
  tile in place; the menu also offers Remove from My Channels on the front
  page. No favorite control on Discover.

Updates the Playwright smoke walk (seed as added, exercise the + toggle,
assert Discover has no favorite). 250 pytest pass; verified via remote
Playwright across desktop dark/light and phone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* style(iptv): glassy channel cards in place of flat grey

Give channel cards a layered frosted-glass surface: a top-to-bottom
translucent gradient, an inset top-edge highlight, refined borders, and a
soft lift shadow — driven by theme-aware shell-scoped tokens so the manual
light/dark toggle keeps working. The logo tile and corner chips get the same
sheen; the now-playing card carries a brand-tinted glass wash. Also flattens
the play button so its inherited global-button shadow no longer casts a seam
across the card.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(readme): add IPTV live channels + My Channels phone mockup

Introduce a "Watch it live" capability blurb and a "Live TV, curated the way
you watch" screenshot row in "See it in action", with a My Channels phone
mockup matching the existing remote/library device shots.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(readme): reshoot IPTV mockup with the live iptv-org playlist

Regenerate the My Channels phone mockup against a real IPTV playlist
(iptv-org · English) so the tiles show real channel logos — Al Jazeera, Sky
News, Bloomberg, CBS News, Euronews, France 24 — instead of placeholders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(iptv): address Codex review findings on the channel UI

- Sync the "On now" highlight from the authoritative status on every poll, so
  it is correct after reload, cross-client playback, or when playback stops —
  not only after this page's own Play action.
- Stop favorites past the first page from vanishing in My Channels: fetch more
  favorites and only drop the ones actually shown in the Favorites section from
  the main list, so any beyond the cap fall through instead of disappearing.
- Make Discover's Refresh pull fresh channels from the enabled sources before
  reloading the grid, matching the control's promise instead of only
  re-reading the local catalog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(iptv): address second Codex review pass on playback + My Channels

- Stop the interrupt-preserve path from writing credential-bearing IPTV stream
  URLs to queue.json: persist only the opaque catalog reference and the source/
  channel IDs, skip caching the resolved stream for IPTV, and let replay
  re-resolve the stream and headers from the catalog. Adds a redaction test.
- Do not mark an IPTV channel "available" just because Play launched mpv;
  launching is not proof the stream plays, so a dead or geo-blocked channel now
  keeps its warning until real probes run.
- Show all added channels in My Channels (visibility=all) so favorites and
  other members that go unavailable or lose their source still appear for the
  user to retry or remove, instead of silently vanishing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(iptv): stop history from persisting credential-bearing stream URLs

- Carry the opaque IPTV catalog references into history entries so persistence
  redacts the stream URL to iptv.invalid/<source>/<channel> and history replay
  re-resolves the stream and headers from the catalog; skip caching the
  resolved IPTV stream so no credentials reach history.json. Adds a test.
- Correct docs/IPTV_OPERATIONS.md: playing a channel no longer restores its
  availability (only an explicit or scheduled check does), matching the code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(player): stop first video's audio from persisting across queue advances

The Pi's subprocess mpv path spawned with a process-global --audio-file,
so every seamless-replace loadfile on the reused --idle=yes player
inherited the first video's external audio track and mpv kept selecting
it over each new video's own audio. Scope --audio-file and --start to
the first file with mpv's per-file --{ ... --} grouping in both spawn
arg builders (Qt shell subprocess + external mpv), so later loads define
audio purely via their per-file options. Also prevents a global resume
--start from seeking every subsequent load.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(iptv): route IPTV and header-bearing items through play_item

mpv's direct up-next handoff appends a queued item's URL to mpv without
re-resolving it or installing per-channel headers. For IPTV that both leaked
the credential-bearing stream URL to history.json/session (the rebuilt
now_item dropped iptv_source_id/iptv_channel_id, so redaction could not fire)
and, for header-protected channels, dropped the http-user-agent/http-referrer
headers and failed with 401/403.

Make IPTV and any header-bearing queue item ineligible for the direct handoff
so they go through play_item, which re-resolves the opaque catalog reference
(restoring redaction) and applies the per-channel headers. Adds a test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(iptv): source-management correctness (Codex review pass)

- Recount iptv_sources.channel_count after Remove unavailable so status and the
  Sources UI stop reporting a stale channel total.
- Exclude disabled sources from scheduled favorite checks: join iptv_sources
  and filter enabled, so disabling a source actually stops its background
  probing.
- Switch a pasted source to URL mode when a location is PATCHed in (clear
  content and set kind=url) so refresh fetches the URL instead of failing on
  now-empty pasted content.
- Keep channel identity stable when a duplicate tvg-id appears in a later
  refresh: preserve the incumbent tvg identity so favorites, My Channels
  membership, hidden state, and manual order are not detached.

Adds regression tests for all four.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(iptv): sync operator + API docs with the current IPTV UI

Update IPTV_OPERATIONS.md for the link-driven shell: My Channels is the added-
channel home with favorites pinned to the top (no separate Favorites/Hidden
views, no Include-unavailable toggle), Discover browses the full catalog with
+/Play/menu, and Sources hosts add-playlist plus the folded-in provider
directory. Note that My Channels keeps showing unavailable added channels, that
disabling a source stops its background checks, and that identity survives a
later duplicate tvg-id. Document the `added` PATCH field and `added_only`
channel filter in API.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: use install-relative paths instead of assuming /opt/relaytv

Reference the .env and data/iptv.sqlite3 files relative to the reader's RelayTV
directory rather than hardcoding /opt/relaytv, which is not the default install
location (the quick start uses ~/relaytv). Container paths (/data/iptv.sqlite3)
and the --dir install example are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(iptv): remove the planning/research doc now that IPTV has shipped

The IPTV catalog research and milestone-roadmap doc was planning-era material.
Its durable operator guidance lives in IPTV_OPERATIONS.md, the API surface in
API.md, and the design rationale in git history; its "Proposed UX" section no
longer matches the shipped link-driven UI. Nothing references it and it is not
in the docs index.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* ci(release): prepend an optional per-release highlight to release notes

The release workflow now prepends docs/release-highlights/<version>.md (when
present) above the generated GitHub Release notes, below the hero image and
under the existing overview marker. Seeds 0.8.0 with a heading introducing the
IPTV live-channels feature. Future releases can add their own highlight file;
releases without one are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(agents): document the release-highlight mechanism and PR review step

Describe docs/release-highlights/<version>.md (prepended to the GitHub Release
notes by the release workflow) under Release and Changelog Discipline, and add
a pull-request preparation step to review whether a release warrants a
highlight heading.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(player): preserve grouped media args in the external-mpv builder

_build_mpv_args now emits the media as a per-file group
(--{ ...file-opts... url --}). _build_qt_external_mpv_args assumed the last
token was the bare stream URL, so with an external audio track or a resume
position it sliced off the closing --} and re-appended the URL, leaving an
unclosed --{ group and a duplicated media URL that mpv could misparse or queue
twice. Split off and re-append the whole file spec intact.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(iptv): resilient source add and URL repoint

- Keep a newly created source when its initial refresh fails: return success
  with the retained source and a refresh_error instead of a 502, so the client
  shows the added source (with its recorded error) rather than retrying and
  creating duplicates. The add form surfaces the partial failure.
- Clear the stored ETag/Last-Modified conditional validators when a source's
  location changes, so the new URL is fully fetched instead of being 304-skipped
  against the old catalog.

Adds regression tests for both.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(iptv): SSRF guard, stale-queue skip, and duplicate-entry dedupe

- SSRF: on a token-less (open-LAN) deployment, only fetch playlist hosts that
  resolve to public addresses, re-validating every redirect hop. A configured
  RELAYTV_API_TOKEN gates source management to the operator, who may then
  target private hosts.
- Queue: a queued IPTV channel whose source was deleted or refreshed to
  inactive resolves to a 404; classify it as unplayable and skip it in every
  mode instead of reinserting it at the queue front and blocking autoplay.
- Catalog: deduplicate playlist entries that resolve to the same channel_id so
  channel_count matches the browsable catalog and no entry silently disappears.

Adds regression tests for all three.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(iptv): probe SSRF guard, identity/redirect/status hardening

- Apply the SSRF public-address guard (and guarded redirect opener) to the
  channel availability Check as well, not just playlist downloads.
- Keep a channel's identity stable when a duplicate tvg-id disappears: a
  now-unique entry whose name already holds a name: identity keeps it instead
  of upgrading to tvg: and detaching membership/favorite/rank.
- Resolve relative channel URLs against the final (post-redirect) playlist URL
  returned by _fetch_source, not the originally configured location.
- Stop reading the potentially 20 MB pasted content column during source
  listing / status polling.
- Preserve runtime telemetry gaps only for live/IPTV sessions so a crashed VOD
  player still demotes to idle instead of sticking in playing/buffering.

Adds regression tests for the probe guard, identity survival, and redirect-base
resolution.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(iptv): exclude disabled sources from Discover results

query_channels now filters discovery/browse queries (and the group list) to
enabled sources, so disabling a source removes its channels and groups from
Discover. My Channels (added_only) is unchanged: added entries from disabled
or inactive sources still appear so they can be retried or removed. Adds a
regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
chore(main): release 0.8.0 (#51)
ci / test (push) Successful in 28s
ci / docker-image (push) Failing after 31s
ddcaca9ce9
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
ci: sync Gitea with upstream v0.8.0
pr-title / validate (pull_request) Successful in 1s
ci / test (pull_request) Successful in 1m12s
ci / docker-image (pull_request) Successful in 4m1s
ci / publish-main (pull_request) Skipped
ci / test (push) Successful in 24s
ci / docker-image (push) Successful in 11s
ci / publish-main (push) Skipped
cb0d2b0aa7
mcgeezy merged commit e4bec6d821 into main 2026-07-23 21:28:08 -05:00
mcgeezy deleted branch sync/github-v0.8.0 2026-07-25 13:58:48 -05:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RelayTV/RelayTV#2