aboutsummaryrefslogtreecommitdiff
path: root/scripts/downloads.js
diff options
context:
space:
mode:
author0neGal <mail@0negal.com>2024-02-06 23:52:42 +0100
committer0neGal <mail@0negal.com>2024-02-06 23:52:42 +0100
commit4385ad45b0c4cb9a46f387ed3b54bd363f3de2ef (patch)
tree15aead61c35373d11eace9561038730af6f68644 /scripts/downloads.js
parentecc2a8f7f71ce530abb39e325e4343854ed64491 (diff)
downloadViper-4385ad45b0c4cb9a46f387ed3b54bd363f3de2ef.tar.gz
Viper-4385ad45b0c4cb9a46f387ed3b54bd363f3de2ef.zip
rename scripts/downloads_count.js to downloads.js
Diffstat (limited to 'scripts/downloads.js')
-rw-r--r--scripts/downloads.js278
1 files changed, 278 insertions, 0 deletions
diff --git a/scripts/downloads.js b/scripts/downloads.js
new file mode 100644
index 0000000..add7d73
--- /dev/null
+++ b/scripts/downloads.js
@@ -0,0 +1,278 @@
+const https = require("https");
+const args = require("minimist")(process.argv.slice(2), {
+ boolean: [
+ "help",
+ "total",
+ "releases",
+ "sort-releases",
+ "total-platforms",
+ "include-prereleases"
+ ],
+
+ default: {
+ "help": false,
+ "total": true,
+ "releases": true,
+ "sort-releases": false,
+ "total-platforms": true,
+ "include-prereleases": false
+ }
+})
+
+// help message
+if (args["help"]) {
+ console.log(`options:
+ --help shows this help message
+ --no-total dont show total downloads
+ --no-releases dont show individual releases
+ --sort-releases sorts releases by download count
+ --no-total-platforms hides individual total platform downloads
+ --include-prereleases includes prereleases when listing out
+ individual releases
+ `.trim()) // the trim removes the last blank newline
+
+ process.exit(0);
+}
+
+// when parsing releases, these will be filled
+let releases = {};
+let total = {
+ all: 0,
+ linux: 0,
+ windows: 0
+}
+
+// calculates what percentage `value` is of `total`
+let percent = (total, value) => {
+ return (value / total * 100).toFixed(2) + "%";
+}
+
+// parses a release object from the GitHub API, and then it changes
+// `releases` and `total` accordingly
+let parse_release = (release) => {
+ if (release.prerelease && ! args["include-prereleases"]) {
+ return;
+ }
+
+ let name = release.name;
+ let assets = release.assets;
+
+ // run through downloadable files from release
+ for (let i = 0; i < assets.length; i++) {
+ // dont count blockmaps
+ if (assets[i].name.match("blockmap")) {
+ continue;
+ }
+
+ switch(assets[i].name) {
+ // dont count these files
+ case "latest.yml":
+ case "latest-linux.yml":
+ continue;
+
+ default:
+ let platform;
+ let downloads = assets[i].download_count;
+
+ // assume platform is Windows if filename ends with
+ // `.exe`, and Linux if not
+ if (assets[i].name.endsWith(".exe")) {
+ platform = "windows";
+ } else {
+ platform = "linux";
+ }
+
+ // create new object for this release in `releases` if
+ // it doesn't already have one
+ if (! releases[name]) {
+ releases[name] = {
+ all: 0,
+ linux: 0,
+ windows: 0
+ }
+ }
+
+ // add total download counts
+ total.all += downloads;
+ releases[name].all += downloads;
+
+ // add platform specific download counts
+ total[platform] += downloads;
+ releases[name][platform] += downloads;
+ }
+ }
+}
+
+// pads out `str` until it's `length` long
+let pad = (str, length) => {
+ str = String(str);
+
+ while (str.length < length) {
+ str += " ";
+ }
+
+ return str;
+}
+
+// takes in `obj` and prints out a table based on it, each key in the
+// objects inside `obj` will be used as a column, and it'll attempt to
+// pad them so it the output looks properly "columnized"
+let print_table = (obj) => {
+ // keep track of the longest value of a key
+ let max_lengths = {};
+
+ // run through all the keys
+ for (let i in obj) {
+ for (let ii in obj[i]) {
+ // get length of current key
+ let length = String(obj[i][ii]).length;
+
+ // if the currently longest value for this type of key is
+ // smaller than `length`, then we make `length` the newest
+ // longest value for this type of key, the same happens if
+ // there's not been a registered longest key for this type
+ // of key yet
+ if (max_lengths[ii] < length || ! max_lengths[ii]) {
+ max_lengths[ii] = length;
+ }
+ }
+ }
+
+ // run through object again
+ for (let i in obj) {
+ // we'll add to this, then print it later
+ let line_str = "";
+
+ // run through keys
+ for (let ii in obj[i]) {
+ // add value to `line_str` padding it to the longest found
+ // value for this type of key and adding 5 for some margin
+ line_str += pad(obj[i][ii], max_lengths[ii] + 5);
+ }
+
+ // print the line of this table out
+ console.log(line_str);
+ }
+}
+
+let parse_json = (json) => {
+ // parse `json`
+ json = JSON.parse(json);
+
+ // run through releases and parse them
+ for (let i = 0; i < json.length; i++) {
+ parse_release(json[i]);
+ }
+
+ // should we should print the individual release stats?
+ if (args["releases"]) {
+ // should we sort the releases?
+ if (args["sort-releases"]) {
+ // the finalized and sorted `releases` will go here
+ let sorted = {};
+
+ // sort `releases` using the `.all` property
+ releases = Object.keys(releases).sort((a, b) => {
+ return releases[b].all - releases[a].all;
+ }).forEach((key) => {
+ sorted[key] = releases[key];
+ })
+
+ // set `releases` to now be the sorted version
+ releases = sorted;
+ }
+
+ // initialize `table` with a header
+ let table = [{
+ version: "VERSION",
+ total: "TOTAL",
+ windows: "WINDOWS",
+ linux: "LINUX"
+ }]
+
+ // runs through `releases` adding the various lines of the table
+ // to `table`, essentially converting it to something we can use
+ // `print_table()` on and nothing else
+ for (let i in releases) {
+ table.push({
+ version: i,
+
+ total: releases[i].all,
+
+ windows: releases[i].windows + " (" + percent(
+ releases[i].all, releases[i].windows
+ ) + ")",
+
+ linux: releases[i].linux + " (" + percent(
+ releases[i].all, releases[i].linux
+ ) + ")"
+ })
+ }
+
+ // print the finalized table
+ print_table(table);
+ }
+
+ // if we dont want to print the total downloads, then we just exit
+ if (! args["total"]) {
+ process.exit(0);
+ }
+
+ // if we've already printed the list of releases, we add an extra
+ // space between this and the total
+ if (args["releases"]) {
+ console.log();
+ }
+
+ // print out the total
+ console.log("Total downloads: " + total.all);
+
+ // if we shouldn't print the platform distribution, then these empty
+ // strings will be used instead
+ let linux_percent = "";
+ let windows_percent = "";
+
+ // get the percent of platform distribution
+ if (args["total-platforms"]) {
+ let linux_percent =
+ "(" + percent(total.all, total.linux) + ")";
+
+ let windows_percent =
+ "(" + percent(total.all, total.windows) + ")";
+ }
+
+ // print Windows platform distribution
+ console.log(
+ " Windows: " +
+ total.windows, windows_percent
+ )
+
+ // print Linux platform distribution
+ console.log(
+ " Linux: " +
+ total.linux, linux_percent
+ )
+}
+
+let link = "/repos/0neGal/viper/releases";
+
+// request info about releases via GitHub's API
+https.get({
+ host: "api.github.com",
+ port: 443,
+ path: link,
+ method: "GET",
+ headers: { "User-Agent": "viper" }
+}, (res) => {
+ res.setEncoding("utf8");
+ let res_data = "";
+
+ res.on("data", data => {
+ res_data += data;
+ })
+
+ // we got the data, now lets parse it!
+ res.on("end", () => {
+ parse_json(res_data);
+ })
+})