Improve API error handling and refresh README response examples

This commit is contained in:
Md Tahseen Hussain
2026-04-03 19:52:19 +05:30
parent aa265aa6bb
commit d663dff0d6
3 changed files with 87 additions and 31 deletions

View File

@@ -104,6 +104,54 @@ class AnimePahe {
return animeSession;
}
/**
* Convert noisy upstream errors into concise API-safe messages
* @param {string} context - Operation context (search, episodes, etc)
* @param {Error|any} error - Raw error
* @returns {string} Public error message
* @private
*/
_formatUpstreamError(context, error) {
const rawMessage = String(error?.message || error || 'Unknown error');
const statusMatch = rawMessage.match(/^(\d{3})\s*-\s*/);
const statusCode = statusMatch ? parseInt(statusMatch[1], 10) : null;
if (statusCode === 404 || /Oops\.\.\.\s*404|404\s+Not\s+Found/i.test(rawMessage)) {
if (context === 'episodes') {
return 'Anime session not found. Use /search first to get a valid session id.';
}
if (context === 'sources') {
return 'Anime or episode session not found. Use /episodes first to get a valid episode_session.';
}
if (context === 'ids') {
return 'Anime session not found. Use /search first to get a valid session id.';
}
}
if (statusCode === 403 && /ddos-guard|checking your browser|cloudflare/i.test(rawMessage)) {
return 'Upstream blocked the request (anti-bot challenge). Please retry shortly.';
}
let cleaned = rawMessage
.replace(/<script[\s\S]*?<\/script>/gi, ' ')
.replace(/<style[\s\S]*?<\/style>/gi, ' ')
.replace(/<[^>]+>/g, ' ')
.replace(/\s+/g, ' ')
.replace(/^\d{3}\s*-\s*"?/, '')
.replace(/"$/, '')
.trim();
if (!cleaned) {
cleaned = 'Unexpected upstream error';
}
if (cleaned.length > 220) {
cleaned = `${cleaned.slice(0, 220)}...`;
}
return cleaned;
}
/**
* Search for anime by query
* @param {string} query - Search query
@@ -138,7 +186,7 @@ class AnimePahe {
return results;
} catch (error) {
throw new Error(`Search failed: ${error.message}`);
throw new Error(`Search failed: ${this._formatUpstreamError('search', error)}`);
}
}
@@ -208,7 +256,7 @@ class AnimePahe {
return formattedEpisodes;
} catch (error) {
throw new Error(`Failed to get episodes: ${error.message}`);
throw new Error(`Failed to get episodes: ${this._formatUpstreamError('episodes', error)}`);
}
}
@@ -288,7 +336,7 @@ class AnimePahe {
return uniqueSources;
} catch (error) {
throw new Error(`Failed to get sources: ${error.message}`);
throw new Error(`Failed to get sources: ${this._formatUpstreamError('sources', error)}`);
}
}
@@ -394,7 +442,7 @@ ${transformedScript}
throw new Error(`Could not resolve .m3u8. Node output (first 2000 chars):\n${nodeOutput.substring(0, 2000)}`);
} catch (error) {
throw new Error(`Failed to resolve Kwik URL: ${error.message}`);
throw new Error(`Failed to resolve Kwik URL: ${this._formatUpstreamError('m3u8', error)}`);
}
}
@@ -419,7 +467,7 @@ ${transformedScript}
myanimelist: malId ? parseInt(malId, 10) : null
};
} catch (error) {
throw new Error(`Failed to get IDs: ${error.message}`);
throw new Error(`Failed to get IDs: ${this._formatUpstreamError('ids', error)}`);
}
}