refactor: extract error and logging helper

This commit is contained in:
WebStreamr 2025-07-24 08:16:40 +00:00
parent b15d93eca8
commit cc3dacdd76
No known key found for this signature in database
2 changed files with 68 additions and 67 deletions

View file

@ -1,3 +1,12 @@
import winston from 'winston';
import { BlockedReason, Context } from '../types';
import { BlockedError } from './BlockedError';
import { HttpError } from './HttpError';
import { QueueIsFullError } from './QueueIsFullError';
import { TimeoutError } from './TimeoutError';
import { TooManyRequestsError } from './TooManyRequestsError';
import { TooManyTimeoutsError } from './TooManyTimeoutsError';
export * from './BlockedError';
export * from './HttpError';
export * from './NotFoundError';
@ -5,3 +14,58 @@ export * from './QueueIsFullError';
export * from './TimeoutError';
export * from './TooManyRequestsError';
export * from './TooManyTimeoutsError';
export const logErrorAndReturnNiceString = (ctx: Context, logger: winston.Logger, source: string, error: unknown): string => {
if (error instanceof BlockedError) {
if (error.reason === BlockedReason.cloudflare_challenge) {
logger.warn(`${source}: Request was blocked via Cloudflare challenge.`, ctx);
} else if (error.reason === BlockedReason.cloudflare_censor) {
logger.warn(`${source}: Request was censored by Cloudflare.`, ctx);
} else if (error.reason === BlockedReason.media_flow_proxy_auth) {
return '⚠️ MediaFlow Proxy authentication failed. Please set the correct password.';
} else {
logger.warn(`${source}: Request was blocked, headers: ${JSON.stringify(error.headers)}.`, ctx);
}
return `⚠️ Request was blocked. Reason: ${error.reason}`;
}
if (error instanceof TooManyRequestsError) {
logger.warn(`${source}: Rate limited for ${error.retryAfter} seconds.`, ctx);
return '🚦 Request was rate-limited. Please try again later or consider self-hosting.';
}
if (error instanceof TooManyTimeoutsError) {
logger.warn(`${source}: Too many timeouts.`, ctx);
return '🚦 Too many recent timeouts. Please try again later.';
}
if (error instanceof TimeoutError) {
logger.warn(`${source}: Request timed out.`, ctx);
return '🐢 Request timed out.';
}
if (error instanceof QueueIsFullError) {
logger.warn(`${source}: Request queue is full.`, ctx);
return '⏳ Request queue is full. Please try again later or consider self-hosting.';
}
if (error instanceof HttpError) {
logger.error(`${source}: HTTP status ${error.status} (${error.statusText}), headers: ${JSON.stringify(error.headers)}, stack: ${error.stack}.`, ctx);
if (error.status >= 500) {
return `❌ Remote server has issues. We can't fix this, please try later again.`;
}
return `❌ Request failed with status ${error.status} (${error.statusText}). Request-id: ${ctx.id}.`;
}
const cause = (error as Error & { cause?: unknown }).cause;
logger.error(`${source} error: ${error}, cause: ${cause}, stack: ${(error as Error).stack}`, ctx);
return `❌ Request failed. Request-id: ${ctx.id}.`;
};

View file

@ -1,18 +1,10 @@
import bytes from 'bytes';
import { ContentType, Stream } from 'stremio-addon-sdk';
import winston from 'winston';
import {
BlockedError,
HttpError,
NotFoundError,
QueueIsFullError,
TimeoutError,
TooManyRequestsError,
TooManyTimeoutsError,
} from '../error';
import { logErrorAndReturnNiceString, NotFoundError } from '../error';
import { ExtractorRegistry } from '../extractor';
import { Source } from '../source';
import { BlockedReason, Context, Format, UrlResult } from '../types';
import { Context, Format, UrlResult } from '../types';
import { showExternalUrls } from './config';
import { envGetAppName } from './env';
import { Id } from './id';
@ -72,7 +64,7 @@ export class StreamResolver {
streams.push({
name: envGetAppName(),
title: [`🔗 ${handler.label}`, this.logErrorAndReturnNiceString(ctx, handler.id, error)].join('\n'),
title: [`🔗 ${handler.label}`, logErrorAndReturnNiceString(ctx, this.logger, handler.id, error)].join('\n'),
externalUrl: ctx.hostUrl.href,
});
}
@ -171,61 +163,6 @@ export class StreamResolver {
return name;
};
private logErrorAndReturnNiceString(ctx: Context, source: string, error: unknown): string {
if (error instanceof BlockedError) {
if (error.reason === BlockedReason.cloudflare_challenge) {
this.logger.warn(`${source}: Request was blocked via Cloudflare challenge.`, ctx);
} else if (error.reason === BlockedReason.cloudflare_censor) {
this.logger.warn(`${source}: Request was censored by Cloudflare.`, ctx);
} else if (error.reason === BlockedReason.media_flow_proxy_auth) {
return '⚠️ MediaFlow Proxy authentication failed. Please set the correct password.';
} else {
this.logger.warn(`${source}: Request was blocked, headers: ${JSON.stringify(error.headers)}.`, ctx);
}
return `⚠️ Request was blocked. Reason: ${error.reason}`;
}
if (error instanceof TooManyRequestsError) {
this.logger.warn(`${source}: Rate limited for ${error.retryAfter} seconds.`, ctx);
return '🚦 Request was rate-limited. Please try again later or consider self-hosting.';
}
if (error instanceof TooManyTimeoutsError) {
this.logger.warn(`${source}: Too many timeouts.`, ctx);
return '🚦 Too many recent timeouts. Please try again later.';
}
if (error instanceof TimeoutError) {
this.logger.warn(`${source}: Request timed out.`, ctx);
return '🐢 Request timed out.';
}
if (error instanceof QueueIsFullError) {
this.logger.warn(`${source}: Request queue is full.`, ctx);
return '⏳ Request queue is full. Please try again later or consider self-hosting.';
}
if (error instanceof HttpError) {
this.logger.error(`${source}: HTTP status ${error.status} (${error.statusText}), headers: ${JSON.stringify(error.headers)}, stack: ${error.stack}.`, ctx);
if (error.status >= 500) {
return `❌ Remote server has issues. We can't fix this, please try later again.`;
}
return `❌ Request failed with status ${error.status} (${error.statusText}). Request-id: ${ctx.id}.`;
}
const cause = (error as Error & { cause?: unknown }).cause;
this.logger.error(`${source} error: ${error}, cause: ${cause}, stack: ${(error as Error).stack}`, ctx);
return `❌ Request failed. Request-id: ${ctx.id}.`;
};
private buildTitle(ctx: Context, urlResult: UrlResult): string {
const titleLines = [];
@ -241,7 +178,7 @@ export class StreamResolver {
titleLines.push(titleDetailsLine.join(' '));
if (urlResult.error) {
titleLines.push(this.logErrorAndReturnNiceString(ctx, urlResult.sourceId, urlResult.error));
titleLines.push(logErrorAndReturnNiceString(ctx, this.logger, urlResult.sourceId, urlResult.error));
}
return titleLines.join('\n');