comments, fixes
This commit is contained in:
parent
d442580c72
commit
72502368b2
134
autoindex.js
134
autoindex.js
@ -19,7 +19,7 @@ const arrow = `
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
`
|
`;
|
||||||
|
|
||||||
function reencodeURI(uri) {
|
function reencodeURI(uri) {
|
||||||
return encodeURIComponent(decodeURIComponent(uri));
|
return encodeURIComponent(decodeURIComponent(uri));
|
||||||
@ -35,10 +35,17 @@ function findByHref(href) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findWholeNumberInText(text, matchNumber) {
|
||||||
|
const numbers = text.match(/\d+/g);
|
||||||
|
return numbers
|
||||||
|
&& numbers.length
|
||||||
|
&& numbers.map((x) => parseInt(x, 10)).some((number) => number === matchNumber);
|
||||||
|
}
|
||||||
|
|
||||||
function findByInfoFile(infoFile) {
|
function findByInfoFile(infoFile) {
|
||||||
const found = ['avi', 'mp4', 'mkv'].reduce((last, current) => {
|
const found = ['mkv', 'mp4', 'avi'].reduce((last, current) => {
|
||||||
const element = findByHref(infoFile.replace(infoRegex, '.' + current))[0];
|
const element = findByHref(infoFile.replace(infoRegex, '.' + current))[0];
|
||||||
return element ? element : last;
|
return element || last;
|
||||||
}, null);
|
}, null);
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
@ -69,38 +76,10 @@ async function createXMLRequest(nfo) {
|
|||||||
.then((str) => parser.parseFromString(str, 'text/xml'));
|
.then((str) => parser.parseFromString(str, 'text/xml'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function createOrImproveMovieMeta(original, thumbnail, nfo) {
|
// Fill metadata boxes, generate buttons
|
||||||
let imgTag = `<img class="thumbnail" src="${thumbnail ? reencodeURI(getHref(thumbnail)) : ''}"/>`;
|
function fillMeta(
|
||||||
let movieTitle = `<div class="movie-title">${original.innerText}</div>`;
|
content, original, nfo, movieTitle, movieDescription, movieButtons
|
||||||
let movieDescription = `<div class="movie-description"></div>`;
|
) {
|
||||||
let movieButtons = `<div class="movie-buttons"></div>`;
|
|
||||||
|
|
||||||
if (!thumbnail && !nfo) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (original.parentElement.classList.contains('enhanced')) {
|
|
||||||
imgTag = original.querySelector('.thumbnail');
|
|
||||||
movieTitle = original.querySelector('.movie-title');
|
|
||||||
movieDescription = original.querySelector('.movie-description');
|
|
||||||
movieButtons = original.querySelector('.movie-buttons');
|
|
||||||
if (thumbnail) {
|
|
||||||
imgTag.src = reencodeURI(getHref(thumbnail));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
original.classList.add('movie');
|
|
||||||
original.innerHTML = imgTag + '<div class="meta-wrap">' + movieTitle + movieDescription + movieButtons + '</div>';
|
|
||||||
original.parentElement.classList.add('enhanced');
|
|
||||||
// quick innerHTML hack to create elements here lol
|
|
||||||
imgTag = original.querySelector('.thumbnail');
|
|
||||||
movieTitle = original.querySelector('.movie-title');
|
|
||||||
movieDescription = original.querySelector('.movie-description');
|
|
||||||
movieButtons = original.querySelector('.movie-buttons');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nfo) {
|
|
||||||
createXMLRequest(reencodeURI(getHref(nfo)))
|
|
||||||
.then((content) => {
|
|
||||||
infoFilesAccounted += 1;
|
infoFilesAccounted += 1;
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return;
|
return;
|
||||||
@ -134,6 +113,7 @@ function createOrImproveMovieMeta(original, thumbnail, nfo) {
|
|||||||
|
|
||||||
movieTitle.innerText = title;
|
movieTitle.innerText = title;
|
||||||
movieDescription.innerText = plotEl.textContent;
|
movieDescription.innerText = plotEl.textContent;
|
||||||
|
|
||||||
if (imdbEl) {
|
if (imdbEl) {
|
||||||
const imlink = document.createElement('a');
|
const imlink = document.createElement('a');
|
||||||
imlink.target = '_blank';
|
imlink.target = '_blank';
|
||||||
@ -141,6 +121,7 @@ function createOrImproveMovieMeta(original, thumbnail, nfo) {
|
|||||||
imlink.href = `https://www.imdb.com/title/${imdbEl.textContent}`;
|
imlink.href = `https://www.imdb.com/title/${imdbEl.textContent}`;
|
||||||
movieButtons.appendChild(imlink);
|
movieButtons.appendChild(imlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tvdbEl) {
|
if (tvdbEl) {
|
||||||
const tvlink = document.createElement('a');
|
const tvlink = document.createElement('a');
|
||||||
tvlink.target = '_blank';
|
tvlink.target = '_blank';
|
||||||
@ -148,9 +129,14 @@ function createOrImproveMovieMeta(original, thumbnail, nfo) {
|
|||||||
tvlink.href = `http://www.thetvdb.com/?tab=series&id=${tvdbEl.textContent}`;
|
tvlink.href = `http://www.thetvdb.com/?tab=series&id=${tvdbEl.textContent}`;
|
||||||
movieButtons.appendChild(tvlink);
|
movieButtons.appendChild(tvlink);
|
||||||
}
|
}
|
||||||
if (getHref(nfo) !== 'tvshow.nfo' &&
|
|
||||||
navigator && navigator.clipboard &&
|
// Add "copy direct url" button
|
||||||
navigator.clipboard.writeText) {
|
if (
|
||||||
|
getHref(nfo) !== 'tvshow.nfo'
|
||||||
|
&& navigator
|
||||||
|
&& navigator.clipboard
|
||||||
|
&& navigator.clipboard.writeText
|
||||||
|
) {
|
||||||
const copybutton = document.createElement('button');
|
const copybutton = document.createElement('button');
|
||||||
copybutton.innerText = 'Copy direct URL';
|
copybutton.innerText = 'Copy direct URL';
|
||||||
movieButtons.appendChild(copybutton);
|
movieButtons.appendChild(copybutton);
|
||||||
@ -166,7 +152,43 @@ function createOrImproveMovieMeta(original, thumbnail, nfo) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// Replace list entry with a metadata box
|
||||||
|
// Either create or populate
|
||||||
|
function createOrImproveMovieMeta(original, thumbnail, nfo) {
|
||||||
|
let imgTag = `<img class="thumbnail" src="${thumbnail ? reencodeURI(getHref(thumbnail)) : ''}"/>`;
|
||||||
|
let movieTitle = `<div class="movie-title">${original.innerText}</div>`;
|
||||||
|
let movieDescription = `<div class="movie-description"></div>`;
|
||||||
|
let movieButtons = `<div class="movie-buttons"></div>`;
|
||||||
|
|
||||||
|
if (!thumbnail && !nfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (original.parentElement.classList.contains('enhanced')) {
|
||||||
|
imgTag = original.querySelector('.thumbnail');
|
||||||
|
movieTitle = original.querySelector('.movie-title');
|
||||||
|
movieDescription = original.querySelector('.movie-description');
|
||||||
|
movieButtons = original.querySelector('.movie-buttons');
|
||||||
|
if (thumbnail) {
|
||||||
|
imgTag.src = reencodeURI(getHref(thumbnail));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
original.classList.add('movie');
|
||||||
|
original.innerHTML = imgTag + '<div class="meta-wrap">' + movieTitle + movieDescription + movieButtons + '</div>';
|
||||||
|
original.parentElement.classList.add('enhanced');
|
||||||
|
// quick innerHTML hack to create elements here lol
|
||||||
|
imgTag = original.querySelector('.thumbnail');
|
||||||
|
movieTitle = original.querySelector('.movie-title');
|
||||||
|
movieDescription = original.querySelector('.movie-description');
|
||||||
|
movieButtons = original.querySelector('.movie-buttons');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch metadata from the nfo file and populate the info box
|
||||||
|
if (nfo) {
|
||||||
|
createXMLRequest(reencodeURI(getHref(nfo)))
|
||||||
|
.then((content) => fillMeta(content, original, nfo, movieTitle, movieDescription, movieButtons))
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
infoFilesAccounted += 1;
|
infoFilesAccounted += 1;
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@ -174,6 +196,7 @@ function createOrImproveMovieMeta(original, thumbnail, nfo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Promise that resolves when all info files that were found have been parsed
|
||||||
function waitUntilInfoComplete() {
|
function waitUntilInfoComplete() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (infoFilesAccounted >= infoFiles) {
|
if (infoFilesAccounted >= infoFiles) {
|
||||||
@ -183,25 +206,28 @@ function waitUntilInfoComplete() {
|
|||||||
|
|
||||||
let seconds = 0;
|
let seconds = 0;
|
||||||
const accountWait = setInterval(() => {
|
const accountWait = setInterval(() => {
|
||||||
if (infoFilesAccounted >= infoFiles || seconds > 5000) {
|
if (infoFilesAccounted >= infoFiles || seconds > 20) {
|
||||||
clearInterval(accountWait);
|
clearInterval(accountWait);
|
||||||
resolve(true);
|
resolve(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
seconds += 500;
|
seconds += 1;
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get episode name or name of file
|
||||||
const getCellValue = (tr, idx) =>
|
const getCellValue = (tr, idx) =>
|
||||||
tr.children[idx].getAttribute('data-episode')
|
tr.children[idx].getAttribute('data-episode')
|
||||||
|| tr.children[idx].innerText
|
|| tr.children[idx].innerText
|
||||||
|| tr.children[idx].textContent;
|
|| tr.children[idx].textContent;
|
||||||
|
|
||||||
|
// Compare numeric or (locale-aware, numeric-aware) by string values
|
||||||
const comparer = (idx, asc) => (a, b) => ((v1, v2) =>
|
const comparer = (idx, asc) => (a, b) => ((v1, v2) =>
|
||||||
v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
|
v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2, 'et', { numeric: true })
|
||||||
)(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
|
)(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
|
||||||
|
|
||||||
|
// Table sort by column index
|
||||||
const sortTableValues = (index) =>
|
const sortTableValues = (index) =>
|
||||||
Array.from(tableElem.querySelectorAll('tr:nth-child(n+2):not(.btn-back)'))
|
Array.from(tableElem.querySelectorAll('tr:nth-child(n+2):not(.btn-back)'))
|
||||||
.sort(comparer(index, this.asc = !this.asc))
|
.sort(comparer(index, this.asc = !this.asc))
|
||||||
@ -211,9 +237,13 @@ let tvShow;
|
|||||||
function accountForMetadata() {
|
function accountForMetadata() {
|
||||||
allLinks.forEach((link) => {
|
allLinks.forEach((link) => {
|
||||||
const url = getHref(link);
|
const url = getHref(link);
|
||||||
|
|
||||||
|
// If nfo or jpg (or subtitle, for hiding it)..
|
||||||
if (url.match(infoRegex)) {
|
if (url.match(infoRegex)) {
|
||||||
|
// Hide metadata file
|
||||||
link.parentElement.parentElement.style.display = 'none';
|
link.parentElement.parentElement.style.display = 'none';
|
||||||
let findOriginal
|
let findOriginal
|
||||||
|
// Place TV show information in the beginning of the table
|
||||||
if (url === 'tvshow.nfo' || url === 'poster.jpg') {
|
if (url === 'tvshow.nfo' || url === 'poster.jpg') {
|
||||||
if (url === 'poster.jpg' && !allLinks.find((found) => getHref(found) === 'tvshow.nfo')) {
|
if (url === 'poster.jpg' && !allLinks.find((found) => getHref(found) === 'tvshow.nfo')) {
|
||||||
findOriginal = document.querySelector('a:not([href=".."])');
|
findOriginal = document.querySelector('a:not([href=".."])');
|
||||||
@ -230,16 +260,30 @@ function accountForMetadata() {
|
|||||||
findOriginal = tvShow;
|
findOriginal = tvShow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Give posters to seasons
|
||||||
} else if (url.startsWith('season') && url.includes('poster')) {
|
} else if (url.startsWith('season') && url.includes('poster')) {
|
||||||
|
// Find season by number
|
||||||
const sn = url.match(/season(\d+)/);
|
const sn = url.match(/season(\d+)/);
|
||||||
if (sn) {
|
if (sn) {
|
||||||
findOriginal = allLinks.find((allurl) => allurl.innerText.includes(parseInt(sn[1], 10)));
|
findOriginal = allLinks.find(
|
||||||
|
({ innerText }) => {
|
||||||
|
return innerText.endsWith('/')
|
||||||
|
&& findWholeNumberInText(innerText, parseInt(sn[1], 10));
|
||||||
|
});
|
||||||
|
// Find specials folder
|
||||||
} else if (url.includes('specials')) {
|
} else if (url.includes('specials')) {
|
||||||
findOriginal = allLinks.find((allurl) => allurl.innerText.toLowerCase().startsWith('special'));
|
findOriginal = allLinks.find(({ innerText }) => {
|
||||||
|
const matchAgainst = innerText.toLowerCase();
|
||||||
|
return (matchAgainst.startsWith('specials') || matchAgainst.startsWith('extras'))
|
||||||
|
&& innerText.endsWith('/');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
// Find the video file associated with this info file
|
||||||
} else {
|
} else {
|
||||||
findOriginal = findByInfoFile(url);
|
findOriginal = findByInfoFile(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populate video file/season folder/tv show info box
|
||||||
if (findOriginal) {
|
if (findOriginal) {
|
||||||
if (url.match(/.nfo$/)) {
|
if (url.match(/.nfo$/)) {
|
||||||
infoFiles += 1;
|
infoFiles += 1;
|
||||||
@ -250,6 +294,8 @@ function accountForMetadata() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace the back button with a more descriptive one
|
||||||
if (url === '..') {
|
if (url === '..') {
|
||||||
link.parentElement.parentElement.classList.add('btn-back');
|
link.parentElement.parentElement.classList.add('btn-back');
|
||||||
link.innerHTML = arrow + 'Back (..)';
|
link.innerHTML = arrow + 'Back (..)';
|
||||||
|
Loading…
Reference in New Issue
Block a user