Add JSDoc comments and defensive error handling to DownloadBuilder.js
This commit is contained in:
@@ -1,9 +1,21 @@
|
|||||||
// Copyright (c) 2026 Gordon Bolton. MIT License.
|
// Copyright (c) 2026 Gordon Bolton. MIT License.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DownloadBuilder - Aggregates and matches download data from multiple sources.
|
||||||
|
* This service processes cached data from SABnzbd, qBittorrent, Sonarr, and Radarr to build
|
||||||
|
* a unified view of downloads for each user, matching downloads to media metadata via tags.
|
||||||
|
*/
|
||||||
|
|
||||||
const { mapTorrentToDownload } = require('../utils/qbittorrent');
|
const { mapTorrentToDownload } = require('../utils/qbittorrent');
|
||||||
const TagMatcher = require('./TagMatcher');
|
const TagMatcher = require('./TagMatcher');
|
||||||
const DownloadAssembler = require('./DownloadAssembler');
|
const DownloadAssembler = require('./DownloadAssembler');
|
||||||
|
|
||||||
// Build series map from queue and history records
|
/**
|
||||||
|
* Builds a Map of series metadata from Sonarr queue and history records.
|
||||||
|
* @param {Array} queueRecords - Sonarr queue records
|
||||||
|
* @param {Array} historyRecords - Sonarr history records
|
||||||
|
* @returns {Map} Map of seriesId to series object
|
||||||
|
*/
|
||||||
function buildSeriesMapFromRecords(queueRecords, historyRecords) {
|
function buildSeriesMapFromRecords(queueRecords, historyRecords) {
|
||||||
const seriesMap = new Map();
|
const seriesMap = new Map();
|
||||||
for (const r of queueRecords) {
|
for (const r of queueRecords) {
|
||||||
@@ -15,7 +27,12 @@ function buildSeriesMapFromRecords(queueRecords, historyRecords) {
|
|||||||
return seriesMap;
|
return seriesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build movies map from queue and history records
|
/**
|
||||||
|
* Builds a Map of movie metadata from Radarr queue and history records.
|
||||||
|
* @param {Array} queueRecords - Radarr queue records
|
||||||
|
* @param {Array} historyRecords - Radarr history records
|
||||||
|
* @returns {Map} Map of movieId to movie object
|
||||||
|
*/
|
||||||
function buildMoviesMapFromRecords(queueRecords, historyRecords) {
|
function buildMoviesMapFromRecords(queueRecords, historyRecords) {
|
||||||
const moviesMap = new Map();
|
const moviesMap = new Map();
|
||||||
for (const r of queueRecords) {
|
for (const r of queueRecords) {
|
||||||
@@ -27,7 +44,14 @@ function buildMoviesMapFromRecords(queueRecords, historyRecords) {
|
|||||||
return moviesMap;
|
return moviesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get slot status and speed based on queue status
|
/**
|
||||||
|
* Determines the status and speed for a SABnzbd slot based on queue state.
|
||||||
|
* @param {Object} slot - SABnzbd queue slot
|
||||||
|
* @param {string} queueStatus - Overall queue status (e.g., 'Paused')
|
||||||
|
* @param {string} queueSpeed - Queue speed string
|
||||||
|
* @param {string} queueKbpersec - Queue speed in KB/s
|
||||||
|
* @returns {Object} Object with status and speed properties
|
||||||
|
*/
|
||||||
function getSlotStatusAndSpeed(slot, queueStatus, queueSpeed, queueKbpersec) {
|
function getSlotStatusAndSpeed(slot, queueStatus, queueSpeed, queueKbpersec) {
|
||||||
if (queueStatus === 'Paused') {
|
if (queueStatus === 'Paused') {
|
||||||
return { status: 'Paused', speed: '0' };
|
return { status: 'Paused', speed: '0' };
|
||||||
@@ -38,7 +62,12 @@ function getSlotStatusAndSpeed(slot, queueStatus, queueSpeed, queueKbpersec) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match SABnzbd queue slots to Sonarr/Radarr activity
|
/**
|
||||||
|
* Matches SABnzbd queue slots to Sonarr/Radarr activity using download IDs and title matching.
|
||||||
|
* @param {Array} slots - SABnzbd queue slots
|
||||||
|
* @param {Object} context - Matching context with records, maps, and user info
|
||||||
|
* @returns {Array} Array of matched download objects
|
||||||
|
*/
|
||||||
function matchSabSlots(slots, context) {
|
function matchSabSlots(slots, context) {
|
||||||
const {
|
const {
|
||||||
sonarrQueueRecords,
|
sonarrQueueRecords,
|
||||||
@@ -215,7 +244,12 @@ function matchSabSlots(slots, context) {
|
|||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match SABnzbd history slots to Sonarr/Radarr activity
|
/**
|
||||||
|
* Matches SABnzbd history slots to Sonarr/Radarr activity using title matching.
|
||||||
|
* @param {Array} slots - SABnzbd history slots
|
||||||
|
* @param {Object} context - Matching context with records, maps, and user info
|
||||||
|
* @returns {Array} Array of matched download objects
|
||||||
|
*/
|
||||||
function matchSabHistory(slots, context) {
|
function matchSabHistory(slots, context) {
|
||||||
const {
|
const {
|
||||||
sonarrHistoryRecords,
|
sonarrHistoryRecords,
|
||||||
@@ -313,7 +347,12 @@ function matchSabHistory(slots, context) {
|
|||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match qBittorrent torrents to Sonarr/Radarr activity
|
/**
|
||||||
|
* Matches qBittorrent torrents to Sonarr/Radarr activity using title matching.
|
||||||
|
* @param {Array} torrents - qBittorrent torrent list
|
||||||
|
* @param {Object} context - Matching context with records, maps, and user info
|
||||||
|
* @returns {Array} Array of matched download objects
|
||||||
|
*/
|
||||||
function matchTorrents(torrents, context) {
|
function matchTorrents(torrents, context) {
|
||||||
const {
|
const {
|
||||||
sonarrQueueRecords,
|
sonarrQueueRecords,
|
||||||
@@ -529,9 +568,31 @@ function matchTorrents(torrents, context) {
|
|||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build user downloads from cache snapshot
|
/**
|
||||||
|
* Builds a unified list of downloads for a user from multiple download clients.
|
||||||
|
* Matches SABnzbd and qBittorrent downloads to Sonarr/Radarr activity using tags.
|
||||||
|
* @param {Object} cacheSnapshot - Cached data from all services
|
||||||
|
* @param {Object} options - User context and metadata maps
|
||||||
|
* @param {string} options.username - Lowercase username for tag matching
|
||||||
|
* @param {string} options.usernameSanitized - Original username
|
||||||
|
* @param {boolean} options.isAdmin - Whether user is admin
|
||||||
|
* @param {boolean} options.showAll - Whether to show all users' downloads
|
||||||
|
* @param {Map} options.seriesMap - Map of seriesId to series object
|
||||||
|
* @param {Map} options.moviesMap - Map of movieId to movie object
|
||||||
|
* @param {Map} options.sonarrTagMap - Map of Sonarr tag IDs to labels
|
||||||
|
* @param {Map} options.radarrTagMap - Map of Radarr tag IDs to labels
|
||||||
|
* @param {Map} options.embyUserMap - Map of Emby users for admin view
|
||||||
|
* @returns {Array} Array of download objects for the user
|
||||||
|
*/
|
||||||
function buildUserDownloads(cacheSnapshot, { username, usernameSanitized, isAdmin, showAll, seriesMap, moviesMap, sonarrTagMap, radarrTagMap, embyUserMap }) {
|
function buildUserDownloads(cacheSnapshot, { username, usernameSanitized, isAdmin, showAll, seriesMap, moviesMap, sonarrTagMap, radarrTagMap, embyUserMap }) {
|
||||||
// Handle null/undefined cache data
|
// Input validation
|
||||||
|
if (!cacheSnapshot || typeof cacheSnapshot !== 'object') {
|
||||||
|
console.error('[DownloadBuilder] Invalid cacheSnapshot provided');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Handle null/undefined cache data
|
||||||
const sabnzbdQueue = cacheSnapshot.sabnzbdQueue || { data: { queue: { slots: [] } } };
|
const sabnzbdQueue = cacheSnapshot.sabnzbdQueue || { data: { queue: { slots: [] } } };
|
||||||
const sabnzbdHistory = cacheSnapshot.sabnzbdHistory || { data: { history: { slots: [] } } };
|
const sabnzbdHistory = cacheSnapshot.sabnzbdHistory || { data: { history: { slots: [] } } };
|
||||||
const sonarrQueue = cacheSnapshot.sonarrQueue || { data: { records: [] } };
|
const sonarrQueue = cacheSnapshot.sonarrQueue || { data: { records: [] } };
|
||||||
@@ -599,7 +660,11 @@ function buildUserDownloads(cacheSnapshot, { username, usernameSanitized, isAdmi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return userDownloads;
|
return userDownloads;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[DownloadBuilder] Error building user downloads:', error.message);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
Reference in New Issue
Block a user