diff --git a/firetv/store/capture.sh b/firetv/store/capture.sh index 5aabf5e..27e8e75 100755 --- a/firetv/store/capture.sh +++ b/firetv/store/capture.sh @@ -6,30 +6,46 @@ # /search: real artwork and real titles (Mighty Oaks Daily Devotional, The # Harry Sisson Show) were in the listing, and we hold no licence to any of it. # -# So the grid comes from /tv-preview, which renders the real card grid with -# invented shows and no image URLs — then draws its own letter tile for -# every square. The app is a WebView of exactly this site at exactly this size, -# so a headless capture is what the TV shows, without needing the Android SDK. +# Both shots therefore come from /tv-preview, which renders the real card grid +# with invented shows and no image URLs, so draws its own typographic +# tile for every square. The app is a WebView of this site at this size, so a +# headless capture is what the TV shows, without needing the Android SDK. # -# Usage (defaults to production): -# sh firetv/store/capture.sh [BASE_URL] +# Three things that are not obvious, each found the hard way: +# +# * NOT the home page. Below its hero it shows the "deep catalogues" row, +# which is real cover art - and two of those shows are the ones Amazon +# named. /tv-preview?hero=1 gives the same hero with our own grid instead. +# * NOT /search either, even with no query: it carries a sponsored ad and +# names a real third-party domain in its help text. +# * Point BASE at the app container, not at the public hostname. p0dcasters +# answers a headless browser with its own x402 paywall ("You have used up +# the free allowance") after 20 requests an hour, and you will screenshot +# that instead. A browser user agent is still needed: the default +# HeadlessChrome string is treated as a crawler. +# +# Usage: +# sh firetv/store/capture.sh # the dev2 app container +# sh firetv/store/capture.sh http://127.0.0.1:PORT set -eu -BASE=${1:-https://p0dcasters.com} +BASE=${1:-http://127.0.0.1:3235} OUT=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)/shots +UA="Mozilla/5.0 (X11; CrKey armv7l 1.5.16041) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" mkdir -p "$OUT" shot() { # shot - docker run --rm --network host -v "$OUT:/out" -w /out \ - --entrypoint chromium-browser zenika/alpine-chrome:124 \ - --headless --no-sandbox --disable-gpu --hide-scrollbars \ - --window-size=1920,1080 --virtual-time-budget=12000 \ - --screenshot="/out/$1.png" "$BASE$2" >/dev/null 2>&1 + docker run --rm --memory 3g --shm-size 1g --network host \ + -v "$OUT:/out" -w /out --entrypoint chromium-browser \ + zenika/alpine-chrome:124 \ + --headless --no-sandbox --disable-gpu --disable-dev-shm-usage \ + --hide-scrollbars --window-size=1920,1080 --virtual-time-budget=15000 \ + --user-agent="$UA" --screenshot="/out/$1.png" "$BASE$2" echo "$1.png <- $BASE$2" } -shot 01-home / +shot 01-hero "/tv-preview?hero=1" shot 02-grid /tv-preview echo -echo "Check both by eye before uploading: no cover art that is not ours, no real show titles." -ls -l "$OUT"/01-home.png "$OUT"/02-grid.png +echo "Look at both before uploading: no cover art that is not ours, no real show titles." +ls -l "$OUT" diff --git a/firetv/store/listing.md b/firetv/store/listing.md index d9a671f..e82f43d 100644 --- a/firetv/store/listing.md +++ b/firetv/store/listing.md @@ -49,7 +49,7 @@ podcasts, podcast player, radio, live tv, p0dcasters, podcasters, rss, free podc | Icon 512x512 / 114x114 | out/icon-512.png, out/icon-114.png | | Fire TV icon 1280x720 | out/firetv-icon-1280x720.png | | Fire TV background 1920x1080 | out/firetv-background-1920x1080.png | -| Screenshots 1920x1080 | shots/01-home.png, 02-grid.png, 03-keyboard.png | +| Screenshots 1920x1080 | shots/01-hero.png, shots/02-grid.png | ### Screenshots must not carry anyone else's artwork diff --git a/firetv/store/shots/01-hero.png b/firetv/store/shots/01-hero.png new file mode 100644 index 0000000..0149508 Binary files /dev/null and b/firetv/store/shots/01-hero.png differ diff --git a/firetv/store/shots/02-grid.png b/firetv/store/shots/02-grid.png new file mode 100644 index 0000000..8697b60 Binary files /dev/null and b/firetv/store/shots/02-grid.png differ diff --git a/src/app/tv-preview/page.tsx b/src/app/tv-preview/page.tsx index 4ae45e0..bbeeaad 100644 --- a/src/app/tv-preview/page.tsx +++ b/src/app/tv-preview/page.tsx @@ -38,7 +38,16 @@ const SAMPLE: Array & { days: const DAY = 86_400; -export default function TvPreviewPage() { +export default async function TvPreviewPage({ + searchParams, +}: { + searchParams: Promise<{ hero?: string }>; +}) { + // ?hero=1 adds the real hero above the grid, for the first store screenshot. + // The home page cannot be used for one: below its hero it shows the "deep + // catalogues" row, which is real cover art, and two of those shows are the + // ones Amazon named in the rejection. + const hero = (await searchParams).hero === "1"; const now = Math.floor(Date.now() / 1000); const shows = SAMPLE.map((s, i) => ({ id: i + 1, @@ -65,7 +74,24 @@ export default function TvPreviewPage() { })) as unknown as Podcast[]; return ( -
+ <> + {hero && ( +
+
+

Every podcast with a feed — on any host.

+

+ 390,000 live shows, read from their RSS feeds: shows on their own domain, + shows on every hosting platform, and the big library networks. Free, no + account, listen on your TV. +

+
+ + +
+
+
+ )} +

Browse every show

@@ -74,6 +100,7 @@ export default function TvPreviewPage() { ))}
-
+
+ ); }