mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 03:56:15 -08:00
fix(stalker): rediscover after benign html endpoints
This commit is contained in:
1 parent
c1f7306ed5
commit
4317380137
2 files changed
+89
-7
No files matched your search
+67
-7
@@ -335,6 +335,60 @@ describe('StalkerEndpointResolver', () => {
|
||||
).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('advances after a benign HTML endpoint-shape miss and promotes the next valid endpoint', async () => {
|
||||
const harness = createHarness((request) => {
|
||||
const action = request.params?.['action'];
|
||||
if (request.mode === STALKER_HTTP_REQUEST_MODES.Anonymous) {
|
||||
return success({}, { finalUrl: request.url });
|
||||
}
|
||||
if (
|
||||
request.url.endsWith('/server/load.php') &&
|
||||
action === 'handshake'
|
||||
) {
|
||||
return rawSuccess(
|
||||
'<!doctype html><html><body>Portal landing</body></html>',
|
||||
{
|
||||
contentType: 'text/html; charset=utf-8',
|
||||
finalUrl: request.url,
|
||||
}
|
||||
);
|
||||
}
|
||||
if (action === 'handshake') {
|
||||
return success(
|
||||
{ js: { token: 'html-fallback-token' } },
|
||||
{ finalUrl: request.url }
|
||||
);
|
||||
}
|
||||
if (action === 'get_profile') {
|
||||
return success(
|
||||
{ js: { status: 0 } },
|
||||
{ finalUrl: request.url }
|
||||
);
|
||||
}
|
||||
throw new Error('Unexpected request');
|
||||
});
|
||||
|
||||
const outcome = await harness.resolver.resolve({
|
||||
descriptor: descriptor(),
|
||||
transport,
|
||||
});
|
||||
|
||||
expect(outcome).toMatchObject({
|
||||
endpoint: 'https://portal.test/portal.php',
|
||||
kind: 'full-session',
|
||||
});
|
||||
expect(
|
||||
harness.calls.filter(
|
||||
(request) => request.params?.['action'] === 'handshake'
|
||||
)
|
||||
).toHaveLength(2);
|
||||
expect(
|
||||
harness.calls.some(
|
||||
(request) => request.params?.['action'] === 'get_genres'
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('continues after early stateless evidence so a later full endpoint wins', async () => {
|
||||
const harness = createHarness((request) => {
|
||||
const action = request.params?.['action'];
|
||||
@@ -479,13 +533,19 @@ describe('StalkerEndpointResolver', () => {
|
||||
handshakeUrls.push(request.url);
|
||||
}
|
||||
if (request.url.includes('/learned/')) {
|
||||
return success(
|
||||
{},
|
||||
{
|
||||
finalUrl: request.url,
|
||||
status: unsupportedStatus,
|
||||
}
|
||||
);
|
||||
return unsupportedStatus === 404
|
||||
? rawSuccess('<html><body>Not found</body></html>', {
|
||||
contentType: 'text/html',
|
||||
finalUrl: request.url,
|
||||
status: unsupportedStatus,
|
||||
})
|
||||
: success(
|
||||
{},
|
||||
{
|
||||
finalUrl: request.url,
|
||||
status: unsupportedStatus,
|
||||
}
|
||||
);
|
||||
}
|
||||
if (action === 'handshake') {
|
||||
return success(
|
||||
|
||||
@@ -470,6 +470,9 @@ function normalizeProtocolOutcome(
|
||||
return failure(STALKER_FAILURE_REASONS.IncompatibleResponse, false);
|
||||
}
|
||||
if (parsed.kind === 'unparsed') {
|
||||
if (isBenignHtmlEndpointMiss(outcome.result, parsed.rawBody)) {
|
||||
return { kind: 'miss' };
|
||||
}
|
||||
return failure(
|
||||
parsed.reason,
|
||||
parsed.reason !== STALKER_FAILURE_REASONS.IncompatibleResponse
|
||||
@@ -522,6 +525,25 @@ function parseTransportEnvelope(
|
||||
: { kind: 'unparsed', rawBody, reason: parsed.reason };
|
||||
}
|
||||
|
||||
function isBenignHtmlEndpointMiss(
|
||||
result: StalkerTransportResult<Uint8Array>,
|
||||
rawBody: string | undefined
|
||||
): boolean {
|
||||
const mediaType = result.contentType
|
||||
?.split(';', 1)[0]
|
||||
?.trim()
|
||||
.toLowerCase();
|
||||
if (mediaType !== 'text/html' && mediaType !== 'application/xhtml+xml') {
|
||||
return false;
|
||||
}
|
||||
const prefix = rawBody?.trimStart().slice(0, 64).toLowerCase() ?? '';
|
||||
return (
|
||||
prefix.startsWith('<!doctype html') ||
|
||||
prefix.startsWith('<html') ||
|
||||
prefix.startsWith('<?xml')
|
||||
);
|
||||
}
|
||||
|
||||
function boundedNonEmptyString(value: unknown): string | undefined {
|
||||
if (
|
||||
typeof value !== 'string' ||
|
||||
|
||||
Reference in new issue
Block a user