|
// ==UserScript== |
|
// @name CurseForge mod download scraper |
|
// @namespace http://tampermonkey.net/ |
|
// @version 0.2 |
|
// @description Scrapes the download count from CurseForge mod pages |
|
// @author You |
|
// @match https://www.curseforge.com/minecraft/mc-mods/* |
|
// @match https://authors.curseforge.com/dashboard |
|
// @match https://authors.curseforge.com/dashboard/projects |
|
// @icon https://www.google.com/s2/favicons?domain=curseforge.com |
|
// @grant GM_setValue |
|
// @grant GM_getValue |
|
// @grant GM_listValues |
|
// @grant GM_deleteValue |
|
// @grant GM_openInTab |
|
// @grant GM_addValueChangeListener |
|
// @grant GM_removeValueChangeListener |
|
// @grant GM_setClipboard |
|
// @grant GM_registerMenuCommand |
|
// @grant GM_unregisterMenuCommand |
|
// @downloadURL https://gist.github.com/thecodewarrior/bf48e0f72ba74e801929859a26fd35e4/raw/CurseForgeDownloadScraper.js |
|
// ==/UserScript== |
|
|
|
(function() { |
|
'use strict'; |
|
|
|
function modUrl(slug) { |
|
return slug === 'author' ? 'https://authors.curseforge.com/dashboard' : 'https://www.curseforge.com/minecraft/mc-mods/' + slug |
|
} |
|
function modKey(slug) { |
|
return slug === 'author' ? 'author' : 'mod:' + slug |
|
} |
|
|
|
function scrapeModPage() { |
|
let path = window.location.pathname.split('/') |
|
let slug = path[path.length-1] |
|
|
|
let candidates = document.querySelectorAll('.w-full.flex.justify-between') |
|
for(let element of candidates) { |
|
let spans = element.querySelectorAll('span') |
|
if(spans.length != 2) |
|
continue |
|
if(spans[0].textContent !== 'Total Downloads') |
|
continue |
|
let downloads = parseInt(spans[1].textContent.replace(/,/g, '')) |
|
console.log(downloads) |
|
GM_setValue(modKey(slug), JSON.stringify({ |
|
slug, |
|
downloads |
|
})) |
|
break |
|
} |
|
} |
|
|
|
function scrapeDashboard() { |
|
let element = document.querySelector('.e-dashboard-stats .e-tile-count') |
|
let downloads = element.textContent |
|
console.log(downloads) |
|
|
|
GM_setValue('author', JSON.stringify({ |
|
slug: 'author', |
|
downloads |
|
})) |
|
} |
|
|
|
function loadModStats(slug, index) { |
|
return new Promise((resolve, reject) => { |
|
setTimeout(() => { |
|
let tab = GM_openInTab(modUrl(slug)) |
|
let listener = GM_addValueChangeListener(modKey(slug), (name, oldValue, newValue, remote) => { |
|
tab.close() |
|
resolve(JSON.parse(newValue)) |
|
GM_removeValueChangeListener(listener) |
|
GM_deleteValue(modKey(slug)) |
|
}) |
|
}, index * 500) |
|
}) |
|
} |
|
|
|
function launchScrapeManager() { |
|
let input = window.prompt( |
|
'Enter the comma-separated mod slugs (or `author` for the author dashboard)', |
|
GM_getValue('previous-slugs') ?? 'author' |
|
) |
|
GM_setValue('previous-slugs', input) |
|
|
|
let slugs = input.split(',').map(it => it.trim()) |
|
|
|
for(let slug of slugs) { |
|
GM_deleteValue(modKey(slug)) |
|
} |
|
|
|
Promise.all(slugs.map((slug, index) => loadModStats(slug, index))).then(values => { |
|
let now = new Date().toLocaleString('en-US', { hour12: false }).replace(',', '') |
|
var text = now + "\t" + values.map(it => it.downloads).join('\t') |
|
GM_setClipboard(text) |
|
window.alert('Downloads copied successfully') |
|
}) |
|
} |
|
|
|
if(window.location.href === 'https://authors.curseforge.com/dashboard/projects') { |
|
GM_registerMenuCommand("Copy download counts", launchScrapeManager); |
|
} else if(window.location.href === 'https://authors.curseforge.com/dashboard') { |
|
scrapeDashboard() |
|
} else { |
|
scrapeModPage() |
|
} |
|
})(); |