Last active
April 26, 2025 07:28
-
-
Save FoxxMD/f3045b4e2c0afe39631c9550bd131133 to your computer and use it in GitHub Desktop.
Qbittorrent get total size, downloaded, uploaded, and overall ratio (WebUI only)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Tested on qBittorrent 4.6.1 | |
// | |
// 1. open qbittorent web interface | |
// 1a. (optionally) filter to just the torrents that should be totalled | |
// 1b. MAY need to ensure any/all columns to be totalled are enabled -> Size, Downloaded, Uploaded | |
// 2. open developer tools | |
// 3. copy and paste the *entirety* of the below code into the developer tools console and hit enter | |
// | |
// Will print totals in MiB/GiB/TiB for: | |
// * Size + Min/Max/Avg | |
// * Downloaded + % of Size + Min/Max/Avg | |
// * Uploaded + % of Size + Min/Max/Avg | |
// and Ratio + Min/Max/Avg | |
(function() { | |
const sizeIndex = Array.from(document.querySelector('tr.dynamicTableHeader').childNodes).findIndex(x => x.title === 'Size'); | |
const downloadedIndex = Array.from(document.querySelector('tr.dynamicTableHeader').childNodes).findIndex(x => x.title === 'Downloaded'); | |
const uploadedIndex = Array.from(document.querySelector('tr.dynamicTableHeader').childNodes).findIndex(x => x.title === 'Uploaded'); | |
const ratioIndex = Array.from(document.querySelector('tr.dynamicTableHeader').childNodes).findIndex(x => x.title === 'Ratio'); | |
const tibThreshold = 1048576; | |
if(sizeIndex === -1 && downloadedIndex === -1 && uploadedIndex === -1) { | |
console.warn('Must have at least one of the following columns enabled to compute some statistics: Size, Downloaded, Uploaded'); | |
return; | |
} | |
const getMibVal = (valueStr, unit) => { | |
const val = parseFloat(valueStr); | |
if(val === 0) { | |
return 0; | |
} | |
switch (unit.toLocaleLowerCase()) { | |
case 'tib': | |
return val * 1024 * 1024; | |
case 'gib': | |
return val * 1024; | |
case 'mib': | |
return val; | |
case 'kib': | |
return val / 1024; | |
case 'B': | |
return val / 1024 / 1024; | |
} | |
} | |
const getTotalBreakdown = (val) => { | |
return [ | |
`${((val / 1024) / 1024).toLocaleString('en', {maximumFractionDigits: 2})} TiB`, | |
`${(val / 1024).toLocaleString('en', {maximumFractionDigits: 2})} GiB`, | |
`${val.toLocaleString('en', {maximumFractionDigits: 2})} MiB`, | |
].join(' == '); | |
} | |
const getHumanSize = (valMib) => { | |
if(valMib === 0) { | |
return '0 B'; | |
} | |
if(valMib < 1) { | |
return `${(valMib / 1024).toLocaleString('en', {maximumFractionDigits: 2})} KiB` | |
} | |
if(valMib >= tibThreshold) { | |
return `${(valMib / 1024 / 1024).toLocaleString('en', {maximumFractionDigits: 2})} TiB` | |
} | |
if(valMib >= 1024) { | |
return `${(valMib / 1024).toLocaleString('en', {maximumFractionDigits: 2})} GiB` | |
} | |
return `${(valMib).toLocaleString('en', {maximumFractionDigits: 2})} MiB` | |
} | |
let mibSize = sizeIndex !== -1 ? 0 : null; | |
let sizeMinMax = [Infinity,0]; | |
let ratio = ratioIndex !== -1 ? 0 : null; | |
let ratioMinMax = [Infinity,0]; | |
let mibDl = downloadedIndex !== -1 ? 0 : null; | |
let dlMinMax = [Infinity,0]; | |
let mibUl = uploadedIndex !== -1 ? 0 : null; | |
let ulMinMax = [Infinity,0]; | |
const elms = document.querySelectorAll('div#torrentsTableDiv tr.torrentsTableContextMenuTarget'); | |
const torNum = elms.length; | |
elms.forEach((row) => { | |
if(mibSize !== null) { | |
const [str, unit] = row.childNodes[sizeIndex].title.split(' '); | |
const val = getMibVal(str, unit); | |
mibSize += val; | |
sizeMinMax = [Math.min(val, sizeMinMax[0]), Math.max(val, sizeMinMax[1])]; | |
} | |
if(mibDl !== null) { | |
const [str, unit] = row.childNodes[downloadedIndex].title.split(' '); | |
const val = getMibVal(str, unit); | |
mibDl += val; | |
dlMinMax = [Math.min(val, dlMinMax[0]), Math.max(val, dlMinMax[1])]; | |
} | |
if(mibDl !== null) { | |
const [str, unit] = row.childNodes[uploadedIndex].title.split(' '); | |
const val = getMibVal(str, unit); | |
mibUl += val; | |
ulMinMax = [Math.min(val, ulMinMax[0]), Math.max(val, ulMinMax[1])]; | |
} | |
if(ratio !== null) { | |
const val = parseFloat(row.childNodes[ratioIndex].title); | |
ratio += val | |
ratioMinMax = [Math.min(val, ratioMinMax[0]), Math.max(val, ratioMinMax[1])]; | |
} | |
}); | |
if(mibSize !== null) { | |
console.log(`${'Size'.padEnd(11,' ')}: ${getTotalBreakdown(mibSize)} | Min ${getHumanSize(sizeMinMax[0])} | Max ${getHumanSize(sizeMinMax[1])} | Avg ${getHumanSize(mibSize / torNum)}`); | |
} | |
if(mibDl !== null) { | |
const parts = [`${'Downloaded'.padEnd(11,' ')}: ${getTotalBreakdown(mibDl)}`]; | |
if(mibSize !== null) { | |
parts.push(`${((mibDl / mibSize) * 100).toLocaleString('en', {maximumFractionDigits: 2})}% of Size`); | |
} | |
parts.push(`Min ${getHumanSize(dlMinMax[0])} | Max ${getHumanSize(dlMinMax[1])} | Avg ${getHumanSize(mibDl / torNum)}`); | |
console.log(parts.join(' | ')); | |
} | |
if(mibUl !== null) { | |
const parts = [`${'Uploaded'.padEnd(11,' ')}: ${getTotalBreakdown(mibUl)}`]; | |
if(mibSize !== null) { | |
parts.push(`${((mibUl / mibSize) * 100).toLocaleString('en', {maximumFractionDigits: 2})}% of Size`); | |
} | |
parts.push(`Min ${getHumanSize(ulMinMax[0])} | Max ${getHumanSize(ulMinMax[1])} | Avg ${getHumanSize(mibUl / torNum)}`); | |
console.log(parts.join(' | ')); | |
} | |
if(mibDl !== null && mibUl !== null) { | |
const parts = [ | |
`${'Ratio'.padEnd(11,' ')}: ${((mibUl / mibDl)).toLocaleString('en', {maximumFractionDigits: 2})}`, | |
`Min ${ratioMinMax[0]} | Max ${ratioMinMax[1]} | Avg ${(ratio / torNum).toLocaleString('en', {maximumFractionDigits: 2})}` | |
]; | |
console.log(parts.join(' | ')); | |
} | |
})(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An alternative that displays on the interface (not written by me) here: https://greasyfork.org/en/scripts/483775-calculate-qbittorrent-selected-torrents-size