Last active
April 26, 2023 13:39
-
-
Save stefansundin/f9df6c5e0fd184c60709 to your computer and use it in GitHub Desktop.
Userscript that shows you the download count for Launchpad packages. Be sure to go to the "View all builds" view. (Read the source code for notes!). Click the [Raw] button to install!
This file contains 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
// ==UserScript== | |
// @name Launchpad Download Count | |
// @namespace https://gist.github.com/stefansundin/ | |
// @homepage https://gist.github.com/stefansundin/f9df6c5e0fd184c60709 | |
// @downloadURL https://gist.github.com/stefansundin/f9df6c5e0fd184c60709/raw/launchpad-download-count.user.js | |
// @version 0.3 | |
// @author Stefan Sundin | |
// @description Gets the download count of your Launchpad packages. | |
// @icon https://launchpad.net/favicon.ico | |
// @match https://launchpad.net/~*/+archive/ubuntu/* | |
// @match https://launchpad.net/~*/+archive/ubuntu/*/+builds* | |
// @grant GM_xmlhttpRequest | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @grant GM_deleteValue | |
// ==/UserScript== | |
// Note: Be patient, getting these results take a while, probably due to log analyzing on Launchpad's end. | |
// Sometimes you have to give it more than one try. | |
// NOTE: I have not yet tackled pagination, so you may have problems if you browse a big package! | |
// Patches and comments are welcome! | |
// To get more detailed stats, including very nice graphs, see this ppa: | |
// https://launchpad.net/~jfi/+archive/ubuntu/ppastats | |
// Configuration options: | |
var print_n_daily = GM_getValue('config_print_n_daily', 3); | |
// To change config, uncomment this: | |
//GM_setValue('config_print_n_daily', print_n_daily=15); | |
// This should preserve the value, even when the script updates. | |
// Go back to defaults with: (requires two refreshes) | |
//GM_deleteValue('config_print_n_daily'); | |
var api = 'https://api.launchpad.net/1.0/'; // this api version has to be updated before April 2015, see https://launchpad.net/+apidoc/ | |
var paths = window.location.pathname.split('/'); | |
var user = paths[1]; | |
var pkg = paths[4]; | |
var total_count = 0; | |
var total_count_div = document.createElement('div'); | |
var fetched = []; | |
var spinner = "data:image/gif;base64,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"; | |
function add_to_total(n) { | |
total_count = total_count+n; | |
total_count_div.innerHTML = 'Total downloads: '+total_count; | |
} | |
function get_rows() { | |
return document.getElementsByClassName('listing')[0].getElementsByClassName('build-row'); | |
} | |
// sorts result from getDailyDownloadTotals | |
function sort_dates(o) { | |
var a = []; | |
for (d in o) { | |
a.push(d); | |
} | |
return a.map(function(d) { | |
return { date: d, count: o[d] }; | |
}).sort(function(a, b) { | |
return new Date(b.date) - new Date(a.date); | |
}); | |
} | |
function getDownloadCount(pub_id, ver, arch, entry) { | |
return function(res) { | |
var key = [user, pkg, ver, arch].join('/'); | |
var real_pub_id = GM_getValue(key, null); | |
if (fetched.indexOf(key) != -1) return; | |
var rows = get_rows(); | |
var row = null; | |
var i; | |
for (i=0; i < rows.length; i++) { | |
var text = rows[i].getElementsByTagName('a')[0].textContent; | |
if (text.indexOf(arch) == -1 || text.indexOf(ver) == -1) continue; | |
row = rows[i]; | |
break; | |
} | |
if (row == null) return; | |
var build_id = row.getElementsByTagName('a')[0].pathname.match(/\/(\d+)$/)[1]; | |
var td = row.getElementsByTagName('td')[2]; | |
if (res.status != 200) { | |
console.log(res); | |
if (real_pub_key == null) { | |
GM_deleteValue(key); | |
} | |
setTimeout(function() { | |
if (fetched.indexOf(key) != -1) return; | |
if (td.childNodes[0].tagName == "IMG") { | |
td.removeChild(td.firstChild); | |
} | |
if (td.childNodes.length > 0) { | |
td.appendChild(document.createElement('br')); | |
} | |
td.appendChild(document.createTextNode('Error ('+res.status+')')); | |
}, 5000); | |
return; | |
} | |
fetched.push(key); | |
//GM_setValue(build_id, pub_id); | |
GM_setValue(key, pub_id); | |
var n = parseInt(res.responseText, 10); | |
td.innerHTML = 'Downloads: '+n; | |
add_to_total(n); | |
console.log(pub_id, ver, arch, n); | |
if (n == 0 || print_n_daily == 0) return; | |
GM_xmlhttpRequest({ | |
url: api+[user, '+archive', paths[3], pkg, '+binarypub', pub_id].join('/')+'?ws.op=getDailyDownloadTotals', | |
// e.g. https://api.launchpad.net/1.0/~stefansundin/+archive/ubuntu/truecrypt/+binarypub/50830085?ws.op=getDailyDownloadTotals | |
method: 'GET', | |
onload: function(res) { | |
var daily = sort_dates(JSON.parse(res.responseText)); | |
console.log('daily', ver, arch, daily); | |
for (var i in daily.slice(0, print_n_daily)) { | |
td.appendChild(document.createElement('br')); | |
td.appendChild(document.createTextNode(daily[i].date+': '+daily[i].count)); | |
} | |
} | |
}); | |
}; | |
} | |
function insertAfter(insert, after) { | |
after.parentNode.insertBefore(insert, after.nextSibling); | |
} | |
if (paths.length == 5) { | |
var links = document.getElementsByClassName('menu-link-packages'); | |
console.log(links); | |
var a = document.createElement('a'); | |
a.href = '+builds?build_state=built'; | |
a.className = 'sprite info'; | |
a.appendChild(document.createTextNode('View download counts')); | |
links[0].parentNode.appendChild(a.cloneNode(true)); | |
var li = document.createElement('li'); | |
li.appendChild(a.cloneNode(true)); | |
insertAfter(li, links[1].parentNode); | |
} | |
else { | |
var rows = get_rows(); | |
if (rows.length != 0) { | |
var i; | |
var gif = document.createElement('img'); | |
gif.setAttribute('src', spinner); | |
for (i=0; i < rows.length; i++) { | |
var row = rows[i]; | |
var td = document.createElement('td'); | |
td.style.verticalAlign = 'middle'; | |
if (row.getElementsByTagName('img')[0].alt == '[FULLYBUILT]') { | |
td.appendChild(gif.cloneNode()); | |
} | |
row.appendChild(td); | |
//var build_id = row.getElementsByTagName('a')[0].pathname.match(/\/(\d+)$/)[1]; | |
//var pub_id = GM_getValue(build_id, null); | |
//console.log(pub_id); | |
} | |
document.getElementById('maincontent').appendChild(total_count_div); | |
add_to_total(0); | |
GM_xmlhttpRequest({ | |
url: api+[user, '+archive', pkg].join('/')+'?ws.op=getPublishedBinaries&ws.size=150', | |
// e.g. https://api.launchpad.net/1.0/~stefansundin/+archive/truecrypt?ws.op=getPublishedBinaries&ws.size=150 | |
method: 'GET', | |
onload: function(res) { | |
var json = JSON.parse(res.responseText); | |
console.log(json); | |
json.entries.forEach(function(entry) { | |
var ver = entry.binary_package_version; | |
var arch = entry.distro_arch_series_link.match(/\/([a-z0-9]+)$/)[1]; | |
var pub_id = entry.self_link.match(/\/(\d+)$/)[1]; | |
var key = [user, pkg, ver, arch].join('/'); | |
var real_pub_id = GM_getValue(key, null); | |
console.log(real_pub_id, pub_id, key, entry); | |
if (real_pub_id != null && pub_id != real_pub_id) return; | |
GM_xmlhttpRequest({ | |
url: api+[user, '+archive', paths[3], pkg, '+binarypub', pub_id].join('/')+'?ws.op=getDownloadCount', | |
// e.g. https://api.launchpad.net/1.0/~stefansundin/+archive/ubuntu/truecrypt/+binarypub/50830085?ws.op=getDownloadCount | |
method: 'GET', | |
onload: getDownloadCount(pub_id, ver, arch, entry) | |
}); | |
}); | |
} | |
}); | |
} | |
} |
This awesome script still works !! 🎉
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Awesome! thank you