Refactor of http client and addition of sonarr anime table

This commit is contained in:
2026-03-08 19:28:04 -06:00
parent 8f049e6704
commit 21a9cc86d8
10 changed files with 206 additions and 54 deletions

View File

@@ -47,6 +47,26 @@
</div>
</div>
<div class="inlineContainer">
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="SonarrAnimeAddress">Sonarr Anime Address (http:port)</label>
<input id="SonarrAnimeAddress" name="SonarrAnimeAddress" type="text" is="emby-input" />
<div class="fieldDescription">The address and port of your sonarr instance.</div>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="SonarrAnimeAPIKey">Sonarr Anime API Key</label>
<input id="SonarrAnimeAPIKey" name="SonarrAnimeAPIKey" type="text" is="emby-input" />
<div class="fieldDescription">The api key used by your sonarr instance</div>
</div>
<div class="inputContainer">
<button id="SonarrAnimeTestConnectionButton" is="emby-button" type="button" class="raised button-submit block emby-button">
<span>Test</span>
</button>
<div class="validation" id="SonarrAnimeConnectionValidation" hidden>
</div>
</div>
</div>
<h3>General Settings</h3>
<div class="inlineContainer">
<div class="inputContainer">

View File

@@ -32,6 +32,14 @@ const startFadeIn = (element, interval = 100) => {
};
// Connection Methods
const testConnectionSonarrAnime = async () => {
var apiKeyElement = document.getElementById('SonarrAnimeAPIKey');
var addressElement = document.getElementById('SonarrAnimeAddress');
var validationElement = document.getElementById('SonarrAnimeConnectionValidation');
await validateConnection(apiKeyElement, addressElement, validationElement, "sonarr");
}
const testConnectionSonarr = async () => {
var apiKeyElement = document.getElementById('SonarrAPIKey');
var addressElement = document.getElementById('SonarrAddress');
@@ -131,6 +139,9 @@ document.querySelector('#RadarrTestConnectionButton')
document.querySelector('#SonarrTestConnectionButton')
.addEventListener('click', testConnectionSonarr);
document.querySelector('#SonarrAnimeTestConnectionButton')
.addEventListener('click', testConnectionSonarrAnime);
document.querySelector('#MediaCleanerConfigPage')
.addEventListener('pageshow', function() {
Dashboard.showLoadingMsg();
@@ -139,6 +150,8 @@ document.querySelector('#MediaCleanerConfigPage')
document.querySelector('#RadarrAddress').value = config.RadarrAddress;
document.querySelector('#SonarrAPIKey').value = config.SonarrAPIKey;
document.querySelector('#SonarrAddress').value = config.SonarrAddress;
document.querySelector('#SonarrAnimeAPIKey').value = config.SonarrAnimeAPIKey;
document.querySelector('#SonarrAnimeAddress').value = config.SonarrAnimeAddress;
document.querySelector('#StaleMediaCutoff').value = config.StaleMediaCutoff;
document.querySelector('#DebugMode').checked = config.DebugMode;
Dashboard.hideLoadingMsg();
@@ -153,6 +166,8 @@ document.querySelector('#MediaCleanerConfigForm')
config.RadarrAddress = document.querySelector('#RadarrAddress').value;
config.SonarrAPIKey = document.querySelector('#SonarrAPIKey').value;
config.SonarrAddress = document.querySelector('#SonarrAddress').value;
config.SonarrAnimeAPIKey = document.querySelector('#SonarrAnimeAPIKey').value;
config.SonarrAnimeAddress = document.querySelector('#SonarrAnimeAddress').value;
config.StaleMediaCutoff = document.querySelector('#StaleMediaCutoff').value;
config.DebugMode = document.querySelector('#DebugMode').checked;
ApiClient.updatePluginConfiguration(MediaCleanerConfig.pluginUniqueId, config).then(function (result) {

View File

@@ -33,6 +33,19 @@
<tbody></tbody>
</table>
<button id="seriesDeleteButton" class="delete-button raised button-submit emby-button" style="visibility: hidden;">Delete</button>
<br>
<h3 id="animeSeriesTitle"></h3>
<table id="animeSeriesTable">
<thead>
<tr>
<th>Name</th>
<th>Seasons</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
<button id="animeSeriesDeleteButton" class="delete-button raised button-submit emby-button" style="visibility: hidden;">Delete</button>
</div>
</div>
</div>

View File

@@ -8,9 +8,11 @@ const refreshFrontEnd = async () => {
var moviesTitle = document.getElementById("moviesTitle");
var seriesTitle = document.getElementById("seriesTitle");
var animeSeriesTitle = document.getElementById("animeSeriesTitle");
moviesTitle.innerHTML = await getMediaCleanerMoviesTitle();
seriesTitle.innerHTML = await getMediaCleanerSeriesTitle();
animeSeriesTitle.innerHTML = await getMediaCleanerAnimeSeriesTitle();
await populateTables();
addClickHandlersToLinks();
@@ -48,6 +50,16 @@ const updateMediaCleanerState = async () => {
return response.json();
};
const getMediaCleanerAnimeSeriesTitle = async () => {
const response = await fetch("/mediacleaner/state/getAnimeSeriesTitle");
if(!response.ok){
throw new Error(`Response status: ${response.status}`);
}
return response.json();
};
const getMediaCleanerSeriesTitle = async () => {
const response = await fetch("/mediacleaner/state/getSeriesTitle");
@@ -72,6 +84,11 @@ const getMediaCleanerMoviesTitle = async () => {
const populateTables = async () => {
var moviesInfo = await getMediaCleanerMovieInfo();
var seriesInfo = await getMediaCleanerSeriesInfo();
var animeSeriesInfo = await getMediaCleanerAnimeSeriesInfo();
var seriesTable = document.getElementById("seriesTable");
var moviesTable = document.getElementById("moviesTable");
var animeSeriesTable = document.getElementById("animeSeriesTable");
var seriesTableBody = seriesTable.getElementsByTagName('tbody')[0];
seriesTableBody.replaceChildren();
@@ -81,6 +98,10 @@ const populateTables = async () => {
moviesTableBody.replaceChildren();
var moviesDeleteButton = document.getElementById('moviesDeleteButton');
var animeSeriesTableBody = animeSeriesTable.getElementsByTagName('tbody')[0];
animeSeriesTableBody.replaceChildren();
var animeSeriesDeleteButton = document.getElementById('animeSeriesDeleteButton');
if (moviesInfo.length > 0){
for(let i = 0; i < moviesInfo.length; i++){
var row = moviesTableBody.insertRow(-1);
@@ -120,7 +141,30 @@ const populateTables = async () => {
var row = seriesTableBody.insertRow(-1);
var cell1 = row.insertCell(0);
cell1.colSpan = columnCount;
cell1.innerHTML = "No stale series found.";
cell1.innerHTML = "No stale tv series found.";
cell1.className = "table-text";
}
if(animeSeriesInfo.length > 0){
for(let i = 0; i < animeSeriesInfo.length; i++){
var row = animeSeriesTableBody.insertRow(-1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2);
cell1.innerHTML = animeSeriesInfo[i].Name;
cell1.className = "table-text";
cell2.innerHTML = animeSeriesInfo[i].Seasons.map(season => season).join(", ");
cell2.className = "table-text";
cell3.appendChild(createCheckbox(animeSeriesInfo[i], animeSeriesTable, animeSeriesDeleteButton));
cell3.className = "table-checkbox"
}
}
else{
var columnCount = animeSeriesTableBody.tHead.rows[0].cells.length;
var row = animeSeriesTableBody.insertRow(-1);
var cell1 = row.insertCell(0);
cell1.colSpan = columnCount;
cell1.innerHTML = "No stale anime series found.";
cell1.className = "table-text";
}
};
@@ -179,8 +223,10 @@ const addClickHandlersToLinks = () => {
const addClickHandlersToDeleteButtons = () => {
const deleteMoviesButtonElement = document.getElementById("moviesDeleteButton");
const deleteSeriesButtonElement = document.getElementById("seriesDeleteButton");
const deleteAnimeSeriesButtonElement = document.getElementById("animeSeriesDeleteButton");
deleteMoviesButtonElement.addEventListener("click", deleteFromRadarr);
deleteSeriesButtonElement.addEventListener("click", deleteFromSonarr);
deleteAnimeSeriesButtonElement.addEventListener("click", deleteFromSonarrAnime);
}
const getCheckedMedia = (table) => {
@@ -219,6 +265,20 @@ const deleteSeriesFromSonarrApi = async (series) => {
}
}
const deleteSeriesFromSonarrAnimeApi = async (series) => {
const response = await fetch("/sonarr/deleteSeriesFromSonarrAnime", {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(series)
});
if(!response.ok){
throw new Error(`Response status: ${response.status}`)
}
}
const deleteFromRadarr = async () => {
const selectedMovies = getCheckedMedia(moviesTable);
selectedMovies.forEach(async movie => await deleteMovieFromRadarrApi(movie));
@@ -231,6 +291,12 @@ const deleteFromSonarr = () => {
refreshFrontEnd();
}
const deleteFromAnimeSonarr = () => {
const selectedSeries = getCheckedMedia(animeSeriesTable);
selectedSeries.forEach(async series => await deleteSeriesFromSonarrApi(series));
refreshFrontEnd();
}
const finishLoading = () => {
const loadingElement = document.getElementById("loading");
const homepage = document.getElementById("homepage");