Without trustProxies(), Laravel didn't know requests arriving via
Traefik were originally HTTPS, so route()/url() generated http://
links (stream/proxy, vtt-proxy, etc.), which browsers block as mixed
content on the HTTPS page. Also corrected APP_URL in Coolify's env
vars from http://localhost/ to https://animexe.com.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
proxyUrl() in player.blade.php listed aniziumserver.sbs/site/com in
DIRECT_CORS_HOSTS, so it unwrapped the server's /stream/proxy URLs and
tried loading them directly from the browser. That CORS assumption is
no longer true (confirmed via browser console), which silently undid
the PlayerController fix from the previous commit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
videoSourcesData (quality/dub failover list) wasn't routed through
stream.proxy, so switching quality/dub hit Anizium's CDN directly and
got blocked by CORS. aniziumserver.sbs was also wrongly whitelisted as
CORS-safe in isOwn — it isn't, per browser console evidence.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Optional "opacity" per entry for visual emphasis; values below 0.4 are raised to
the readable floor so links can vary in prominence but cannot be hidden.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stray extra quote after the milliol.com URL made the file invalid JSON,
so json_decode failed and the footer silently rendered no partner links.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reads resources/data/partners.json (url/anchor/title/rel), cached by the file's
mtime so edits go live on the next deploy. Skips invalid/non-http entries and
renders nothing when the list is empty.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The player pings /track/watch every 30s with the CUMULATIVE position, and each
ping inserted a new row (~18 rows per viewing, 254k/day). SUM(seconds_watched)
therefore summed cumulative snapshots: a single 58-minute viewing reported as
4238 minutes (~73x), skewing TrendingController's watch-minute ranking and the
admin "total_sec"/"plays" figures.
Upsert per (session_id, episode_id) so SUM is the real watch time and COUNT is
the real play count. Adds the supporting index.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Media responses carried Laravel session cookies (Set-Cookie), which made
Cloudflare BYPASS the cache for every cover/avatar/banner. These are public
files with no user context, so the session/cookie/CSRF chain is unnecessary.
Also skips BotDetector (one analytics_bot_logs INSERT per image) and the SEO
redirect lookup.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Resolve hosts to IPs and reject private/reserved/link-local ranges (incl.
169.254 cloud metadata) instead of matching hostname text, and re-validate
every redirect hop by following them manually. Restrict curl to http(s).
vtt-proxy allowlist now requires an exact host or a real subdomain.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>