v1.5.9 (Actuel)

This commit is contained in:
2026-09-15 21:56:10 +02:00
parent c21cd3ab5e
commit bff992aa4a
56 changed files with 3404 additions and 327 deletions
+4 -6
View File
@@ -11,10 +11,8 @@ function isSeriesIdentifier(identifier: string): boolean {
export class FreeTeleAPI implements ISource {
name = 'freetel';
displayName = 'Free-Télécharger';
private baseUrl: string | undefined;
constructor(baseUrl?: string) {
this.baseUrl = baseUrl?.replace(/\/$/, '');
get baseUrl() {
return CONFIG.FT_URL?.replace(/\/$/, '');
}
async healthCheck(): Promise<boolean> {
@@ -114,7 +112,7 @@ export class FreeTeleAPI implements ISource {
let hostUrl: string | null = null;
// Cas série : page intermédiaire liens.free-telecharger.cam/SLUG-episode_N
if (linkId.includes('liens.free-telecharger.cam')) {
if (linkId.includes('liens.free-telecharger.')) {
try {
const html = await fetchPage(linkId);
const hosts = parseEpisodeLinks(html);
@@ -139,4 +137,4 @@ export class FreeTeleAPI implements ISource {
}
}
sourceRegistry.register(new FreeTeleAPI(CONFIG.FT_URL));
sourceRegistry.register(new FreeTeleAPI());
+25 -5
View File
@@ -64,9 +64,17 @@ function detectType(href: string): 'movie' | 'series' | 'anime' {
}
function absUrl(url: string, baseUrl: string): string {
if (url.startsWith('http')) return url;
let path = url;
if (url.startsWith('http')) {
try {
const u = new URL(url);
path = u.pathname + u.search + u.hash;
} catch {
return url;
}
}
const cleanedBase = baseUrl.replace(/\/$/, '');
return cleanedBase + '/' + url.replace(/^\//, '');
return cleanedBase + '/' + path.replace(/^\//, '');
}
/**
@@ -83,9 +91,15 @@ export function parseSearchResults(html: string, baseUrl: string): SearchResult[
const href = absUrl(hrefRaw, baseUrl);
const title = m[3]!.replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();
if (!title) continue;
let year: string | null = null;
const yearMatch = title.match(/\(\s*(\d{4})\s*\)/) || hrefRaw.match(/-(\d{4})-/);
if (yearMatch) {
year = yearMatch[1];
}
results.push({
title,
year: null,
year,
image,
hrefPath: href,
type: detectType(hrefRaw),
@@ -106,9 +120,15 @@ export function parseTrendingResults(html: string, baseUrl: string): SearchResul
const hrefRaw = m[1]!;
const title = m[2]!.trim();
const image = absUrl(m[3]!, baseUrl);
let year: string | null = null;
const yearMatch = title.match(/\(\s*(\d{4})\s*\)/) || hrefRaw.match(/-(\d{4})-/);
if (yearMatch) {
year = yearMatch[1];
}
results.push({
title,
year: null,
year,
image,
hrefPath: absUrl(hrefRaw, baseUrl),
type: detectType(hrefRaw),
@@ -127,7 +147,7 @@ export function parseContentHTML(html: string, isSeries: boolean): ContentLinks
const links: VideoLink[] = [];
if (isSeries) {
const episodeRegex = /<input[^>]+name="lien"\s+value="(https?:\/\/liens\.free-telecharger\.cam\/[^"]+)"/gi;
const episodeRegex = /<input[^>]+name="lien"\s+value="(https?:\/\/liens\.free-telecharger\.[a-z]+\/[^"]+)"/gi;
let m: RegExpExecArray | null;
let idx = 0;
while ((m = episodeRegex.exec(html)) !== null) {