mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 19:46:16 -08:00
fix(playlist): address bot review — no identity cross-pairing across MACs, honest caps, password in dedupe key
- 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
This commit is contained in:
3 files changed
+63
-10
No files matched your search
@@ -652,6 +652,44 @@ describe('detectProviderImportCandidates', () => {
|
||||
expect(stalker[0].deviceId2).toBeUndefined();
|
||||
});
|
||||
|
||||
it('does not cross-pair global identity labels onto multiple MACs', () => {
|
||||
// First-match-wins labels cannot say WHOSE serial/device ID they
|
||||
// are once a second MAC appears — and a device ID submitted with
|
||||
// the wrong MAC gets pinned by the portal permanently. Multi-MAC
|
||||
// candidates must therefore carry portal + MAC only.
|
||||
const candidates = detectProviderImportCandidates(
|
||||
[
|
||||
'Portal: http://multi.example.com/c/',
|
||||
'MAC: 00:1A:79:11:11:11',
|
||||
`Device ID: ${'a'.repeat(64)}`,
|
||||
'SN: AAAA1111BBBB2',
|
||||
'MAC: 00:1A:79:22:22:22',
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
const stalker = only(candidates, 'stalker');
|
||||
expect(stalker).toHaveLength(2);
|
||||
for (const candidate of stalker) {
|
||||
expect(candidate.portalUrl).toBe(
|
||||
'http://multi.example.com/c/'
|
||||
);
|
||||
expect(candidate.deviceId1).toBeUndefined();
|
||||
expect(candidate.serialNumber).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
it('surfaces every MAC of a long multi-account list', () => {
|
||||
const macs = Array.from(
|
||||
{ length: 6 },
|
||||
(_, index) => `00:1A:79:0${index}:0${index}:0${index}`
|
||||
);
|
||||
const candidates = detectProviderImportCandidates(
|
||||
['http://long.example.com/c/', ...macs].join('\n')
|
||||
);
|
||||
|
||||
expect(only(candidates, 'stalker')).toHaveLength(6);
|
||||
});
|
||||
|
||||
it('gives labeled credentials to the stalker candidate, not a competing xtream guess', () => {
|
||||
const candidates = detectProviderImportCandidates(
|
||||
[
|
||||
@@ -749,7 +787,7 @@ describe('detectProviderImportCandidates', () => {
|
||||
|
||||
expect(
|
||||
detectProviderImportCandidates(urls).length
|
||||
).toBeLessThanOrEqual(6);
|
||||
).toBeLessThanOrEqual(16);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -69,7 +69,9 @@ export interface ProviderImportCandidate {
|
||||
|
||||
const GET_PHP_PATH_PATTERN = /\/get\.php$/i;
|
||||
const EXTM3U_HEADER_PATTERN = /^\s*#EXTM3U/i;
|
||||
const MAX_CANDIDATES = 6;
|
||||
// Guard against pathological pastes, not against real handouts: multi-account
|
||||
// MAC lists with a dozen entries are legitimate and must all surface.
|
||||
const MAX_CANDIDATES = 16;
|
||||
|
||||
/**
|
||||
* Scans a pasted provider message and returns ranked import candidates.
|
||||
@@ -106,7 +108,15 @@ export function detectProviderImportCandidates(
|
||||
// ── Stalker: a MAC address is the strongest signal there is. Labeled
|
||||
// credentials attach here (Stalker portals can require a login too)
|
||||
// rather than seeding a competing Xtream guess.
|
||||
//
|
||||
// Identity fields attach ONLY when the message names exactly one account:
|
||||
// labeled extraction is first-match-wins over the whole text, so with
|
||||
// several MACs there is no reliable way to tell whose serial/device ID a
|
||||
// label belongs to — and a device ID submitted with the wrong MAC is
|
||||
// pinned by the portal permanently. Multi-MAC candidates therefore carry
|
||||
// portal + MAC only, and the user supplies identity per account.
|
||||
const portal = pickStalkerPortalUrl(urls, labeled);
|
||||
const identity: LabeledFields = macs.length === 1 ? labeled : {};
|
||||
for (const macAddress of macs) {
|
||||
candidates.push(
|
||||
compact({
|
||||
@@ -114,13 +124,13 @@ export function detectProviderImportCandidates(
|
||||
confidence: portal?.confidence ?? 'low',
|
||||
portalUrl: portal?.url,
|
||||
macAddress,
|
||||
serialNumber: labeled.serialNumber,
|
||||
deviceId1: labeled.deviceId1,
|
||||
deviceId2: labeled.deviceId2,
|
||||
signature1: labeled.signature1,
|
||||
signature2: labeled.signature2,
|
||||
username: labeled.username,
|
||||
password: labeled.password,
|
||||
serialNumber: identity.serialNumber,
|
||||
deviceId1: identity.deviceId1,
|
||||
deviceId2: identity.deviceId2,
|
||||
signature1: identity.signature1,
|
||||
signature2: identity.signature2,
|
||||
username: identity.username,
|
||||
password: identity.password,
|
||||
suggestedTitle: hostnameOf(portal?.url),
|
||||
})
|
||||
);
|
||||
@@ -322,6 +332,9 @@ function dedupe(
|
||||
candidate.url ?? '',
|
||||
candidate.serverUrl ?? '',
|
||||
candidate.username ?? '',
|
||||
// Same server + username with a DIFFERENT password is a distinct
|
||||
// account (e.g. a rotation message) — never collapse it away.
|
||||
candidate.password ?? '',
|
||||
candidate.portalUrl ?? '',
|
||||
candidate.macAddress ?? '',
|
||||
].join('|');
|
||||
|
||||
@@ -53,7 +53,9 @@ const HOSTISH_PATTERN = /^[a-z0-9][a-z0-9.-]*(?::\d{2,5})?$/i;
|
||||
const WRAPPING_CHARS = /^["'`«<([]+|["'`»>)\]]+$/g;
|
||||
|
||||
const MAX_URLS = 8;
|
||||
const MAX_MACS = 4;
|
||||
// High enough that a real multi-account handout is never silently truncated;
|
||||
// only a pathological paste (hex dumps, logs) hits it.
|
||||
const MAX_MACS = 12;
|
||||
|
||||
interface FieldMatcher {
|
||||
field: keyof LabeledFields;
|
||||
|
||||
Reference in new issue
Block a user