From 42f0481a9a790ca33d6862faf08638186029f32c Mon Sep 17 00:00:00 2001 From: Gronod Date: Wed, 20 May 2026 20:44:08 +0100 Subject: [PATCH] fix: SABnzbd speed assignment and size/progress parsing --- server/clients/SABnzbdClient.js | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/server/clients/SABnzbdClient.js b/server/clients/SABnzbdClient.js index 264d1bd..b02bffb 100644 --- a/server/clients/SABnzbdClient.js +++ b/server/clients/SABnzbdClient.js @@ -58,14 +58,18 @@ class SABnzbdClient extends DownloadClient { // Process active queue items if (queueData.queue && queueData.queue.slots) { - // Find the currently downloading slot (first one with status 'Downloading') - const activeSlot = queueData.queue.slots.find(slot => slot.status === 'Downloading'); - const activeSpeed = activeSlot && clientStatus ? (clientStatus.kbpersec ? clientStatus.kbpersec * 1024 : 0) : 0; + const kbpersec = (queueData.queue && queueData.queue.kbpersec) || (clientStatus && clientStatus.kbpersec) || 0; + const globalSpeed = parseFloat(kbpersec) * 1024; - logToFile(`[SABnzbd:${this.name}] Active slot: ${activeSlot ? activeSlot.nzo_id : 'none'}, Speed: ${activeSpeed}, Client status: ${clientStatus ? JSON.stringify({ kbpersec: clientStatus.kbpersec }) : 'none'}`); + logToFile(`[SABnzbd:${this.name}] Global Speed: ${globalSpeed}, Client status: ${clientStatus ? JSON.stringify({ kbpersec: clientStatus.kbpersec }) : 'none'}`); for (const slot of queueData.queue.slots) { - const slotSpeed = activeSlot === slot ? activeSpeed : 0; + let slotSpeed = 0; + if (slot.status === 'Downloading') { + slotSpeed = globalSpeed; + } else if (slot.status === 'Paused' && slot.kbpersec && parseFloat(slot.kbpersec) > 0) { + slotSpeed = globalSpeed; + } logToFile(`[SABnzbd:${this.name}] Slot ${slot.nzo_id} status ${slot.status}, speed ${slotSpeed}`); downloads.push(this.normalizeDownload(slot, 'queue', slotSpeed)); } @@ -111,8 +115,9 @@ class SABnzbdClient extends DownloadClient { } } - normalizeDownload(slot, source, speed = 0) { + normalizeDownload(slot, source, speed) { const isHistory = source === 'history'; + const finalSpeed = speed !== undefined ? speed : (slot.kbpersec ? parseFloat(slot.kbpersec) * 1024 : 0); // Map SABnzbd statuses to normalized status const statusMap = { @@ -135,10 +140,15 @@ class SABnzbdClient extends DownloadClient { let downloaded = 0; let size = 0; - if (slot.mb && slot.mbleft !== undefined) { - size = slot.mb * 1024 * 1024; // Convert MB to bytes - downloaded = (slot.mb - slot.mbleft) * 1024 * 1024; - progress = slot.mb > 0 ? ((slot.mb - slot.mbleft) / slot.mb) * 100 : 0; + const hasMb = slot.mb !== undefined && slot.mb !== null; + const hasMbLeft = slot.mbleft !== undefined && slot.mbleft !== null; + const mbValue = hasMb ? parseFloat(slot.mb) : 0; + const mbLeftValue = hasMbLeft ? parseFloat(slot.mbleft) : 0; + + if (hasMb && hasMbLeft && mbValue !== 0) { + size = mbValue * 1024 * 1024; // Convert MB to bytes + downloaded = (mbValue - mbLeftValue) * 1024 * 1024; + progress = mbValue > 0 ? ((mbValue - mbLeftValue) / mbValue) * 100 : 0; } else if (slot.size) { // Try to parse size string (e.g., "1.5 GB") const sizeMatch = slot.size.match(/^([\d.]+)\s*(\w+)$/i); @@ -173,7 +183,7 @@ class SABnzbdClient extends DownloadClient { progress: Math.round(progress), size: Math.round(size), downloaded: Math.round(downloaded), - speed: speed, + speed: finalSpeed, eta: this.calculateEta(slot.timeleft || slot.eta), category: slot.cat || undefined, tags: slot.labels ? (Array.isArray(slot.labels) ? slot.labels : slot.labels.split(',')).filter(tag => tag && tag.trim()) : [],