mirror of
https://github.com/C9Glax/tranga-website.git
synced 2025-02-28 22:15:49 +01:00

Changed CSS style to be stored in local storage since we might want it to be browser specific (mobile vs desktop vs tablet)
907 lines
31 KiB
JavaScript
907 lines
31 KiB
JavaScript
let monitoringJobsCount = 0;
|
|
let runningJobs = [];
|
|
let waitingJobs = [];
|
|
let notificationConnectorTypes = [];
|
|
let libraryConnectorTypes = [];
|
|
let selectedManga;
|
|
let selectedJob;
|
|
let searchMatch;
|
|
|
|
let connectorMatch = [];
|
|
let connectorNameMatch;
|
|
let statusMatch = [];
|
|
let statusNameMatch = [];
|
|
|
|
const searchBox = document.querySelector("#searchbox");
|
|
const settingsPopup = document.querySelector("#settingsPopup");
|
|
const filterBox = document.querySelector("#filterBox");
|
|
const settingsCog = document.querySelector("#settingscog");
|
|
const filterFunnel = document.querySelector("#filterFunnel");
|
|
const tasksContent = document.querySelector("content");
|
|
const createMonitorTaskButton = document.querySelector("#createMonitoJobButton");
|
|
const createDownloadChapterTaskButton = document.querySelector("#createDownloadChapterJobButton");
|
|
const startJobButton = document.querySelector("#startJobButton");
|
|
const cancelJobButton = document.querySelector("#cancelJobButton");
|
|
const deleteJobButton = document.querySelector("#deleteJobButton");
|
|
|
|
//Manga viewer popup
|
|
const mangaViewerPopup = document.querySelector("#publicationViewerPopup");
|
|
const mangaViewerWindow = document.querySelector("publication-viewer");
|
|
const mangaViewerDescription = document.querySelector("#publicationViewerDescription");
|
|
const mangaViewerName = document.querySelector("#publicationViewerName");
|
|
const mangaViewerTags = document.querySelector("#publicationViewerTags");
|
|
const mangaViewerAuthor = document.querySelector("#publicationViewerAuthor");
|
|
const mangaViewCover = document.querySelector("#pubviewcover");
|
|
|
|
//Rate Limits
|
|
const manganatoRateLimit = document.querySelector('#manganatoRL');
|
|
const mangaseeRateLimit = document.querySelector('#mangaseeRL');
|
|
const mangadexRateLimit = document.querySelector('#mDexRL');
|
|
const mangakatanaRateLimit = document.querySelector('#mKatanaRL');
|
|
const mangaworldRateLimit = document.querySelector('#mWorldRL');
|
|
const batoRateLimit = document.querySelector('#batoRL');
|
|
const mangalifeRateLimit = document.querySelector('#mLifeRL');
|
|
|
|
//Komga
|
|
const settingKomgaUrl = document.querySelector("#komgaUrl");
|
|
const settingKomgaUser = document.querySelector("#komgaUsername");
|
|
const settingKomgaPass = document.querySelector("#komgaPassword");
|
|
|
|
//Kavita
|
|
const settingKavitaUrl = document.querySelector("#kavitaUrl");
|
|
const settingKavitaUser = document.querySelector("#kavitaUsername");
|
|
const settingKavitaPass = document.querySelector("#kavitaPassword");
|
|
|
|
//Gotify
|
|
const settingGotifyUrl = document.querySelector("#gotifyUrl");
|
|
const settingGotifyAppToken = document.querySelector("#gotifyAppToken");
|
|
|
|
//Lunasea
|
|
const settingLunaseaWebhook = document.querySelector("#lunaseaWebhook");
|
|
|
|
//Ntfy
|
|
const settingNtfyEndpoint = document.querySelector("#ntfyEndpoint");
|
|
const settingNtfyAuth = document.querySelector("#ntfyAuth");
|
|
|
|
//Connector Configured
|
|
const settingKomgaConfigured = document.querySelector("#komgaConfigured");
|
|
const settingKavitaConfigured = document.querySelector("#kavitaConfigured");
|
|
const settingGotifyConfigured = document.querySelector("#gotifyConfigured");
|
|
const settingLunaseaConfigured = document.querySelector("#lunaseaConfigured");
|
|
const settingNtfyConfigured = document.querySelector("#ntfyConfigured");
|
|
|
|
const settingUserAgent = document.querySelector("#userAgent");
|
|
const settingApiUri = document.querySelector("#settingApiUri");
|
|
const settingCSSStyle = document.querySelector('#cssStyle');
|
|
const newMangaPopup = document.querySelector("#newMangaPopup");
|
|
const newMangaConnector = document.querySelector("#newMangaConnector");
|
|
const newMangaTitle = document.querySelector("#newMangaTitle");
|
|
const newMangaResult = document.querySelector("#newMangaResult");
|
|
const newMangaTranslatedLanguage = document.querySelector("#newMangaTranslatedLanguage");
|
|
|
|
//Jobs
|
|
const jobsRunningTag = document.querySelector("#jobsRunningTag");
|
|
const jobsQueuedTag = document.querySelector("#jobsQueuedTag");
|
|
const loaderdiv = document.querySelector('#loaderdiv');
|
|
const jobStatusView = document.querySelector("#jobStatusView");
|
|
const jobStatusRunning = document.querySelector("#jobStatusRunning");
|
|
const jobStatusWaiting = document.querySelector("#jobStatusWaiting");
|
|
|
|
function Setup(){
|
|
Ping().then((ret) => {
|
|
loaderdiv.style.display = 'none';
|
|
|
|
GetAvailableNotificationConnectors().then((json) => {
|
|
//console.log(json);
|
|
json.forEach(connector => {
|
|
notificationConnectorTypes[connector.Key] = connector.Value;
|
|
});
|
|
});
|
|
|
|
GetAvailableLibraryConnectors().then((json) => {
|
|
//console.log(json);
|
|
json.forEach(connector => {
|
|
libraryConnectorTypes[connector.Key] = connector.Value;
|
|
});
|
|
});
|
|
|
|
GetAvailableControllers().then((json) => {
|
|
//console.log(json);
|
|
newMangaConnector.replaceChildren();
|
|
connectorFilterBox = document.querySelector("#connectorFilterBox");
|
|
json.forEach(connector => {
|
|
//Add the connector to the New Manga dropdown
|
|
var option = document.createElement('option');
|
|
option.value = connector;
|
|
option.innerText = connector;
|
|
newMangaConnector.appendChild(option);
|
|
|
|
//Add the connector to the filter box
|
|
connectorFilter = document.createElement('connector-name');
|
|
connectorFilter.innerText = connector;
|
|
connectorFilter.className = "pill";
|
|
connectorFilter.style.backgroundColor = stringToColour(connector);
|
|
|
|
connectorFilter.addEventListener("click", (event) => {
|
|
ToggleFilterConnector(connector, event);
|
|
});
|
|
connectorFilterBox.appendChild(connectorFilter);
|
|
});
|
|
});
|
|
|
|
//Add the publication status options to the filter bar
|
|
publicationStatusOptions = ["Ongoing", "Completed", "On Hiatus", "Cancelled", "Upcoming", "Status Unavailable"];
|
|
statusFilterBox = document.querySelector("#statusFilterBox");
|
|
publicationStatusOptions.forEach(publicationStatus => {
|
|
var releaseStatus = document.createElement('status-filter');
|
|
releaseStatus.innerText = publicationStatus;
|
|
releaseStatus.setAttribute("release-status", publicationStatus);
|
|
releaseStatus.addEventListener("click", (event) => {
|
|
ToggleFilterStatus(publicationStatus, event);
|
|
});
|
|
|
|
statusFilterBox.appendChild(releaseStatus);
|
|
});
|
|
|
|
ResetContent();
|
|
UpdateJobs();
|
|
GetSettings().then((json) => {
|
|
//console.log(json);
|
|
settingApiUri.placeholder = apiUri;
|
|
});
|
|
|
|
//If the cssStyle key isn't in the local storage of the browser, then set the css style to the default and load the page
|
|
//Otherwise get the style key from storage and set it.
|
|
if (!localStorage.getItem('cssStyle')) {
|
|
localStorage.setItem('cssStyle', 'card_compact');
|
|
document.getElementById('librarystyle').setAttribute('href', 'styles/' + localStorage.getItem('cssStyle') + '.css');
|
|
document.getElementById('card_compact').selected = true;
|
|
} else {
|
|
css_style = localStorage.getItem('cssStyle');
|
|
document.getElementById('librarystyle').setAttribute('href', 'styles/' + css_style + '.css');
|
|
document.getElementById(css_style).selected = true;
|
|
}
|
|
setInterval(() => {
|
|
UpdateJobs();
|
|
}, 1000);
|
|
});
|
|
//Clear the previous values if any exist.
|
|
searchBox.value = "";
|
|
connectorMatch.length = 0;
|
|
statusMatch.length = 0;
|
|
}
|
|
Setup();
|
|
|
|
function ToggleFilterConnector(connector, event) {
|
|
//console.log("Initial Array:");
|
|
//console.log(connectorMatch);
|
|
if (connectorMatch.includes(connector)) {
|
|
idx = connectorMatch.indexOf(connector);
|
|
connectorMatch.splice(idx, 1);
|
|
event.target.style.outline = 'none';
|
|
event.target.style.outlineOffset = "0px";
|
|
} else {
|
|
connectorMatch.push(connector);
|
|
event.target.style.outline = '4px solid var(--secondary-color)';
|
|
event.target.style.outlineOffset = '3px';
|
|
}
|
|
//console.log("Final Array");
|
|
//console.log(connectorMatch);
|
|
FilterResults();
|
|
}
|
|
|
|
function ToggleFilterStatus(status, event) {
|
|
//console.log("Initial Array:");
|
|
//console.log(statusMatch);
|
|
if (statusMatch.includes(status)) {
|
|
idx = statusMatch.indexOf(status);
|
|
statusMatch.splice(idx, 1);
|
|
event.target.style.outline = 'none';
|
|
event.target.style.outlineOffset = "0px";
|
|
} else {
|
|
statusMatch.push(status);
|
|
event.target.style.outline = '4px solid var(--secondary-color)';
|
|
event.target.style.outlineOffset = '3px';
|
|
}
|
|
//console.log("Final Array");
|
|
//console.log(statusMatch);
|
|
FilterResults();
|
|
}
|
|
|
|
function ClearFilter() {
|
|
searchBox.value = "";
|
|
statusMatch.length = 0;
|
|
connectorMatch.length = 0;
|
|
FilterResults();
|
|
|
|
//Get rid of the outlines
|
|
connectorFilterBox = document.querySelector("#connectorFilterBox");
|
|
connectorFilterBox.childNodes.forEach(connector => {
|
|
if (connector.nodeName.toLowerCase() == 'connector-name') {
|
|
connector.style.outline = 'none';
|
|
connector.style.outlineOffset = "0px";
|
|
}
|
|
});
|
|
|
|
statusFilterBox = document.querySelector("#statusFilterBox");
|
|
statusFilterBox.childNodes.forEach(publicationStatus => {
|
|
if (publicationStatus.nodeName.toLowerCase() == 'status-filter') {
|
|
publicationStatus.style.outline = 'none';
|
|
publicationStatus.style.outlineOffset = "0px";
|
|
}
|
|
});
|
|
}
|
|
|
|
settingCSSStyle.addEventListener("change", (event) => {
|
|
localStorage.setItem('cssStyle', settingCSSStyle.value);
|
|
document.getElementById('librarystyle').setAttribute('href', 'styles/' + localStorage.getItem('cssStyle') + '.css');
|
|
});
|
|
|
|
function ResetContent(){
|
|
//Delete everything
|
|
tasksContent.replaceChildren();
|
|
|
|
//Add "Add new Task" Button
|
|
var add = document.createElement("div");
|
|
add.setAttribute("id", "addPublication")
|
|
var plus = document.createElement("p");
|
|
plus.innerText = "+";
|
|
add.appendChild(plus);
|
|
add.addEventListener("click", () => ShowNewMangaSearch());
|
|
tasksContent.appendChild(add);
|
|
|
|
//Populate with the monitored mangas
|
|
GetMonitorJobs().then((json) => {
|
|
//console.log(json);
|
|
json.forEach(job => {
|
|
var mangaView = CreateManga(job.manga, job.mangaConnector.name);
|
|
mangaView.addEventListener("click", (event) => {
|
|
ShowMangaWindow(job, job.manga, event, false);
|
|
});
|
|
tasksContent.appendChild(mangaView);
|
|
});
|
|
monitoringJobsCount = json.length;
|
|
});
|
|
}
|
|
|
|
function ShowNewMangaSearch(){
|
|
newMangaTitle.value = "";
|
|
newMangaPopup.style.display = "block";
|
|
newMangaResult.replaceChildren();
|
|
}
|
|
|
|
newMangaTitle.addEventListener("keypress", (event) => { if(event.key === "Enter") GetNewMangaItems();});
|
|
|
|
|
|
|
|
|
|
function GetNewMangaItems(){
|
|
if(newMangaTitle.value.length < 4)
|
|
return;
|
|
|
|
newMangaResult.replaceChildren();
|
|
newMangaConnector.disabled = true;
|
|
newMangaTitle.disabled = true;
|
|
newMangaTranslatedLanguage.disabled = true;
|
|
GetPublicationFromConnector(newMangaConnector.value, newMangaTitle.value).then((json) => {
|
|
//console.log(json);
|
|
if(json.length > 0)
|
|
newMangaResult.style.display = "flex";
|
|
json.forEach(result => {
|
|
var mangaElement = CreateManga(result, newMangaConnector.value)
|
|
newMangaResult.appendChild(mangaElement);
|
|
mangaElement.addEventListener("click", (event) => {
|
|
ShowMangaWindow(null, result, event, true);
|
|
});
|
|
});
|
|
|
|
newMangaConnector.disabled = false;
|
|
newMangaTitle.disabled = false;
|
|
newMangaTranslatedLanguage.disabled = false;
|
|
});
|
|
}
|
|
|
|
//Returns a new "Publication" Item to display in the jobs section
|
|
function CreateManga(manga, connector){
|
|
//Create a new publication and set an internal ID
|
|
var mangaElement = document.createElement('publication');
|
|
mangaElement.id = GetValidSelector(manga.internalId);
|
|
|
|
//Append the cover image to the publication
|
|
var mangaImage = document.createElement('img');
|
|
mangaImage.src = GetCoverUrl(manga.internalId);
|
|
mangaElement.appendChild(mangaImage);
|
|
|
|
//Append the publication information to the publication
|
|
//console.log(manga);
|
|
var info = document.createElement('publication-information');
|
|
var connectorName = document.createElement('connector-name');
|
|
connectorName.innerText = connector;
|
|
connectorName.className = "pill";
|
|
connectorName.style.backgroundColor = stringToColour(connector);
|
|
info.appendChild(connectorName);
|
|
|
|
var mangaName = document.createElement('publication-name');
|
|
mangaName.innerText = manga.sortName;
|
|
|
|
//Create the publication status indicator
|
|
var releaseStatus = document.createElement('publication-status');
|
|
releaseStatus.setAttribute("release-status", manga.releaseStatus);
|
|
switch(manga.releaseStatus){
|
|
case 0:
|
|
releaseStatus.setAttribute("release-status", "Ongoing");
|
|
break;
|
|
case 1:
|
|
releaseStatus.setAttribute("release-status", "Completed");
|
|
break;
|
|
case 2:
|
|
releaseStatus.setAttribute("release-status", "On Hiatus");
|
|
break;
|
|
case 3:
|
|
releaseStatus.setAttribute("release-status", "Cancelled");
|
|
break;
|
|
case 4:
|
|
releaseStatus.setAttribute("release-status", "Upcoming");
|
|
break;
|
|
default:
|
|
releaseStatus.setAttribute("release-status", "Status Unavailable");
|
|
break;
|
|
}
|
|
|
|
info.appendChild(mangaName);
|
|
mangaElement.appendChild(info);
|
|
mangaElement.appendChild(releaseStatus); //Append the release status indicator to the publication element
|
|
return mangaElement;
|
|
}
|
|
|
|
createMonitorJobButton.addEventListener("click", () => {
|
|
CreateMonitorJob(newMangaConnector.value, selectedManga.internalId, newMangaTranslatedLanguage.value);
|
|
UpdateJobs();
|
|
mangaViewerPopup.style.display = "none";
|
|
ResetContent();
|
|
});
|
|
startJobButton.addEventListener("click", () => {
|
|
StartJob(selectedJob.id);
|
|
mangaViewerPopup.style.display = "none";
|
|
});
|
|
cancelJobButton.addEventListener("click", () => {
|
|
CancelJob(selectedJob.id);
|
|
mangaViewerPopup.style.display = "none";
|
|
});
|
|
deleteJobButton.addEventListener("click", () => {
|
|
RemoveJob(selectedJob.id);
|
|
UpdateJobs();
|
|
mangaViewerPopup.style.display = "none";
|
|
ResetContent();
|
|
});
|
|
|
|
function ShowMangaWindow(job, manga, event, add){
|
|
selectedManga = manga;
|
|
selectedJob = job;
|
|
//Show popup
|
|
mangaViewerPopup.style.display = "block";
|
|
|
|
//Set position to mouse-position
|
|
if(event.clientY < window.innerHeight - mangaViewerWindow.offsetHeight)
|
|
mangaViewerWindow.style.top = `${event.clientY}px`;
|
|
else
|
|
mangaViewerWindow.style.top = `${event.clientY - mangaViewerWindow.offsetHeight}px`;
|
|
|
|
if(event.clientX < window.innerWidth - mangaViewerWindow.offsetWidth)
|
|
mangaViewerWindow.style.left = `${event.clientX}px`;
|
|
else
|
|
mangaViewerWindow.style.left = `${event.clientX - mangaViewerWindow.offsetWidth}px`;
|
|
|
|
//Edit information inside the window
|
|
mangaViewerName.innerText = manga.sortName;
|
|
mangaViewerTags.innerText = manga.tags.join(", ");
|
|
mangaViewerDescription.innerText = manga.description;
|
|
mangaViewerAuthor.innerText = manga.authors.join(',');
|
|
mangaViewCover.src = GetCoverUrl(manga.internalId);
|
|
toEditId = manga.internalId;
|
|
|
|
//Check what action should be listed
|
|
if(add){
|
|
createMonitorJobButton.style.display = "initial";
|
|
createDownloadChapterJobButton.style.display = "none";
|
|
cancelJobButton.style.display = "none";
|
|
startJobButton.style.display = "none";
|
|
deleteJobButton.style.display = "none";
|
|
}
|
|
else{
|
|
createMonitorJobButton.style.display = "none";
|
|
createDownloadChapterJobButton.style.display = "none";
|
|
cancelJobButton.style.display = "initial";
|
|
startJobButton.style.display = "initial";
|
|
deleteJobButton.style.display = "initial";
|
|
}
|
|
}
|
|
|
|
function HidePublicationPopup(){
|
|
publicationViewerPopup.style.display = "none";
|
|
}
|
|
|
|
searchBox.addEventListener("keyup", () => FilterResults());
|
|
//Filter shown jobs
|
|
function FilterResults(){
|
|
//For each publication
|
|
tasksContent.childNodes.forEach(publication => {
|
|
//If the search box isn't empty check that the title contains the searchbox content. If it does then
|
|
//'searchMatch' is true and the manga is shown. If the search box is empty, then consider this field
|
|
//to be true anyways.
|
|
if (searchBox.value.length > 0) {
|
|
publication.childNodes.forEach(item => {
|
|
if (item.nodeName.toLowerCase() == "publication-information"){
|
|
item.childNodes.forEach(information => {
|
|
if (information.nodeName.toLowerCase() == "publication-name") {
|
|
if (information.textContent.toLowerCase().includes(searchBox.value.toLowerCase())){
|
|
searchMatch = 1;
|
|
} else {
|
|
searchMatch = 0;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
searchMatch = 1;
|
|
}
|
|
|
|
//If the array connectorMatch isn't empty then check that the connector matches one of the ones
|
|
//in the array
|
|
if (connectorMatch.length > 0) {
|
|
publication.childNodes.forEach(item => {
|
|
if (item.nodeName.toLowerCase() == "publication-information"){
|
|
item.childNodes.forEach(information => {
|
|
if (information.nodeName.toLowerCase() == "connector-name") {
|
|
if (connectorMatch.includes(information.textContent)){
|
|
connectorNameMatch = 1;
|
|
} else {
|
|
connectorNameMatch = 0;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
connectorNameMatch = 1;
|
|
}
|
|
|
|
//If the array statusMatch isn't empty then check that the status matches one of the ones
|
|
//in the array
|
|
if (statusMatch.length > 0) {
|
|
publication.childNodes.forEach(item => {
|
|
if (item.nodeName.toLowerCase() == "publication-status"){
|
|
if (statusMatch.includes(item.getAttribute('release-status'))) {
|
|
statusNameMatch = 1;
|
|
} else {
|
|
statusNameMatch = 0;
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
statusNameMatch = 1;
|
|
}
|
|
|
|
//If all of the filtering conditions are met then show the manga, otherwise hide it.
|
|
if (searchMatch && connectorNameMatch && statusNameMatch) {
|
|
publication.style.display = 'initial';
|
|
} else {
|
|
publication.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
settingsCog.addEventListener("click", () => {
|
|
OpenSettings();
|
|
settingsPopup.style.display = "flex";
|
|
});
|
|
|
|
filterFunnel.addEventListener("click", () => {
|
|
filterBox.classList.toggle("animate");
|
|
});
|
|
|
|
settingKomgaUrl.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingKomgaUser.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingKomgaPass.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingKavitaUrl.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingKavitaUser.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingKavitaPass.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingGotifyUrl.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingGotifyAppToken.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingLunaseaWebhook.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingNtfyEndpoint.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingNtfyAuth.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingUserAgent.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
settingApiUri.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
|
|
|
manganatoRateLimit.addEventListener("keypress", (event) => { if(event.key === "Enter") NewRateLimit(event);});
|
|
mangaseeRateLimit.addEventListener("keypress", (event) => { if(event.key === "Enter") NewRateLimit(event);});
|
|
mangadexRateLimit.addEventListener("keypress", (event) => { if(event.key === "Enter") NewRateLimit(event);});
|
|
mangakatanaRateLimit.addEventListener("keypress", (event) => { if(event.key === "Enter") NewRateLimit(event);});
|
|
mangaworldRateLimit.addEventListener("keypress", (event) => { if(event.key === "Enter") NewRateLimit(event);});
|
|
batoRateLimit.addEventListener("keypress", (event) => { if(event.key === "Enter") NewRateLimit(event);});
|
|
mangalifeRateLimit.addEventListener("keypress", (event) => { if(event.key === "Enter") NewRateLimit(event);});
|
|
|
|
function NewRateLimit(event) {
|
|
if (event.target.value.length > 0 && event.target.value != 0) {
|
|
console.log(event.target.id);
|
|
switch (event.target.id) {
|
|
case "manganatoRL":
|
|
connector = 'Manganato';
|
|
byteValue = 1;
|
|
UpdateRateLimit(connector, byteValue, event.target.value);
|
|
break;
|
|
case "mangaseeRL":
|
|
connector = 'Mangasee';
|
|
byteValue = 1;
|
|
UpdateRateLimit(connector, byteValue, event.target.value);
|
|
break;
|
|
case "mDexRL":
|
|
connector = 'MangaDex'
|
|
byteValue = 250;
|
|
UpdateRateLimit(connector, byteValue, event.target.value);
|
|
break;
|
|
case "mKatanaRL":
|
|
connector = 'MangaKatana';
|
|
byteValue = 1;
|
|
UpdateRateLimit(connector, byteValue, event.target.value);
|
|
break;
|
|
case "mWorldRL":
|
|
connector = 'Mangaworld';
|
|
byteValue = 1;
|
|
UpdateRateLimit(connector, byteValue, event.target.value);
|
|
break;
|
|
case "batoRL":
|
|
connector = 'Bato';
|
|
byteValue = 1;
|
|
UpdateRateLimit(connector, byteValue, event.target.value);
|
|
break;
|
|
case "mLifeRL":
|
|
connector = 'Manga4Life';
|
|
byteValue = 1;
|
|
UpdateRateLimit(connector, byteValue, event.target.value);
|
|
break;
|
|
default:
|
|
console.log("Unknown connector:");
|
|
console.log(event.target.id);
|
|
}
|
|
}
|
|
}
|
|
|
|
function OpenSettings(){
|
|
settingGotifyConfigured.setAttribute("configuration", "Not Configured");
|
|
settingLunaseaConfigured.setAttribute("configuration", "Not Configured");
|
|
settingNtfyConfigured.setAttribute("configuration", "Not Configured");
|
|
settingKavitaConfigured.setAttribute("configuration", "Not Configured");
|
|
settingKomgaConfigured.setAttribute("configuration", "Not Configured");
|
|
settingKomgaUrl.value = "";
|
|
settingKomgaUser.value = "";
|
|
settingKomgaPass.value = "";
|
|
settingKavitaUrl.value = "";
|
|
settingKavitaUser.value = "";
|
|
settingKavitaPass.value = "";
|
|
settingGotifyUrl.value = "";
|
|
settingGotifyAppToken.value = "";
|
|
settingLunaseaWebhook.value = "";
|
|
settingNtfyAuth.value = "";
|
|
settingNtfyEndpoint.value = "";
|
|
settingUserAgent.value = "";
|
|
settingApiUri.value = "";
|
|
|
|
GetSettings().then((json) => {
|
|
//console.log(json);
|
|
settingApiUri.placeholder = apiUri;
|
|
settingUserAgent.placeholder = json.userAgent;
|
|
//console.log(json.styleSheet);
|
|
});
|
|
GetLibraryConnectors().then((json) => {
|
|
//console.log(json);
|
|
json.forEach(connector => {
|
|
switch(libraryConnectorTypes[connector.libraryType]){
|
|
case "Kavita":
|
|
settingKavitaConfigured.setAttribute("configuration", "Active");
|
|
settingKavitaUrl.value = connector.baseUrl;
|
|
settingKavitaUser.value = "***";
|
|
settingKavitaPass.value = "***";
|
|
break;
|
|
case "Komga":
|
|
settingKomgaConfigured.setAttribute("configuration", "Active");
|
|
settingKomgaUrl.value = connector.baseUrl;
|
|
settingKomgaUser.value = "***";
|
|
settingKomgaPass.value = "***";
|
|
break;
|
|
default:
|
|
console.log("Unknown type");
|
|
console.log(connector);
|
|
break;
|
|
}
|
|
});
|
|
});
|
|
GetNotificationConnectors().then((json) => {
|
|
console.log(json);
|
|
json.forEach(connector => {
|
|
switch(notificationConnectorTypes[connector.notificationConnectorType]){
|
|
case "Gotify":
|
|
settingGotifyUrl.value = connector.endpoint;
|
|
settingGotifyAppToken.value = "***";
|
|
settingGotifyConfigured.setAttribute("configuration", "Active");
|
|
break;
|
|
case "LunaSea":
|
|
settingLunaseaConfigured.setAttribute("configuration", "Active");
|
|
settingLunaseaWebhook.value = connector.id;
|
|
break;
|
|
case "Ntfy":
|
|
settingNtfyConfigured.setAttribute("configuration", "Active");
|
|
settingNtfyEndpoint.value = connector.endpoint;
|
|
settingNtfyAuth.value = "***";
|
|
break;
|
|
default:
|
|
console.log("Unknown type");
|
|
console.log(connector);
|
|
break;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
//Functions for clearing/resetting connectors in the settings pop-up
|
|
function ClearKomga(){
|
|
settingKomgaUrl.value = "";
|
|
settingKomgaUser.value = "";
|
|
settingKomgaPass.value = "";
|
|
settingKomgaConfigured.setAttribute("configuration", "Not Configured");
|
|
ResetKomga();
|
|
}
|
|
|
|
function ClearKavita(){
|
|
settingKavitaUrl.value = "";
|
|
settingKavitaUser.value = "";
|
|
settingKavitaPass.value = "";
|
|
settingKavitaConfigured.setAttribute("configuration", "Not Configured");
|
|
ResetKavita();
|
|
}
|
|
|
|
function ClearGotify(){
|
|
settingGotifyUrl.value = "";
|
|
settingGotifyAppToken.value = ""
|
|
settingGotifyConfigured.setAttribute("configuration", "Not Configured");
|
|
ResetGotify();
|
|
}
|
|
|
|
function ClearLunasea(){
|
|
settingLunaseaWebhook.value = "";
|
|
settingLunaseaConfigured.setAttribute("configuration", "Not Configured");
|
|
ResetLunaSea();
|
|
}
|
|
|
|
function ClearNtfy(){
|
|
settingNtfyEndpoint.value = "";
|
|
settingNtfyAuth.value = "";
|
|
settingNtfyConfigured.setAttribute("configuration", "Not Configured");
|
|
ResetNtfy();
|
|
}
|
|
|
|
function UpdateSettings(){
|
|
if(settingApiUri.value != ""){
|
|
apiUri = settingApiUri.value;
|
|
setCookie("apiUri", apiUri);
|
|
Setup();
|
|
}
|
|
|
|
if(settingKomgaUrl.value != "" &&
|
|
settingKomgaUser.value != "" &&
|
|
settingKomgaPass.value != ""){
|
|
UpdateKomga(settingKomgaUrl.value, utf8_to_b64(`${settingKomgaUser.value}:${settingKomgaPass.value}`));
|
|
}
|
|
|
|
if(settingKavitaUrl.value != "" &&
|
|
settingKavitaUser.value != "" &&
|
|
settingKavitaPass.value != ""){
|
|
UpdateKavita(settingKavitaUrl.value, settingKavitaUser.value, settingKavitaPass.value);
|
|
}
|
|
|
|
if(settingGotifyUrl.value != "" &&
|
|
settingGotifyAppToken.value != ""){
|
|
UpdateGotify(settingGotifyUrl.value, settingGotifyAppToken.value);
|
|
}
|
|
|
|
if(settingLunaseaWebhook.value != ""){
|
|
UpdateLunaSea(settingLunaseaWebhook.value);
|
|
}
|
|
|
|
if(settingNtfyEndpoint.value != "" &&
|
|
settingNtfyAuth.value != ""){
|
|
UpdateNtfy(settingNtfyEndpoint.value, settingNtfyAuth.value);
|
|
}
|
|
|
|
if(settingUserAgent.value != ""){
|
|
UpdateUserAgent(settingUserAgent.value);
|
|
}
|
|
|
|
if (manganatoRateLimit.value.length > 0) {
|
|
UpdateRateLimit('Manganato', 1, manganatoRateLimit.value);
|
|
}
|
|
|
|
if (mangaseeRateLimit.value.length > 0) {
|
|
UpdateRateLimit('Mangasee', 1, mangaseeRateLimit.value);
|
|
}
|
|
|
|
if (mangadexRateLimit.value.length > 0) {
|
|
UpdateRateLimit('MangaDex', 250, mangadexRateLimit.value);
|
|
}
|
|
|
|
if (mangakatanaRateLimit.value.length > 0) {
|
|
UpdateRateLimit('MangaKatana', 1, mangakatanaRateLimit.value);
|
|
}
|
|
|
|
if (mangaworldRateLimit.value.length > 0) {
|
|
UpdateRateLimit('Mangaworld', 1, mangaworldRateLimit.value);
|
|
}
|
|
|
|
if (batoRateLimit.value.length > 0) {
|
|
UpdateRateLimit('Bato', 1, batoRateLimit.value);
|
|
}
|
|
|
|
if (mangalifeRateLimit.value.length > 0) {
|
|
UpdateRateLimit('Manga4Life', 1, mangalifeRateLimit.value);
|
|
}
|
|
|
|
setTimeout(() => {
|
|
OpenSettings();
|
|
Setup();
|
|
}, 100)
|
|
}
|
|
|
|
function utf8_to_b64(str) {
|
|
return window.btoa(unescape(encodeURIComponent( str )));
|
|
}
|
|
|
|
function UpdateJobs(){
|
|
|
|
GetMonitorJobs().then((json) => {
|
|
if(monitoringJobsCount != json.length){
|
|
ResetContent();
|
|
//console.log(json);
|
|
json.forEach(job => {
|
|
var mangaView = CreateManga(job.manga, job.mangaConnector.name);
|
|
mangaView.addEventListener("click", (event) => {
|
|
ShowMangaWindow(job, job.manga, event, false);
|
|
});
|
|
tasksContent.appendChild(mangaView);
|
|
});
|
|
monitoringJobsCount = json.length;
|
|
}
|
|
});
|
|
|
|
//Get the jobs that are waiting in the queue
|
|
GetWaitingJobs().then((json) => {
|
|
jobsQueuedTag.innerText = json.length;
|
|
|
|
var nowWaitingJobs = [];
|
|
|
|
json.forEach(job => {
|
|
if(!waitingJobs.includes(GetValidSelector(job.id))){
|
|
var jobDom = createJob(job);
|
|
jobStatusWaiting.appendChild(jobDom);
|
|
}
|
|
nowWaitingJobs.push(GetValidSelector(job.id));
|
|
});
|
|
waitingJobs = nowWaitingJobs;
|
|
});
|
|
|
|
jobStatusWaiting.childNodes.forEach(child => {
|
|
if(!waitingJobs.includes(child.id))
|
|
jobStatusWaiting.removeChild(child);
|
|
});
|
|
|
|
//Get currently running jobs
|
|
GetRunningJobs().then((json) => {
|
|
jobsRunningTag.innerText = json.length;
|
|
|
|
var nowRunningJobs = [];
|
|
|
|
json.forEach(job => {
|
|
if(!runningJobs.includes(GetValidSelector(job.id))){
|
|
var jobDom = createJob(job);
|
|
jobStatusRunning.appendChild(jobDom);
|
|
}
|
|
nowRunningJobs.push(GetValidSelector(job.id));
|
|
UpdateJobProgress(job.id);
|
|
});
|
|
|
|
runningJobs = nowRunningJobs;
|
|
});
|
|
|
|
jobStatusRunning.childNodes.forEach(child => {
|
|
if(!runningJobs.includes(child.id))
|
|
jobStatusRunning.removeChild(child);
|
|
});
|
|
}
|
|
|
|
function createJob(jobjson){
|
|
var manga;
|
|
if(jobjson.chapter != null)
|
|
manga = jobjson.chapter.parentManga;
|
|
else if(jobjson.manga != null)
|
|
manga = jobjson.manga;
|
|
else return null;
|
|
|
|
|
|
var wrapper = document.createElement("div");
|
|
wrapper.className = "jobWrapper";
|
|
wrapper.id = GetValidSelector(jobjson.id);
|
|
|
|
var image = document.createElement("img");
|
|
image.className = "jobImage";
|
|
image.src = GetCoverUrl(manga.internalId);
|
|
wrapper.appendChild(image);
|
|
|
|
var title = document.createElement("span");
|
|
title.className = "jobTitle";
|
|
if(jobjson.chapter != null)
|
|
title.innerText = `${manga.sortName} - ${jobjson.chapter.fileName}`;
|
|
else if(jobjson.manga != null)
|
|
title.innerText = manga.sortName;
|
|
wrapper.appendChild(title);
|
|
|
|
var progressBar = document.createElement("progress");
|
|
progressBar.className = "jobProgressBar";
|
|
progressBar.id = `jobProgressBar${GetValidSelector(jobjson.id)}`;
|
|
wrapper.appendChild(progressBar);
|
|
|
|
var progressSpan = document.createElement("span");
|
|
progressSpan.className = "jobProgressSpan";
|
|
progressSpan.id = `jobProgressSpan${GetValidSelector(jobjson.id)}`;
|
|
progressSpan.innerText = "0% 00:00:00";
|
|
wrapper.appendChild(progressSpan);
|
|
|
|
var cancelSpan = document.createElement("span");
|
|
cancelSpan.className = "jobCancel";
|
|
cancelSpan.innerText = "Cancel";
|
|
cancelSpan.addEventListener("click", () => CancelJob(jobjson.id));
|
|
wrapper.appendChild(cancelSpan);
|
|
|
|
return wrapper;
|
|
}
|
|
|
|
function ShowJobQueue(){
|
|
jobStatusView.style.display = "initial";
|
|
}
|
|
|
|
function UpdateJobProgress(jobId){
|
|
GetProgress(jobId).then((json) => {
|
|
var progressBar = document.querySelector(`#jobProgressBar${GetValidSelector(jobId)}`);
|
|
var progressSpan = document.querySelector(`#jobProgressSpan${GetValidSelector(jobId)}`);
|
|
if(progressBar != null && json.progress != 0){
|
|
progressBar.value = json.progress;
|
|
}
|
|
if(progressSpan != null){
|
|
var percentageStr = "0%";
|
|
var timeleftStr = "00:00:00";
|
|
if(json.progress != 0){
|
|
percentageStr = Intl.NumberFormat("en-US", { style: "percent"}).format(json.progress);
|
|
timeleftStr = json.timeRemaining.split('.')[0];
|
|
}
|
|
progressSpan.innerText = `${percentageStr} ${timeleftStr}`;
|
|
}
|
|
});
|
|
}
|
|
|
|
function GetValidSelector(str){
|
|
var clean = [...str.matchAll(/[a-zA-Z0-9]*-*_*/g)];
|
|
return clean.join('');
|
|
}
|
|
|
|
const stringToColour = (str) => {
|
|
let hash = 0;
|
|
str.split('').forEach(char => {
|
|
hash = char.charCodeAt(0) + ((hash << 5) - hash)
|
|
})
|
|
let colour = '#'
|
|
for (let i = 0; i < 3; i++) {
|
|
const value = (hash >> (i * 8)) & 0xff
|
|
colour += value.toString(16).padStart(2, '0')
|
|
}
|
|
return colour
|
|
} |