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);
})
})
|