fixes for extension sources & tweaks

This commit is contained in:
2025-11-29 22:11:42 +01:00
parent 655ab9c987
commit 7625c52017
17 changed files with 1103 additions and 463 deletions

View File

@@ -6,6 +6,7 @@ let audioMode = 'sub';
let currentExtension = '';
let plyrInstance;
let hlsInstance;
let totalEpisodes = 0;
const params = new URLSearchParams(window.location.search);
const firstKey = params.keys().next().value;
@@ -21,42 +22,130 @@ document.getElementById('episode-label').innerText = `Episode ${currentEpisode}`
async function loadMetadata() {
try {
const res = await fetch(`/api/anime/${animeId}`);
const extQuery = extName ? `?ext=${extName}` : "";
const res = await fetch(`/api/anime/${animeId}${extQuery}`);
const data = await res.json();
if(!data.error) {
const title = data.title.english || data.title.romaji;
document.getElementById('anime-title').innerText = title;
document.title = `Watching ${title} - Ep ${currentEpisode}`;
if (!data.error) {
const romajiTitle = data.title.romaji || data.title.english || 'Anime Title';
document.getElementById('anime-title').innerText = romajiTitle;
document.title = `Watching ${romajiTitle} - Ep ${currentEpisode}`;
document.getElementById('detail-anime-title').innerText = romajiTitle;
const tempDiv = document.createElement('div');
tempDiv.innerHTML = data.description || 'No description available.';
document.getElementById('detail-description').innerText =
tempDiv.textContent || tempDiv.innerText;
document.getElementById('detail-format').innerText = data.format || '--';
document.getElementById('detail-score').innerText =
data.averageScore ? `${data.averageScore}%` : '--';
const season = data.season
? data.season.charAt(0) + data.season.slice(1).toLowerCase()
: '';
document.getElementById('detail-season').innerText =
data.seasonYear ? `${season} ${data.seasonYear}` : '--';
document.getElementById('detail-cover-image').src =
data.coverImage.large || data.coverImage.medium || '';
if (!extName) {
totalEpisodes = data.episodes || 0;
} else {
try {
const res2 = await fetch(`/api/anime/${animeId}/episodes${extQuery}`);
const data2 = await res2.json();
totalEpisodes = Array.isArray(data2) ? data2.length : 0;
} catch (e) {
console.error("Error cargando episodios por extensión:", e);
totalEpisodes = 0;
}
}
populateEpisodeSelectors(totalEpisodes);
if (currentEpisode >= totalEpisodes && totalEpisodes > 0) {
document.getElementById('next-btn').disabled = true;
}
}
} catch(e) { console.error(e); }
} catch (error) {
console.error('Error loading metadata:', error);
}
}
function populateEpisodeSelectors(count) {
const list = document.getElementById('episode-list');
list.innerHTML = '';
for (let i = 1; i <= count; i++) {
const extParam = extName ? `?${extName}` : "";
const btn = document.createElement('a');
btn.href = `/watch/${animeId}/${i}${extParam}`;
btn.classList.add('episode-btn');
btn.dataset.episode = i;
btn.innerText = i;
if (i === currentEpisode) {
btn.classList.add('active-ep');
}
list.appendChild(btn);
}
}
function filterEpisodes() {
const searchInput = document.getElementById('episode-search');
const filter = searchInput.value.toUpperCase().trim();
const episodeList = document.getElementById('episode-list');
const buttons = episodeList.getElementsByClassName('episode-btn');
for (let i = 0; i < buttons.length; i++) {
const episodeNumber = buttons[i].dataset.episode;
if (episodeNumber.startsWith(filter) || filter === "") {
buttons[i].style.display = "";
} else {
buttons[i].style.display = "none";
}
}
}
async function loadExtensions() {
try {
const res = await fetch('/api/extensions');
const res = await fetch('/api/extensions/anime');
const data = await res.json();
const select = document.getElementById('extension-select');
if (data.extensions && data.extensions.length > 0) {
select.innerHTML = '';
data.extensions.forEach(ext => {
const opt = document.createElement('option');
opt.value = opt.innerText = ext;
select.appendChild(opt);
});
if (data.extensions.includes(extName ?? "")) {
if (typeof extName === 'string' && data.extensions.includes(extName)) {
select.value = extName;
currentExtension = extName;
onExtensionChange();
} else {
select.selectedIndex = 0;
}
currentExtension = select.value;
onExtensionChange();
} else {
select.innerHTML = '<option>No Extensions</option>';
select.disabled = true;
setLoading("No extensions found in WaifuBoards folder.");
setLoading("No anime extensions found.");
}
} catch(e) {
console.error("Extension Error:", e);
} catch (error) {
console.error("Extension Error:", error);
}
}
@@ -66,7 +155,7 @@ async function onExtensionChange() {
setLoading("Fetching extension settings...");
try {
const res = await fetch(`/api/extension/${currentExtension}/settings`);
const res = await fetch(`/api/extensions/${currentExtension}/settings`);
const settings = await res.json();
const toggle = document.getElementById('sd-toggle');
@@ -93,9 +182,8 @@ async function onExtensionChange() {
}
loadStream();
} catch (err) {
console.error(err);
} catch (error) {
console.error(error);
setLoading("Failed to load extension settings.");
}
}
@@ -113,6 +201,7 @@ function setAudioMode(mode) {
const dubOpt = document.getElementById('opt-dub');
toggle.setAttribute('data-state', mode);
if (mode === 'sub') {
subOpt.classList.add('active');
dubOpt.classList.remove('active');
@@ -128,7 +217,7 @@ async function loadStream() {
const serverSelect = document.getElementById('server-select');
const server = serverSelect.value || "default";
setLoading(`Searching & Resolving Stream (${audioMode})...`);
setLoading(`Loading stream (${audioMode})...`);
try {
const url = `/api/watch/stream?animeId=${animeId.slice(0, 30)}&episode=${currentEpisode}&server=${server}&category=${audioMode}&ext=${currentExtension}`;
@@ -146,21 +235,18 @@ async function loadStream() {
}
const source = data.videoSources.find(s => s.type === 'm3u8') || data.videoSources[0];
const headers = data.headers || {};
let proxyUrl = `/api/proxy?url=${encodeURIComponent(source.url)}`;
let proxyUrl = `/api/proxy?url=${encodeURIComponent(source.url)}`;
if (headers['Referer']) proxyUrl += `&referer=${encodeURIComponent(headers['Referer'])}`;
if (headers['Origin']) proxyUrl += `&origin=${encodeURIComponent(headers['Origin'])}`;
if (headers['User-Agent']) proxyUrl += `&userAgent=${encodeURIComponent(headers['User-Agent'])}`;
playVideo(proxyUrl, data.videoSources[0].subtitles);
document.getElementById('loading-overlay').style.display = 'none';
} catch (err) {
setLoading("Stream Error. Check console.");
console.error(err);
} catch (error) {
setLoading("Stream error. Check console.");
console.error(error);
}
}
@@ -169,6 +255,7 @@ function playVideo(url, subtitles) {
if (Hls.isSupported()) {
if (hlsInstance) hlsInstance.destroy();
hlsInstance = new Hls({
xhrSetup: (xhr, url) => {
xhr.withCredentials = false;
@@ -193,30 +280,52 @@ function playVideo(url, subtitles) {
track.label = sub.language;
track.srclang = sub.language.slice(0, 2).toLowerCase();
track.src = sub.url;
if (sub.default || sub.language.toLowerCase().includes('english')) {
track.default = true;
}
video.appendChild(track);
});
}
plyrInstance = new Plyr(video, {
captions: { active: true, update: true, language: 'en' },
controls: ['play-large', 'play', 'progress', 'current-time', 'duration', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen'],
captions: {
active: true,
update: true,
language: 'en'
},
controls: [
'play-large',
'play',
'progress',
'current-time',
'duration',
'mute',
'volume',
'captions',
'settings',
'pip',
'airplay',
'fullscreen'
],
settings: ['captions', 'quality', 'speed']
});
video.play().catch(e => console.log("Auto-play blocked"));
video.play().catch(error => {
console.log("Autoplay blocked:", error);
});
}
function setLoading(msg) {
function setLoading(message) {
const overlay = document.getElementById('loading-overlay');
const text = document.getElementById('loading-text');
overlay.style.display = 'flex';
text.innerText = msg;
text.innerText = message;
}
const extParam = extName ? `?${extName}` : "";
document.getElementById('prev-btn').onclick = () => {
if (currentEpisode > 1) {
window.location.href = `/watch/${animeId}/${currentEpisode - 1}${extParam}`;
@@ -226,7 +335,10 @@ document.getElementById('prev-btn').onclick = () => {
document.getElementById('next-btn').onclick = () => {
window.location.href = `/watch/${animeId}/${currentEpisode + 1}${extParam}`;
};
if(currentEpisode <= 1) document.getElementById('prev-btn').disabled = true;
if (currentEpisode <= 1) {
document.getElementById('prev-btn').disabled = true;
}
loadMetadata();
loadExtensions();