aboutsummaryrefslogtreecommitdiff
path: root/scripts/download_count.js
blob: add7d733c51c5ae842e3dcf20e85b2f66d3c074a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
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);
	})
})