You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
5.5 KiB
196 lines
5.5 KiB
4 years ago
|
import { uniqWith } from 'lodash';
|
||
|
import RadarrAPI from '../api/radarr';
|
||
|
import SonarrAPI from '../api/sonarr';
|
||
|
import { MediaType } from '../constants/media';
|
||
|
import logger from '../logger';
|
||
|
import { getSettings } from './settings';
|
||
|
|
||
|
export interface DownloadingItem {
|
||
|
mediaType: MediaType;
|
||
|
externalId: number;
|
||
|
size: number;
|
||
|
sizeLeft: number;
|
||
|
status: string;
|
||
|
timeLeft: string;
|
||
|
estimatedCompletionTime: Date;
|
||
|
title: string;
|
||
|
}
|
||
|
|
||
|
class DownloadTracker {
|
||
|
private radarrServers: Record<number, DownloadingItem[]> = {};
|
||
|
private sonarrServers: Record<number, DownloadingItem[]> = {};
|
||
|
|
||
|
public getMovieProgress(
|
||
|
serverId: number,
|
||
|
externalServiceId: number
|
||
|
): DownloadingItem[] {
|
||
|
if (!this.radarrServers[serverId]) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
return this.radarrServers[serverId].filter(
|
||
|
(item) => item.externalId === externalServiceId
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public getSeriesProgress(
|
||
|
serverId: number,
|
||
|
externalServiceId: number
|
||
|
): DownloadingItem[] {
|
||
|
if (!this.sonarrServers[serverId]) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
return this.sonarrServers[serverId].filter(
|
||
|
(item) => item.externalId === externalServiceId
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public async resetDownloadTracker() {
|
||
|
this.radarrServers = {};
|
||
|
}
|
||
|
|
||
|
public updateDownloads() {
|
||
|
this.updateRadarrDownloads();
|
||
|
this.updateSonarrDownloads();
|
||
|
}
|
||
|
|
||
|
private async updateRadarrDownloads() {
|
||
|
const settings = getSettings();
|
||
|
|
||
|
// Remove duplicate servers
|
||
|
const filteredServers = uniqWith(settings.radarr, (radarrA, radarrB) => {
|
||
|
return (
|
||
|
radarrA.hostname === radarrB.hostname &&
|
||
|
radarrA.port === radarrB.port &&
|
||
|
radarrA.baseUrl === radarrB.baseUrl
|
||
|
);
|
||
|
});
|
||
|
|
||
|
// Load downloads from Radarr servers
|
||
|
Promise.all(
|
||
|
filteredServers.map(async (server) => {
|
||
|
if (server.syncEnabled) {
|
||
|
const radarr = new RadarrAPI({
|
||
|
apiKey: server.apiKey,
|
||
|
url: RadarrAPI.buildRadarrUrl(server, '/api/v3'),
|
||
|
});
|
||
|
|
||
|
const queueItems = await radarr.getQueue();
|
||
|
|
||
|
this.radarrServers[server.id] = queueItems.map((item) => ({
|
||
|
externalId: item.movieId,
|
||
|
estimatedCompletionTime: new Date(item.estimatedCompletionTime),
|
||
|
mediaType: MediaType.MOVIE,
|
||
|
size: item.size,
|
||
|
sizeLeft: item.sizeleft,
|
||
|
status: item.status,
|
||
|
timeLeft: item.timeleft,
|
||
|
title: item.title,
|
||
|
}));
|
||
|
|
||
|
if (queueItems.length > 0) {
|
||
|
logger.debug(
|
||
|
`Found ${queueItems.length} item(s) in progress on Radarr server: ${server.name}`,
|
||
|
{ label: 'Download Tracker' }
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Duplicate this data to matching servers
|
||
|
const matchingServers = settings.radarr.filter(
|
||
|
(rs) =>
|
||
|
rs.hostname === server.hostname &&
|
||
|
rs.port === server.port &&
|
||
|
rs.baseUrl === server.baseUrl &&
|
||
|
rs.id !== server.id
|
||
|
);
|
||
|
|
||
|
if (matchingServers.length > 0) {
|
||
|
logger.debug(
|
||
|
`Matching download data to ${matchingServers.length} other Radarr server(s)`,
|
||
|
{ label: 'Download Tracker' }
|
||
|
);
|
||
|
}
|
||
|
|
||
|
matchingServers.forEach((ms) => {
|
||
|
if (ms.syncEnabled) {
|
||
|
this.radarrServers[ms.id] = this.radarrServers[server.id];
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
})
|
||
|
);
|
||
|
}
|
||
|
|
||
|
private async updateSonarrDownloads() {
|
||
|
const settings = getSettings();
|
||
|
|
||
|
// Remove duplicate servers
|
||
|
const filteredServers = uniqWith(settings.sonarr, (sonarrA, sonarrB) => {
|
||
|
return (
|
||
|
sonarrA.hostname === sonarrB.hostname &&
|
||
|
sonarrA.port === sonarrB.port &&
|
||
|
sonarrA.baseUrl === sonarrB.baseUrl
|
||
|
);
|
||
|
});
|
||
|
|
||
|
// Load downloads from Radarr servers
|
||
|
Promise.all(
|
||
|
filteredServers.map(async (server) => {
|
||
|
if (server.syncEnabled) {
|
||
|
const radarr = new SonarrAPI({
|
||
|
apiKey: server.apiKey,
|
||
|
url: SonarrAPI.buildSonarrUrl(server, '/api/v3'),
|
||
|
});
|
||
|
|
||
|
const queueItems = await radarr.getQueue();
|
||
|
|
||
|
this.sonarrServers[server.id] = queueItems.map((item) => ({
|
||
|
externalId: item.seriesId,
|
||
|
estimatedCompletionTime: new Date(item.estimatedCompletionTime),
|
||
|
mediaType: MediaType.TV,
|
||
|
size: item.size,
|
||
|
sizeLeft: item.sizeleft,
|
||
|
status: item.status,
|
||
|
timeLeft: item.timeleft,
|
||
|
title: item.title,
|
||
|
}));
|
||
|
|
||
|
if (queueItems.length > 0) {
|
||
|
logger.debug(
|
||
|
`Found ${queueItems.length} item(s) in progress on Sonarr server: ${server.name}`,
|
||
|
{ label: 'Download Tracker' }
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Duplicate this data to matching servers
|
||
|
const matchingServers = settings.sonarr.filter(
|
||
|
(rs) =>
|
||
|
rs.hostname === server.hostname &&
|
||
|
rs.port === server.port &&
|
||
|
rs.baseUrl === server.baseUrl &&
|
||
|
rs.id !== server.id
|
||
|
);
|
||
|
|
||
|
if (matchingServers.length > 0) {
|
||
|
logger.debug(
|
||
|
`Matching download data to ${matchingServers.length} other Sonarr server(s)`,
|
||
|
{ label: 'Download Tracker' }
|
||
|
);
|
||
|
}
|
||
|
|
||
|
matchingServers.forEach((ms) => {
|
||
|
if (ms.syncEnabled) {
|
||
|
this.sonarrServers[ms.id] = this.sonarrServers[server.id];
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
})
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const downloadTracker = new DownloadTracker();
|
||
|
|
||
|
export default downloadTracker;
|