Commit Graph

21 Commits

Author SHA1 Message Date
Simon
0f7e27fd77 Stamp asset URLs with their content hash
index.html is revalidated on every load, but the assets it names are not
under our control once they leave the origin: Cloudflare rewrites our
`Cache-Control: no-cache` on /static/* to `max-age=14400`, so a phone --
an iOS home-screen app above all, which keeps running whatever it has --
can execute four-hour-old JavaScript after a deploy.

The URLs now carry the file's content hash (static/js/main.js?v=<hash>),
reusing the manifest /api/version already computes, so every deploy asks
for URLs no cache can answer from an old copy. index.html itself gets an
explicit no-cache, must-revalidate.

Verified: served HTML carries per-file hashes, a changed file yields a
new URL, the app boots clean, and the refresh button's update path still
hot-swaps CSS and reloads for JS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QBDkEXP4htyXTCZUwMLphd
2026-09-05 16:02:11 +00:00
Simon
d7086ead27 Play favorites from freshly resolved formats, not the page URL
Streaming a page URL makes /api/stream re-run yt-dlp on every request --
slow, and a 500 on some sites -- so the player and the reels feed now
wait for App.videos.ensureFormats() when an item has no formats
(favorites, or a card clicked before its hover-resolve landed) and play a
real media URL with the extractor's headers, the same path a hovered card
takes. Favorites' download does the same. The page URL survives only as a
last resort when resolution yields nothing.

Two things in the proxy kept this site broken either way:

heavyfetish serves media from paths with a trailing slash
(/get_file/.../11097_720p.mp4/), which missed every extension test in
stream_video and sent even a resolved media URL down the yt-dlp branch --
a full extraction per request, including every seek.

Its CDN (st17.heavyfetish.com) also serves a certificate that expired
2026-02-16, so the upstream fetch failed verification and returned 500.
A browser can't play such a host at all, which is much of why this proxy
exists, so impersonate_get() now retries once without verification, logs
it, and remembers the host so the doomed handshake isn't repeated for
every range request. STREAM_TLS_VERIFY_ONLY=1 restores the hard failure.

Verified in headless Chrome against the real site: a favorite holding
only the page URL now resolves, streams (206, video/mp4, duration
3167.8s, readyState 4, no error) and shows "720p mp4 | 480p mp4" in the
quality menu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QBDkEXP4htyXTCZUwMLphd
2026-09-05 14:26:15 +00:00
Simon
382a637b95 version updates 2026-06-24 20:54:16 +00:00
Simon
9fe7511b4d header bugfix 2026-06-24 20:08:08 +00:00
Simon
d6865d7c35 advanced probing 2026-06-23 12:44:13 +00:00
Simon
3d4b90b0e1 default impersonation on yt-dlp 2026-06-23 06:19:50 +00:00
Simon
b5b3e13dd0 live stream support 2026-06-22 12:34:47 +00:00
Simon
988e11b159 fix missing headers in video get requests 2026-06-18 11:55:08 +00:00
Simon
f8072884b2 preferred quality setting 2026-06-17 15:44:20 +00:00
Simon
d73e413352 backend improvements 2026-02-12 17:40:45 +00:00
Simon
081493d13f request information with referer 2026-02-10 17:57:59 +00:00
Simon
c2872c1883 detect m3u8 is actually mp4 2026-02-09 18:35:39 +00:00
Simon
5baca567cb beeg fixed 2026-02-09 18:27:26 +00:00
Simon
7b90c05a29 load image fallback 2026-02-09 16:28:01 +00:00
Simon
6915da7f85 improved video play 2026-02-08 20:44:36 +00:00
Simon
407e3bf9c6 improved yt-dlp 2026-02-08 20:11:07 +00:00
Simon
313ba70fec improved video streams 2026-02-08 20:08:23 +00:00
Simon
1becdce9ff favicon 2026-02-08 17:16:48 +00:00
Simon
c67a5cde16 handle application/vnd.apple.mpegurl. 2026-02-08 15:23:01 +00:00
Simon
273e7c61f3 basic functionality running 2026-01-30 11:24:19 +00:00
Simon
3a9011690c first commit 2026-01-28 16:02:57 +00:00