fix(feedback): freeomovie posters + dead hoster + myvidplay; watchporn _embed_iframe guard
From user bug reports (8f8c10c0 freeomovie, c156e4b7/8db71220 watchporn scene): freeomovie (app/connectors/freeomovie.py): - Parse the detail-page poster (<img class="rmbd">); RawMovie was built with no poster_url, so title-only orphans (no canonical match) rendered blank cards. Re-ingest backfilled existing blanks 11 -> 1. - _host_label now returns the registrable domain (parts[-2]) not the subdomain, so video.player4me.xyz labels as 'player4me' (was garbage 'freeomovie:video'). - Skip player4me (JS-SPA, no known resolver); pruned 28 dead freeomovie:video sources. - myvidplay.com added to mobile DOOD_HOSTS (doodstream.ts): it 301s to playmogo.com (doodcdn clone), so it now routes to the native dood resolver instead of a dead WebView. watchporn: the reported 4 duplicate/broken quality rows were the API process serving a STALE extractor registry (never restarted after the re-enable deploy) -> _embed_iframe scraped 2 tokenless get_file (403) + 2 preview trailers (404). The running api now serves the native extractor (2 clean playing links, verified). Hardened _embed_iframe to skip preview/videos_screenshots clips and tokenless get_file so this class can't recur. Also: DonateScreen em-dashes -> commas/semicolon (no-em-dash rule). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
393dbe548a
commit
0c18472a15
5 changed files with 38 additions and 6 deletions
|
|
@ -50,9 +50,16 @@ _LIST_ITEM_RE = re.compile(
|
|||
)
|
||||
_TABS_RE = re.compile(r"var\s+TABS\s*=\s*(\[.*?\])\s*;", re.DOTALL)
|
||||
_ARTICLE_SECTION_RE = re.compile(r'"articleSection"\s*:\s*"([^"]+)"')
|
||||
# Poster: <img class="... rmbd ..." src="..."> (fastpic.org itp.). Bez tego film-orphan
|
||||
# (tytuł bez matchu do canonical) miał poster_url=None → pusty kafelek (report 8f8c10c0).
|
||||
_POSTER_RE = re.compile(
|
||||
r'<img[^>]+class="[^"]*\brmbd\b[^"]*"[^>]+src="(https?://[^"]+)"',
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
# Hostery pomijane (martwe/flaky).
|
||||
_SKIP_HOSTS = ("streamtape", "mxdrop", "mixdrop", "streamsb")
|
||||
# Hostery pomijane (martwe/flaky). player4me = JS-SPA bez znanego resolvera (28 martwych
|
||||
# źródeł freeomovie:video, report 8f8c10c0).
|
||||
_SKIP_HOSTS = ("streamtape", "mxdrop", "mixdrop", "streamsb", "player4me")
|
||||
|
||||
|
||||
def _host_label(embed_url: str) -> str | None:
|
||||
|
|
@ -60,7 +67,9 @@ def _host_label(embed_url: str) -> str | None:
|
|||
if not host:
|
||||
return None
|
||||
parts = host.replace("www.", "").split(".")
|
||||
return parts[0] if parts else None
|
||||
# Rejestrowalna domena (SLD), nie subdomena: video.player4me.xyz → 'player4me' (nie
|
||||
# 'video'), myvidplay.com → 'myvidplay'. Inaczej origin był śmieciowy (freeomovie:video).
|
||||
return parts[-2] if len(parts) >= 2 else parts[0]
|
||||
|
||||
|
||||
class FreeoMovieConnector(BaseMovieConnector):
|
||||
|
|
@ -177,11 +186,15 @@ class FreeoMovieConnector(BaseMovieConnector):
|
|||
if not playback:
|
||||
return None # bez playbacku film jest bezużyteczny (nie tworzymy orphana)
|
||||
|
||||
pm = _POSTER_RE.search(detail)
|
||||
poster_url = html.unescape(pm.group(1)) if pm else None
|
||||
|
||||
slug = urlparse(url).path.strip("/").split("/")[-1]
|
||||
return RawMovie(
|
||||
external_id=slug,
|
||||
title=title,
|
||||
url=url,
|
||||
poster_url=poster_url,
|
||||
tags=tags,
|
||||
playback_sources=playback,
|
||||
raw={"source": "freeomovie", "url": url},
|
||||
|
|
|
|||
|
|
@ -283,6 +283,15 @@ def _extract_direct_stream_urls(page_html: str, page_url: str) -> list[StreamSou
|
|||
# i embed pages z .mp4 suffix (playmogo/dood /d/ — to HTML, nie video).
|
||||
if _NOT_DIRECT_STREAM_RE.search(url):
|
||||
continue
|
||||
# KVS false-positives (report c156e4b7/8db71220, watchporn przez _embed_iframe):
|
||||
# preview_/videos_screenshots to krótkie trailery (404), a surowy get_file/ bez
|
||||
# podpisanego query-tokena daje 403 — kt_player dokłada token z license_code (patrz
|
||||
# natywny watchporn.extract). Żadne z nich to pełne wideo → pomijamy.
|
||||
low = url.lower()
|
||||
if "videos_screenshots/" in low or "/preview_" in low:
|
||||
continue
|
||||
if "/get_file/" in low and "?" not in url:
|
||||
continue
|
||||
# Quality wykrycie z nazwy pliku
|
||||
q_int = 0
|
||||
q_label = "mp4"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,13 @@ export type ChangelogEntry = {
|
|||
};
|
||||
|
||||
export const CHANGELOG: ChangelogEntry[] = [
|
||||
{
|
||||
id: '2026-07-03',
|
||||
date: 'July 2026',
|
||||
items: [
|
||||
'Movie posters show up again (freeomovie), and more of its sources actually play (myvidplay).',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '2026-07-02b',
|
||||
date: 'July 2026',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ const DOOD_HOSTS = new Set([
|
|||
'ds2play.com', 'ds2video.com',
|
||||
'd000d.com', 'd0o0d.com', 'do0od.com', 'do7go.com',
|
||||
'dooood.com', 'd0000d.com',
|
||||
// myvidplay.com: 301 -> playmogo.com (doodcdn clone). Najczęstszy hoster freeomovie
|
||||
// (63 filmy); bez tego isDoodStream() false -> WebView -> nie gra (report 8f8c10c0).
|
||||
'myvidplay.com',
|
||||
]);
|
||||
|
||||
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36';
|
||||
|
|
|
|||
|
|
@ -33,12 +33,12 @@ export function DonateScreen() {
|
|||
<Text style={styles.footnoteTitle}>Why crypto?</Text>
|
||||
<Text style={styles.footnoteBody}>
|
||||
Mainstream payment processors (Stripe, PayPal, Patreon) refuse adult
|
||||
projects — even open-source tooling like this one. Crypto is the only
|
||||
projects, even open-source tooling like this one. Crypto is the only
|
||||
channel that does not require us to identify our donors and does not
|
||||
let third parties freeze the project mid-month.
|
||||
</Text>
|
||||
<Text style={[styles.footnoteBody, { marginTop: 10 }]}>
|
||||
Monero is privacy-preserving by design — if you care about not being
|
||||
Monero is privacy-preserving by design; if you care about not being
|
||||
linked to this app on-chain, send XMR. Bitcoin and USDT are public
|
||||
ledgers; use a fresh wallet if anonymity matters to you.
|
||||
</Text>
|
||||
|
|
@ -83,7 +83,7 @@ function CoinCard({ coin }: { coin: DonateCoin }) {
|
|||
{placeholder ? (
|
||||
<View style={styles.placeholderBox}>
|
||||
<Text style={styles.placeholderText}>
|
||||
Address not configured yet — see{' '}
|
||||
Address not configured yet, see{' '}
|
||||
<Text style={{ color: theme.muted, fontWeight: '700' }}>mobile/src/lib/donate.ts</Text>
|
||||
</Text>
|
||||
</View>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue