Skip to content

Detect DACH geo-restricted episodes at crawl time - #46

Merged
ChrisonSimtian merged 1 commit into
mainfrom
feat/geo-detection
Jul 26, 2026
Merged

Detect DACH geo-restricted episodes at crawl time#46
ChrisonSimtian merged 1 commit into
mainfrom
feat/geo-detection

Conversation

@ChrisonSimtian

Copy link
Copy Markdown
Contributor

What

First of three increments for #45 (geo-aware proxy egress). Surfaces each asset's broadcaster-declared geo restriction through the model so the Downloader can later route only restricted jobs through a German egress.

No behaviour change yet — the flag is detected and persisted, but nothing routes on it. That lands in PR 2 (Mode A: Download:ProxyUrl + geo-aware routing).

How

  • Detection at resolve time (both already-fetched responses, zero extra requests):
    • ARD page-gateway → mediaCollection.embedded.isGeoBlocked (bool)
    • ZDF PTMD → attributes.geoLocation.value — restricted when != "none" (e.g. "dach", "de")
  • Threaded EpisodeDetail.GeoRestrictedEpisode.GeoRestricted (persisted) via EpisodeMapper → snapshot onto DownloadJob.GeoRestricted at enqueue (rides the same rails as the existing StreamUrl/Quality snapshot).
  • EF migration AddGeoRestricted — two boolean NOT NULL DEFAULT false columns (existing rows default to false; they get re-crawled anyway).

Tests

  • Unit: EpisodeMapper carries the flag; AddDownloadByToken snapshots it onto the job.
  • Live (opt-in, ./build.cmd TestLive): the three fetch tests now assert the flag against real API data — Biene Maja (KiKA) = true, Extra 3 (ARD) / heute-show (ZDF) = false. Verified locally: Passed: 3.
  • ./build.cmd Test (deterministic) green.

Background

Why this is the right signal, and the proven bypass, are documented in #41 (investigation) and the #45 thread. Plan doc: docs/plans/2026-07-27 - geo-aware-proxy-egress.md.

… model

First increment of #45 — surface each asset's broadcaster-declared geo
restriction so the Downloader can later route only restricted jobs through a
German egress. No behaviour change yet; the flag is recorded, nothing routes.

- Read at resolve time: ARD mediaCollection.embedded.isGeoBlocked; ZDF PTMD
  attributes.geoLocation (anything != "none" = in-region-only).
- EpisodeDetail.GeoRestricted → Episode.GeoRestricted (persisted) via
  EpisodeMapper → snapshot onto DownloadJob.GeoRestricted at enqueue.
- EF migration AddGeoRestricted (two boolean NOT NULL DEFAULT false columns).
- Tests: mapper carries the flag; AddDownloadByToken snapshots it; live fetch
  tests assert real data — Biene Maja restricted, Extra 3 / heute-show not.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ChrisonSimtian
ChrisonSimtian merged commit d489295 into main Jul 26, 2026
1 check passed
@ChrisonSimtian
ChrisonSimtian deleted the feat/geo-detection branch July 26, 2026 14:19
ChrisonSimtian added a commit that referenced this pull request Jul 26, 2026
…ss proxy

Closes the #45 build (Mode A + Mode B): a geo-restricted job (flagged by the
detection landed in #46) is fetched through an in-region proxy; unrestricted
jobs still go direct. Proven live — the KiKA "Biene Maja" full download, fenced
from NZ, now completes through a DE egress.

Mode A — bring-your-own (recommended):
- Download:ProxyUrl, dialled via a dedicated proxied HttpClient in the raw-MP4
  provider (best-first fall-through across candidates) and ffmpeg (-http_proxy).
- A geo-restricted job with no egress configured fails fast with a clear message.

Mode B — opt-in auto public list:
- Proxy table + IProxyRepository (upsert preserves our probe feedback; ranked
  best-first: known-good → uptime → speed → recency) + EF migration.
- IProxyListSource → GeoNodeProxyListSource (typed HTTP client) + RefreshProxyList
  Action + ProxyRefreshService (BackgroundService, daily by default, mirrors
  CrawlSchedulerService). Real fetch outcomes feed back into ranking.
- Config Download:ProxyList:{Enabled,RefreshInterval,SourceUrl,Country,MaxCandidates}.

Shared:
- IEgressProxyProvider (Domain) selects candidates: BYO first, then ranked list.
  Options live in Domain since both App and Infra bind them.
- Activity page shows a "DACH" badge on geo-restricted jobs (DownloadJobResponse
  gains GeoRestricted). CLAUDE.md documents the config.

Tests: egress selection, GeoNode parsing, proxy ranking/upsert-preserves-feedback,
refresh handler, and the raw provider's fail-fast. App 50 / Arch 8 / Infra 67 green.
Live: KRAUTWATCH_TEST_PROXY=<de-proxy> ./build.cmd TestLive does the real KiKA pull.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ChrisonSimtian ChrisonSimtian added the enhancement New feature or request label Aug 2, 2026
@ChrisonSimtian ChrisonSimtian changed the title feat(downloads): detect DACH geo-restriction through the model (#45 · 1/3) Detect DACH geo-restricted episodes at crawl time Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant