- normalizeXtreamServerUrl strips panel_api.php like the other API
endpoints, so a panel_api.php handout (pasted or auto-detected) prefills
the server base instead of a URL the transport would double-suffix.
- The multi-MAC portal ambiguity key is origin plus the installation base
path: tenant installs sharing one origin (/a/stalker_portal/c/ vs /b/...)
no longer collapse, while alternate endpoints of one install (/c/,
portal.php, server/load.php, Real/Panel pairs) still compare equal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
Addresses Copilot's suppressed review comments:
- The m3u-url candidate card no longer shows a get.php password in clear —
the display masks the query value while the untouched URL still prefills
the form.
- A picked candidate is dropped if the user switches to another method
before its target form mounts, so it cannot lie in wait and prefill a
later visit.
- The parser contract now names its one assembled-value exception
(labeledHostUrl completing a scheme-less host with http:// and a labeled
port).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
- The MAC and candidate caps are raised to 64/96: they exist to keep a
pathological paste (a log full of MAC-shaped hex) from rendering thousands
of cards, not to bound real handouts — scanner dumps top out around a
couple dozen accounts, so no real multi-account message is truncated.
- The multi-MAC portal ambiguity guard compares URL origins instead of
hostnames, so two panels on one DNS name but different ports no longer
cross-pair; URL normalization drops default ports, keeping the Real/Panel
':80'-vs-bare pairs of scanner dumps unambiguous.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
The round-2 guard judged ambiguity over portal-shaped URLs only, while the
portal picker falls back to a generic URL when no shaped one exists — two
root-URL panels with several MACs still cross-paired through that fallback.
The guard now inspects the exact pool the picker draws from.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
- Several MACs meeting portal-shaped URLs on different hosts now yield
MAC-only candidates: there is no deterministic owner for either portal, and
prefilling half the accounts with the wrong panel only fails later at
authentication. Same-host Real/Panel pairs and one portal shared by a MAC
list stay unambiguous.
- The URL scanner cap is raised to match the candidate cap (16), so a
nine-link handout is no longer truncated to eight before assembly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
- Multi-MAC messages no longer attach globally scanned serial/device-ID/
signature/credential labels to every MAC: with several accounts in one
message there is no reliable owner for a first-match label, and a device ID
submitted with the wrong MAC is pinned by the portal permanently. Identity
fields now attach only when exactly one MAC is present.
- MAC and candidate caps raised (12/16) so real multi-account lists are never
silently truncated; the caps remain only as pathological-paste guards.
- The candidate dedupe key includes the password, so two accounts sharing a
server and username (e.g. a rotation message) both stay selectable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
Second corpus batch (14 real reseller messages; 11 already parsed). New:
- Bare 'URL, token, token' handouts with no labels at all become a
low-confidence Xtream guess — only when the message contains exactly those
three lines, a single generic URL, and no label/MAC produced anything.
- Separator-less serials ('SN 38415545307A3') are accepted when the value is
hex-shaped, so prose cannot match.
- The dual device-ID marker now allows any symbol between 1 and 2 (¹💥², 1/2)
and whitespace-only label separators, again guarded by the hex value shape.
- A separately labeled port completes a port-less 'Portal: http://host' URL.
Nine messages from the batch join the test corpus verbatim.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
Extends the deterministic detector for three real reseller message shapes:
- Negative-circled / squared / regional-indicator 'font' capitals and circled
digits (🅤🅢🅔🅡, 🅜➌🅤) that NFKC leaves alone are folded to the ASCII they
depict before scanning, so decorated USER/PASS/URL labels are recognized.
- 'DEVICE ID=> 1&2 <hex>' hands one hex value to both device-ID slots.
- 'S N', 'S/N', 'S.N' serial labels, the Turkish 'MAC ADRESİ' label, and a
guard so 'ADULT PASS' (the parental PIN) is not read as the account password.
All three pasted messages are covered verbatim by new parser tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
Reseller messages dress labels in Unicode math alphabets and arrow
separators to slip past chat spam filters. The detector now NFKC-normalizes
the pasted text before scanning, so decorated labels fold back to the plain
ASCII the vocabulary matches, and accepts arrow/geometric/dingbat glyphs,
'>' and a space-surrounded dash as label separators alongside ':' and '='.
A hyphen glued inside a word stays prose, so hyphenated words are still not
read as labeled values.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4
Adds a deterministic parser (detectProviderImportCandidates in
libs/shared/interfaces) that scans a pasted provider message for URLs, MAC
addresses, and labeled credentials/identity fields (username, password,
serial, device IDs, signatures), classifies the source as Xtream, Stalker,
or an M3U link/body, and returns ranked candidates. Every extracted value is
a verbatim substring or a canonical form from an existing shared normalizer;
detection only proposes — the existing forms and their behavioral probes
(portal discovery, connection test) stay authoritative.
The Add playlist dialog gains a sixth "Auto-detect" method with a textarea
that runs the parser on every edit and renders candidate cards; picking one
switches to the matching import form with the fields prefilled.
Detection runs fully locally; pasted text never leaves the app.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE1De2dfyRZMYh4H2iGXb4