osrs-json-hiscores 2.5.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/hiscores.js CHANGED
@@ -1,384 +1,387 @@
1
- "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
- return new (P || (P = Promise))(function (resolve, reject) {
16
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
- step((generator = generator.apply(thisArg, _arguments || [])).next());
20
- });
21
- };
22
- var __generator = (this && this.__generator) || function (thisArg, body) {
23
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
- function verb(n) { return function (v) { return step([n, v]); }; }
26
- function step(op) {
27
- if (f) throw new TypeError("Generator is already executing.");
28
- while (_) try {
29
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
- if (y = 0, t) op = [op[0] & 2, t.value];
31
- switch (op[0]) {
32
- case 0: case 1: t = op; break;
33
- case 4: _.label++; return { value: op[1], done: false };
34
- case 5: _.label++; y = op[1]; op = [0]; continue;
35
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
- default:
37
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
- if (t[2]) _.ops.pop();
42
- _.trys.pop(); continue;
43
- }
44
- op = body.call(thisArg, _);
45
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
- }
48
- };
49
- Object.defineProperty(exports, "__esModule", { value: true });
50
- exports.getActivityPage = exports.getSkillPage = exports.getStatsByGamemode = exports.getStats = exports.parseStats = exports.getRSNFormat = void 0;
51
- var jsdom_1 = require("jsdom");
52
- var utils_1 = require("./utils");
53
- /**
54
- * Screen scrapes the hiscores to get the formatted rsn of a player.
55
- *
56
- * @param rsn Username of the player.
57
- * @returns Formatted version of the rsn.
58
- */
59
- function getRSNFormat(rsn) {
60
- return __awaiter(this, void 0, void 0, function () {
61
- var url, response, dom, spans, nameSpan, _a;
62
- return __generator(this, function (_b) {
63
- switch (_b.label) {
64
- case 0:
65
- if (typeof rsn !== 'string') {
66
- throw Error('RSN must be a string');
67
- }
68
- else if (!/^[a-zA-Z0-9 _-]+$/.test(rsn)) {
69
- throw Error('RSN contains invalid character');
70
- }
71
- else if (rsn.length > 12 || rsn.length < 1) {
72
- throw Error('RSN must be between 1 and 12 characters');
73
- }
74
- url = utils_1.getPlayerTableURL('main', rsn);
75
- _b.label = 1;
76
- case 1:
77
- _b.trys.push([1, 3, , 4]);
78
- return [4 /*yield*/, utils_1.httpGet(url)];
79
- case 2:
80
- response = _b.sent();
81
- dom = new jsdom_1.JSDOM(response.data);
82
- spans = dom.window.document.querySelectorAll('span[style="color:#AA0022;"]');
83
- if (spans.length >= 2) {
84
- nameSpan = spans[1];
85
- return [2 /*return*/, utils_1.rsnFromElement(nameSpan)];
86
- }
87
- throw Error('Player not found');
88
- case 3:
89
- _a = _b.sent();
90
- throw Error('Player not found');
91
- case 4: return [2 /*return*/];
92
- }
93
- });
94
- });
95
- }
96
- exports.getRSNFormat = getRSNFormat;
97
- /**
98
- * Parses CSV string of raw stats and returns a stats object.
99
- *
100
- * @param csv Raw CSV from the official OSRS API.
101
- * @returns Parsed stats object.
102
- */
103
- function parseStats(csv) {
104
- var splitCSV = csv
105
- .split('\n')
106
- .filter(function (entry) { return !!entry; })
107
- .map(function (stat) { return stat.split(','); });
108
- var skillObjects = splitCSV
109
- .filter(function (stat) { return stat.length === 3; })
110
- .map(function (stat) {
111
- var rank = stat[0], level = stat[1], xp = stat[2];
112
- var skill = {
113
- rank: parseInt(rank, 10),
114
- level: parseInt(level, 10),
115
- xp: parseInt(xp, 10)
116
- };
117
- return skill;
118
- });
119
- var activityObjects = splitCSV
120
- .filter(function (stat) { return stat.length === 2; })
121
- .map(function (stat) {
122
- var rank = stat[0], score = stat[1];
123
- var activity = {
124
- rank: parseInt(rank, 10),
125
- score: parseInt(score, 10)
126
- };
127
- return activity;
128
- });
129
- var leaguePoints = activityObjects.splice(0, 1)[0];
130
- var bhObjects = activityObjects.splice(0, utils_1.BH_MODES.length);
131
- var clueObjects = activityObjects.splice(0, utils_1.CLUES.length);
132
- var _a = activityObjects.splice(0, 2), lastManStanding = _a[0], soulWarsZeal = _a[1];
133
- var bossObjects = activityObjects.splice(0, utils_1.BOSSES.length);
134
- var skills = skillObjects.reduce(function (prev, curr, index) {
135
- var newSkills = __assign({}, prev);
136
- newSkills[utils_1.SKILLS[index]] = curr;
137
- return newSkills;
138
- }, {});
139
- var bountyHunter = bhObjects.reduce(function (prev, curr, index) {
140
- var newBH = __assign({}, prev);
141
- newBH[utils_1.BH_MODES[index]] = curr;
142
- return newBH;
143
- }, {});
144
- var clues = clueObjects.reduce(function (prev, curr, index) {
145
- var newClues = __assign({}, prev);
146
- newClues[utils_1.CLUES[index]] = curr;
147
- return newClues;
148
- }, {});
149
- var bosses = bossObjects.reduce(function (prev, curr, index) {
150
- var newBosses = __assign({}, prev);
151
- newBosses[utils_1.BOSSES[index]] = curr;
152
- return newBosses;
153
- }, {});
154
- var stats = {
155
- skills: skills,
156
- leaguePoints: leaguePoints,
157
- bountyHunter: bountyHunter,
158
- lastManStanding: lastManStanding,
159
- soulWarsZeal: soulWarsZeal,
160
- clues: clues,
161
- bosses: bosses
162
- };
163
- return stats;
164
- }
165
- exports.parseStats = parseStats;
166
- /**
167
- * Fetches stats from the OSRS API and consolidates the info into a player object.
168
- *
169
- * **Note:** This function will make up to 5 separate network requests.
170
- * As such, it is highly subject to the performance of the official OSRS API.
171
- *
172
- * @param rsn Username of the player.
173
- * @returns Player object.
174
- */
175
- function getStats(rsn) {
176
- return __awaiter(this, void 0, void 0, function () {
177
- var mainRes, otherResponses, ironRes, hcRes, ultRes, formattedName, player;
178
- return __generator(this, function (_a) {
179
- switch (_a.label) {
180
- case 0:
181
- if (typeof rsn !== 'string') {
182
- throw Error('RSN must be a string');
183
- }
184
- else if (!/^[a-zA-Z0-9 _]+$/.test(rsn)) {
185
- throw Error('RSN contains invalid character');
186
- }
187
- else if (rsn.length > 12 || rsn.length < 1) {
188
- throw Error('RSN must be between 1 and 12 characters');
189
- }
190
- return [4 /*yield*/, utils_1.httpGet(utils_1.getStatsURL('main', rsn))];
191
- case 1:
192
- mainRes = _a.sent();
193
- if (!(mainRes.status === 200)) return [3 /*break*/, 3];
194
- return [4 /*yield*/, Promise.all([
195
- utils_1.httpGet(utils_1.getStatsURL('ironman', rsn)).catch(function (err) { return err; }),
196
- utils_1.httpGet(utils_1.getStatsURL('hardcore', rsn)).catch(function (err) { return err; }),
197
- utils_1.httpGet(utils_1.getStatsURL('ultimate', rsn)).catch(function (err) { return err; }),
198
- getRSNFormat(rsn).catch(function () { return undefined; })
199
- ])];
200
- case 2:
201
- otherResponses = _a.sent();
202
- ironRes = otherResponses[0], hcRes = otherResponses[1], ultRes = otherResponses[2], formattedName = otherResponses[3];
203
- player = {
204
- name: formattedName !== null && formattedName !== void 0 ? formattedName : rsn,
205
- mode: 'main',
206
- dead: false,
207
- deulted: false,
208
- deironed: false
209
- };
210
- player.main = parseStats(mainRes.data);
211
- if (ironRes.status === 200) {
212
- player.ironman = parseStats(ironRes.data);
213
- if (hcRes.status === 200) {
214
- player.mode = 'hardcore';
215
- player.hardcore = parseStats(hcRes.data);
216
- if (player.ironman.skills.overall.xp !== player.hardcore.skills.overall.xp) {
217
- player.dead = true;
218
- player.mode = 'ironman';
219
- }
220
- if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
221
- player.deironed = true;
222
- player.mode = 'main';
223
- }
224
- }
225
- else if (ultRes.status === 200) {
226
- player.mode = 'ultimate';
227
- player.ultimate = parseStats(ultRes.data);
228
- if (player.ironman.skills.overall.xp !== player.ultimate.skills.overall.xp) {
229
- player.deulted = true;
230
- player.mode = 'ironman';
231
- }
232
- if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
233
- player.deironed = true;
234
- player.mode = 'main';
235
- }
236
- }
237
- else {
238
- player.mode = 'ironman';
239
- if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
240
- player.deironed = true;
241
- player.mode = 'main';
242
- }
243
- }
244
- }
245
- return [2 /*return*/, player];
246
- case 3: throw Error('Player not found');
247
- }
248
- });
249
- });
250
- }
251
- exports.getStats = getStats;
252
- /**
253
- * Fetches stats from the OSRS API and returns them as an object.
254
- *
255
- * @param rsn Username of the player.
256
- * @param mode Gamemode to fetch ranks for.
257
- * @returns Stats object.
258
- */
259
- function getStatsByGamemode(rsn, mode) {
260
- if (mode === void 0) { mode = 'main'; }
261
- return __awaiter(this, void 0, void 0, function () {
262
- var response, stats;
263
- return __generator(this, function (_a) {
264
- switch (_a.label) {
265
- case 0:
266
- if (typeof rsn !== 'string') {
267
- throw Error('RSN must be a string');
268
- }
269
- else if (!/^[a-zA-Z0-9 _]+$/.test(rsn)) {
270
- throw Error('RSN contains invalid character');
271
- }
272
- else if (rsn.length > 12 || rsn.length < 1) {
273
- throw Error('RSN must be between 1 and 12 characters');
274
- }
275
- else if (!utils_1.GAMEMODES.includes(mode)) {
276
- throw Error('Invalid game mode');
277
- }
278
- return [4 /*yield*/, utils_1.httpGet(utils_1.getStatsURL(mode, rsn))];
279
- case 1:
280
- response = _a.sent();
281
- if (response.status !== 200) {
282
- throw Error('Player not found');
283
- }
284
- stats = parseStats(response.data);
285
- return [2 /*return*/, stats];
286
- }
287
- });
288
- });
289
- }
290
- exports.getStatsByGamemode = getStatsByGamemode;
291
- function getSkillPage(skill, mode, page) {
292
- if (mode === void 0) { mode = 'main'; }
293
- if (page === void 0) { page = 1; }
294
- return __awaiter(this, void 0, void 0, function () {
295
- var url, response, dom, playersHTML, players;
296
- return __generator(this, function (_a) {
297
- switch (_a.label) {
298
- case 0:
299
- if (!utils_1.GAMEMODES.includes(mode)) {
300
- throw Error('Invalid game mode');
301
- }
302
- else if (!Number.isInteger(page) || page < 1) {
303
- throw Error('Page must be an integer greater than 0');
304
- }
305
- else if (!utils_1.SKILLS.includes(skill)) {
306
- throw Error('Invalid skill');
307
- }
308
- url = utils_1.getSkillPageURL(mode, skill, page);
309
- return [4 /*yield*/, utils_1.httpGet(url)];
310
- case 1:
311
- response = _a.sent();
312
- dom = new jsdom_1.JSDOM(response.data);
313
- playersHTML = dom.window.document.querySelectorAll('.personal-hiscores__row');
314
- players = [];
315
- playersHTML.forEach(function (row) {
316
- var rankEl = row.querySelector('td');
317
- var nameEl = row.querySelector('td a');
318
- var levelEl = row.querySelector('td.left + td');
319
- var xpEl = row.querySelector('td.left + td + td');
320
- var isDead = !!row.querySelector('td img');
321
- players.push({
322
- name: utils_1.rsnFromElement(nameEl),
323
- rank: utils_1.numberFromElement(rankEl),
324
- level: utils_1.numberFromElement(levelEl),
325
- xp: utils_1.numberFromElement(xpEl),
326
- dead: isDead
327
- });
328
- });
329
- return [2 /*return*/, players];
330
- }
331
- });
332
- });
333
- }
334
- exports.getSkillPage = getSkillPage;
335
- /**
336
- * Screen scrapes a hiscores page of an activity or boss and returns an array of up to 25 players.
337
- *
338
- * @param activity Name of the activity or boss to fetch hiscores for.
339
- * @param mode Gamemode to fetch ranks for.
340
- * @param page Page number.
341
- * @returns Array of `PlayerActivityRow` objects.
342
- */
343
- function getActivityPage(activity, mode, page) {
344
- if (mode === void 0) { mode = 'main'; }
345
- if (page === void 0) { page = 1; }
346
- return __awaiter(this, void 0, void 0, function () {
347
- var url, response, dom, playersHTML, players;
348
- return __generator(this, function (_a) {
349
- switch (_a.label) {
350
- case 0:
351
- if (!utils_1.GAMEMODES.includes(mode)) {
352
- throw Error('Invalid game mode');
353
- }
354
- else if (!Number.isInteger(page) || page < 1) {
355
- throw Error('Page must be an integer greater than 0');
356
- }
357
- else if (!utils_1.ACTIVITIES.includes(activity)) {
358
- throw Error('Invalid activity');
359
- }
360
- url = utils_1.getActivityPageURL(mode, activity, page);
361
- return [4 /*yield*/, utils_1.httpGet(url)];
362
- case 1:
363
- response = _a.sent();
364
- dom = new jsdom_1.JSDOM(response.data);
365
- playersHTML = dom.window.document.querySelectorAll('.personal-hiscores__row');
366
- players = [];
367
- playersHTML.forEach(function (row) {
368
- var rankEl = row.querySelector('td');
369
- var nameEl = row.querySelector('td a');
370
- var scoreEl = row.querySelector('td.left + td');
371
- var isDead = !!row.querySelector('td img');
372
- players.push({
373
- name: utils_1.rsnFromElement(nameEl),
374
- rank: utils_1.numberFromElement(rankEl),
375
- score: utils_1.numberFromElement(scoreEl),
376
- dead: isDead
377
- });
378
- });
379
- return [2 /*return*/, players];
380
- }
381
- });
382
- });
383
- }
384
- exports.getActivityPage = getActivityPage;
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (_) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.getActivityPage = exports.getSkillPage = exports.getStatsByGamemode = exports.getStats = exports.parseStats = exports.getRSNFormat = void 0;
51
+ var jsdom_1 = require("jsdom");
52
+ var utils_1 = require("./utils");
53
+ /**
54
+ * Screen scrapes the hiscores to get the formatted rsn of a player.
55
+ *
56
+ * @param rsn Username of the player.
57
+ * @returns Formatted version of the rsn.
58
+ */
59
+ function getRSNFormat(rsn) {
60
+ return __awaiter(this, void 0, void 0, function () {
61
+ var url, response, dom, spans, nameSpan, _a;
62
+ return __generator(this, function (_b) {
63
+ switch (_b.label) {
64
+ case 0:
65
+ if (typeof rsn !== 'string') {
66
+ throw Error('RSN must be a string');
67
+ }
68
+ else if (!/^[a-zA-Z0-9 _-]+$/.test(rsn)) {
69
+ throw Error('RSN contains invalid character');
70
+ }
71
+ else if (rsn.length > 12 || rsn.length < 1) {
72
+ throw Error('RSN must be between 1 and 12 characters');
73
+ }
74
+ url = utils_1.getPlayerTableURL('main', rsn);
75
+ _b.label = 1;
76
+ case 1:
77
+ _b.trys.push([1, 3, , 4]);
78
+ return [4 /*yield*/, utils_1.httpGet(url)];
79
+ case 2:
80
+ response = _b.sent();
81
+ dom = new jsdom_1.JSDOM(response.data);
82
+ spans = dom.window.document.querySelectorAll('span[style="color:#AA0022;"]');
83
+ if (spans.length >= 2) {
84
+ nameSpan = spans[1];
85
+ return [2 /*return*/, utils_1.rsnFromElement(nameSpan)];
86
+ }
87
+ throw Error('Player not found');
88
+ case 3:
89
+ _a = _b.sent();
90
+ throw Error('Player not found');
91
+ case 4: return [2 /*return*/];
92
+ }
93
+ });
94
+ });
95
+ }
96
+ exports.getRSNFormat = getRSNFormat;
97
+ /**
98
+ * Parses CSV string of raw stats and returns a stats object.
99
+ *
100
+ * @param csv Raw CSV from the official OSRS API.
101
+ * @returns Parsed stats object.
102
+ */
103
+ function parseStats(csv) {
104
+ var splitCSV = csv
105
+ .split('\n')
106
+ .filter(function (entry) { return !!entry; })
107
+ .map(function (stat) { return stat.split(','); });
108
+ if (splitCSV.length !== utils_1.SKILLS.length + utils_1.BH_MODES.length + utils_1.CLUES.length + utils_1.BOSSES.length + 3) {
109
+ throw Error(utils_1.INVALID_FORMAT_ERROR);
110
+ }
111
+ var skillObjects = splitCSV
112
+ .filter(function (stat) { return stat.length === 3; })
113
+ .map(function (stat) {
114
+ var rank = stat[0], level = stat[1], xp = stat[2];
115
+ var skill = {
116
+ rank: parseInt(rank, 10),
117
+ level: parseInt(level, 10),
118
+ xp: parseInt(xp, 10)
119
+ };
120
+ return skill;
121
+ });
122
+ var activityObjects = splitCSV
123
+ .filter(function (stat) { return stat.length === 2; })
124
+ .map(function (stat) {
125
+ var rank = stat[0], score = stat[1];
126
+ var activity = {
127
+ rank: parseInt(rank, 10),
128
+ score: parseInt(score, 10)
129
+ };
130
+ return activity;
131
+ });
132
+ var leaguePoints = activityObjects.splice(0, 1)[0];
133
+ var bhObjects = activityObjects.splice(0, utils_1.BH_MODES.length);
134
+ var clueObjects = activityObjects.splice(0, utils_1.CLUES.length);
135
+ var _a = activityObjects.splice(0, 2), lastManStanding = _a[0], soulWarsZeal = _a[1];
136
+ var bossObjects = activityObjects.splice(0, utils_1.BOSSES.length);
137
+ var skills = skillObjects.reduce(function (prev, curr, index) {
138
+ var newSkills = __assign({}, prev);
139
+ newSkills[utils_1.SKILLS[index]] = curr;
140
+ return newSkills;
141
+ }, {});
142
+ var bountyHunter = bhObjects.reduce(function (prev, curr, index) {
143
+ var newBH = __assign({}, prev);
144
+ newBH[utils_1.BH_MODES[index]] = curr;
145
+ return newBH;
146
+ }, {});
147
+ var clues = clueObjects.reduce(function (prev, curr, index) {
148
+ var newClues = __assign({}, prev);
149
+ newClues[utils_1.CLUES[index]] = curr;
150
+ return newClues;
151
+ }, {});
152
+ var bosses = bossObjects.reduce(function (prev, curr, index) {
153
+ var newBosses = __assign({}, prev);
154
+ newBosses[utils_1.BOSSES[index]] = curr;
155
+ return newBosses;
156
+ }, {});
157
+ var stats = {
158
+ skills: skills,
159
+ leaguePoints: leaguePoints,
160
+ bountyHunter: bountyHunter,
161
+ lastManStanding: lastManStanding,
162
+ soulWarsZeal: soulWarsZeal,
163
+ clues: clues,
164
+ bosses: bosses
165
+ };
166
+ return stats;
167
+ }
168
+ exports.parseStats = parseStats;
169
+ /**
170
+ * Fetches stats from the OSRS API and consolidates the info into a player object.
171
+ *
172
+ * **Note:** This function will make up to 5 separate network requests.
173
+ * As such, it is highly subject to the performance of the official OSRS API.
174
+ *
175
+ * @param rsn Username of the player.
176
+ * @returns Player object.
177
+ */
178
+ function getStats(rsn) {
179
+ return __awaiter(this, void 0, void 0, function () {
180
+ var mainRes, otherResponses, ironRes, hcRes, ultRes, formattedName, player;
181
+ return __generator(this, function (_a) {
182
+ switch (_a.label) {
183
+ case 0:
184
+ if (typeof rsn !== 'string') {
185
+ throw Error('RSN must be a string');
186
+ }
187
+ else if (!/^[a-zA-Z0-9 _]+$/.test(rsn)) {
188
+ throw Error('RSN contains invalid character');
189
+ }
190
+ else if (rsn.length > 12 || rsn.length < 1) {
191
+ throw Error('RSN must be between 1 and 12 characters');
192
+ }
193
+ return [4 /*yield*/, utils_1.httpGet(utils_1.getStatsURL('main', rsn))];
194
+ case 1:
195
+ mainRes = _a.sent();
196
+ if (!(mainRes.status === 200)) return [3 /*break*/, 3];
197
+ return [4 /*yield*/, Promise.all([
198
+ utils_1.httpGet(utils_1.getStatsURL('ironman', rsn)).catch(function (err) { return err; }),
199
+ utils_1.httpGet(utils_1.getStatsURL('hardcore', rsn)).catch(function (err) { return err; }),
200
+ utils_1.httpGet(utils_1.getStatsURL('ultimate', rsn)).catch(function (err) { return err; }),
201
+ getRSNFormat(rsn).catch(function () { return undefined; })
202
+ ])];
203
+ case 2:
204
+ otherResponses = _a.sent();
205
+ ironRes = otherResponses[0], hcRes = otherResponses[1], ultRes = otherResponses[2], formattedName = otherResponses[3];
206
+ player = {
207
+ name: formattedName !== null && formattedName !== void 0 ? formattedName : rsn,
208
+ mode: 'main',
209
+ dead: false,
210
+ deulted: false,
211
+ deironed: false
212
+ };
213
+ player.main = parseStats(mainRes.data);
214
+ if (ironRes.status === 200) {
215
+ player.ironman = parseStats(ironRes.data);
216
+ if (hcRes.status === 200) {
217
+ player.mode = 'hardcore';
218
+ player.hardcore = parseStats(hcRes.data);
219
+ if (player.ironman.skills.overall.xp !== player.hardcore.skills.overall.xp) {
220
+ player.dead = true;
221
+ player.mode = 'ironman';
222
+ }
223
+ if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
224
+ player.deironed = true;
225
+ player.mode = 'main';
226
+ }
227
+ }
228
+ else if (ultRes.status === 200) {
229
+ player.mode = 'ultimate';
230
+ player.ultimate = parseStats(ultRes.data);
231
+ if (player.ironman.skills.overall.xp !== player.ultimate.skills.overall.xp) {
232
+ player.deulted = true;
233
+ player.mode = 'ironman';
234
+ }
235
+ if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
236
+ player.deironed = true;
237
+ player.mode = 'main';
238
+ }
239
+ }
240
+ else {
241
+ player.mode = 'ironman';
242
+ if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
243
+ player.deironed = true;
244
+ player.mode = 'main';
245
+ }
246
+ }
247
+ }
248
+ return [2 /*return*/, player];
249
+ case 3: throw Error('Player not found');
250
+ }
251
+ });
252
+ });
253
+ }
254
+ exports.getStats = getStats;
255
+ /**
256
+ * Fetches stats from the OSRS API and returns them as an object.
257
+ *
258
+ * @param rsn Username of the player.
259
+ * @param mode Gamemode to fetch ranks for.
260
+ * @returns Stats object.
261
+ */
262
+ function getStatsByGamemode(rsn, mode) {
263
+ if (mode === void 0) { mode = 'main'; }
264
+ return __awaiter(this, void 0, void 0, function () {
265
+ var response, stats;
266
+ return __generator(this, function (_a) {
267
+ switch (_a.label) {
268
+ case 0:
269
+ if (typeof rsn !== 'string') {
270
+ throw Error('RSN must be a string');
271
+ }
272
+ else if (!/^[a-zA-Z0-9 _]+$/.test(rsn)) {
273
+ throw Error('RSN contains invalid character');
274
+ }
275
+ else if (rsn.length > 12 || rsn.length < 1) {
276
+ throw Error('RSN must be between 1 and 12 characters');
277
+ }
278
+ else if (!utils_1.GAMEMODES.includes(mode)) {
279
+ throw Error('Invalid game mode');
280
+ }
281
+ return [4 /*yield*/, utils_1.httpGet(utils_1.getStatsURL(mode, rsn))];
282
+ case 1:
283
+ response = _a.sent();
284
+ if (response.status !== 200) {
285
+ throw Error('Player not found');
286
+ }
287
+ stats = parseStats(response.data);
288
+ return [2 /*return*/, stats];
289
+ }
290
+ });
291
+ });
292
+ }
293
+ exports.getStatsByGamemode = getStatsByGamemode;
294
+ function getSkillPage(skill, mode, page) {
295
+ if (mode === void 0) { mode = 'main'; }
296
+ if (page === void 0) { page = 1; }
297
+ return __awaiter(this, void 0, void 0, function () {
298
+ var url, response, dom, playersHTML, players;
299
+ return __generator(this, function (_a) {
300
+ switch (_a.label) {
301
+ case 0:
302
+ if (!utils_1.GAMEMODES.includes(mode)) {
303
+ throw Error('Invalid game mode');
304
+ }
305
+ else if (!Number.isInteger(page) || page < 1) {
306
+ throw Error('Page must be an integer greater than 0');
307
+ }
308
+ else if (!utils_1.SKILLS.includes(skill)) {
309
+ throw Error('Invalid skill');
310
+ }
311
+ url = utils_1.getSkillPageURL(mode, skill, page);
312
+ return [4 /*yield*/, utils_1.httpGet(url)];
313
+ case 1:
314
+ response = _a.sent();
315
+ dom = new jsdom_1.JSDOM(response.data);
316
+ playersHTML = dom.window.document.querySelectorAll('.personal-hiscores__row');
317
+ players = [];
318
+ playersHTML.forEach(function (row) {
319
+ var rankEl = row.querySelector('td');
320
+ var nameEl = row.querySelector('td a');
321
+ var levelEl = row.querySelector('td.left + td');
322
+ var xpEl = row.querySelector('td.left + td + td');
323
+ var isDead = !!row.querySelector('td img');
324
+ players.push({
325
+ name: utils_1.rsnFromElement(nameEl),
326
+ rank: utils_1.numberFromElement(rankEl),
327
+ level: utils_1.numberFromElement(levelEl),
328
+ xp: utils_1.numberFromElement(xpEl),
329
+ dead: isDead
330
+ });
331
+ });
332
+ return [2 /*return*/, players];
333
+ }
334
+ });
335
+ });
336
+ }
337
+ exports.getSkillPage = getSkillPage;
338
+ /**
339
+ * Screen scrapes a hiscores page of an activity or boss and returns an array of up to 25 players.
340
+ *
341
+ * @param activity Name of the activity or boss to fetch hiscores for.
342
+ * @param mode Gamemode to fetch ranks for.
343
+ * @param page Page number.
344
+ * @returns Array of `PlayerActivityRow` objects.
345
+ */
346
+ function getActivityPage(activity, mode, page) {
347
+ if (mode === void 0) { mode = 'main'; }
348
+ if (page === void 0) { page = 1; }
349
+ return __awaiter(this, void 0, void 0, function () {
350
+ var url, response, dom, playersHTML, players;
351
+ return __generator(this, function (_a) {
352
+ switch (_a.label) {
353
+ case 0:
354
+ if (!utils_1.GAMEMODES.includes(mode)) {
355
+ throw Error('Invalid game mode');
356
+ }
357
+ else if (!Number.isInteger(page) || page < 1) {
358
+ throw Error('Page must be an integer greater than 0');
359
+ }
360
+ else if (!utils_1.ACTIVITIES.includes(activity)) {
361
+ throw Error('Invalid activity');
362
+ }
363
+ url = utils_1.getActivityPageURL(mode, activity, page);
364
+ return [4 /*yield*/, utils_1.httpGet(url)];
365
+ case 1:
366
+ response = _a.sent();
367
+ dom = new jsdom_1.JSDOM(response.data);
368
+ playersHTML = dom.window.document.querySelectorAll('.personal-hiscores__row');
369
+ players = [];
370
+ playersHTML.forEach(function (row) {
371
+ var rankEl = row.querySelector('td');
372
+ var nameEl = row.querySelector('td a');
373
+ var scoreEl = row.querySelector('td.left + td');
374
+ var isDead = !!row.querySelector('td img');
375
+ players.push({
376
+ name: utils_1.rsnFromElement(nameEl),
377
+ rank: utils_1.numberFromElement(rankEl),
378
+ score: utils_1.numberFromElement(scoreEl),
379
+ dead: isDead
380
+ });
381
+ });
382
+ return [2 /*return*/, players];
383
+ }
384
+ });
385
+ });
386
+ }
387
+ exports.getActivityPage = getActivityPage;