added chapters on player using aniskip api
This commit is contained in:
@@ -7,6 +7,10 @@ let currentExtension = '';
|
||||
let plyrInstance;
|
||||
let hlsInstance;
|
||||
let totalEpisodes = 0;
|
||||
let aniSkipData = null;
|
||||
|
||||
let isAnilist = false;
|
||||
let malId = null;
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const firstKey = params.keys().next().value;
|
||||
@@ -20,6 +24,18 @@ const href = extName
|
||||
document.getElementById('back-link').href = href;
|
||||
document.getElementById('episode-label').innerText = `Episode ${currentEpisode}`;
|
||||
|
||||
async function loadAniSkip(malId, episode, duration) {
|
||||
try {
|
||||
const res = await fetch(`https://api.aniskip.com/v2/skip-times/${malId}/${episode}?types[]=op&types[]=ed&episodeLength=${duration}`);
|
||||
if (!res.ok) return null;
|
||||
const data = await res.json();
|
||||
return data.results || [];
|
||||
} catch (error) {
|
||||
console.error('Error loading AniSkip data:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMetadata() {
|
||||
try {
|
||||
const extQuery = extName ? `?source=${extName}` : "?source=anilist";
|
||||
@@ -40,11 +56,8 @@ async function loadMetadata() {
|
||||
let format = '';
|
||||
let seasonYear = '';
|
||||
let season = '';
|
||||
let episodesCount = 0;
|
||||
let characters = [];
|
||||
|
||||
if (isAnilistFormat) {
|
||||
|
||||
title = data.title.romaji || data.title.english || data.title.native || 'Anime Title';
|
||||
description = data.description || 'No description available.';
|
||||
coverImage = data.coverImage?.large || data.coverImage?.medium || '';
|
||||
@@ -62,6 +75,14 @@ async function loadMetadata() {
|
||||
seasonYear = data.year || '';
|
||||
}
|
||||
|
||||
if (isAnilistFormat && data.idMal) {
|
||||
isAnilist = true;
|
||||
malId = data.idMal;
|
||||
} else {
|
||||
isAnilist = false;
|
||||
malId = null;
|
||||
}
|
||||
|
||||
document.getElementById('anime-title-details').innerText = title;
|
||||
document.getElementById('anime-title-details2').innerText = title;
|
||||
document.title = `Watching ${title} - Ep ${currentEpisode}`;
|
||||
@@ -106,6 +127,102 @@ async function loadMetadata() {
|
||||
}
|
||||
}
|
||||
|
||||
async function applyAniSkip(video) {
|
||||
if (!isAnilist || !malId) {
|
||||
console.log('AniSkip disabled: isAnilist=' + isAnilist + ', malId=' + malId);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Loading AniSkip for MAL ID:', malId, 'Episode:', currentEpisode);
|
||||
|
||||
aniSkipData = await loadAniSkip(
|
||||
malId,
|
||||
currentEpisode,
|
||||
Math.floor(video.duration)
|
||||
);
|
||||
|
||||
console.log('AniSkip data received:', aniSkipData);
|
||||
|
||||
if (!aniSkipData || aniSkipData.length === 0) {
|
||||
console.log('No AniSkip data available');
|
||||
return;
|
||||
}
|
||||
|
||||
let op, ed;
|
||||
const markers = [];
|
||||
|
||||
aniSkipData.forEach(item => {
|
||||
const { startTime, endTime } = item.interval;
|
||||
|
||||
if (item.skipType === 'op') {
|
||||
op = { start: startTime, end: endTime };
|
||||
markers.push({
|
||||
start: startTime,
|
||||
end: endTime,
|
||||
label: 'Opening'
|
||||
});
|
||||
|
||||
console.log('Opening found:', startTime, '-', endTime);
|
||||
}
|
||||
|
||||
if (item.skipType === 'ed') {
|
||||
ed = { start: startTime, end: endTime };
|
||||
markers.push({
|
||||
start: startTime,
|
||||
end: endTime,
|
||||
label: 'Ending'
|
||||
});
|
||||
|
||||
console.log('Ending found:', startTime, '-', endTime);
|
||||
}
|
||||
});
|
||||
|
||||
// Crear markers visuales en el DOM
|
||||
if (plyrInstance && markers.length > 0) {
|
||||
console.log('Creating visual markers:', markers);
|
||||
|
||||
// Esperar a que el player esté completamente cargado
|
||||
setTimeout(() => {
|
||||
const progressContainer = document.querySelector('.plyr__progress');
|
||||
if (!progressContainer) {
|
||||
console.error('Progress container not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Eliminar markers anteriores si existen
|
||||
const oldMarkers = progressContainer.querySelector('.plyr__markers');
|
||||
if (oldMarkers) oldMarkers.remove();
|
||||
|
||||
// Crear contenedor de markers
|
||||
const markersContainer = document.createElement('div');
|
||||
markersContainer.className = 'plyr__markers';
|
||||
|
||||
markers.forEach(marker => {
|
||||
const markerElement = document.createElement('div');
|
||||
markerElement.className = 'plyr__marker';
|
||||
markerElement.dataset.label = marker.label;
|
||||
|
||||
const startPercent = (marker.start / video.duration) * 100;
|
||||
const widthPercent = ((marker.end - marker.start) / video.duration) * 100;
|
||||
|
||||
markerElement.style.left = `${startPercent}%`;
|
||||
markerElement.style.width = `${widthPercent}%`;
|
||||
|
||||
markerElement.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
video.currentTime = marker.start;
|
||||
});
|
||||
|
||||
markersContainer.appendChild(markerElement);
|
||||
});
|
||||
|
||||
|
||||
progressContainer.appendChild(markersContainer);
|
||||
console.log('Visual markers created successfully');
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadExtensionEpisodes() {
|
||||
try {
|
||||
const extQuery = extName ? `?source=${extName}` : "?source=anilist";
|
||||
@@ -117,7 +234,6 @@ async function loadExtensionEpisodes() {
|
||||
if (Array.isArray(data) && data.length > 0) {
|
||||
populateEpisodeCarousel(data);
|
||||
} else {
|
||||
|
||||
const fallback = [];
|
||||
for (let i = 1; i <= totalEpisodes; i++) {
|
||||
fallback.push({ number: i, title: null, thumbnail: null });
|
||||
@@ -132,6 +248,8 @@ async function loadExtensionEpisodes() {
|
||||
|
||||
function populateEpisodeCarousel(episodesData) {
|
||||
const carousel = document.getElementById('episode-carousel');
|
||||
if (!carousel) return;
|
||||
|
||||
carousel.innerHTML = '';
|
||||
|
||||
episodesData.forEach((ep, index) => {
|
||||
@@ -319,9 +437,8 @@ function playVideo(url, subtitles = []) {
|
||||
|
||||
if (plyrInstance) plyrInstance.destroy();
|
||||
|
||||
while (video.textTracks.length > 0) {
|
||||
video.removeChild(video.textTracks[0]);
|
||||
}
|
||||
const existingTracks = video.querySelectorAll('track');
|
||||
existingTracks.forEach(track => track.remove());
|
||||
|
||||
subtitles.forEach(sub => {
|
||||
if (!sub.url) return;
|
||||
@@ -337,7 +454,15 @@ function playVideo(url, subtitles = []) {
|
||||
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'],
|
||||
settings: ['captions', 'quality', 'speed']
|
||||
settings: ['captions', 'quality', 'speed'],
|
||||
markers: {
|
||||
enabled: true,
|
||||
points: []
|
||||
}
|
||||
});
|
||||
|
||||
video.addEventListener('loadedmetadata', () => {
|
||||
applyAniSkip(video);
|
||||
});
|
||||
|
||||
let alreadyTriggered = false;
|
||||
@@ -353,7 +478,6 @@ function playVideo(url, subtitles = []) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
video.play().catch(() => console.log("Autoplay blocked"));
|
||||
}
|
||||
|
||||
@@ -382,7 +506,6 @@ if (currentEpisode <= 1) {
|
||||
document.getElementById('prev-btn').disabled = true;
|
||||
}
|
||||
|
||||
|
||||
async function sendProgress() {
|
||||
const token = localStorage.getItem('token');
|
||||
if (!token) return;
|
||||
@@ -415,7 +538,5 @@ async function sendProgress() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
loadMetadata();
|
||||
loadExtensions();
|
||||
|
||||
loadExtensions();
|
||||
Reference in New Issue
Block a user