osrs-json-hiscores 2.7.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
package/lib/hiscores.js CHANGED
@@ -1,387 +1,389 @@
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;
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 + 5) {
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, 4), lastManStanding = _a[0], pvpArena = _a[1], soulWarsZeal = _a[2], riftsClosed = _a[3];
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
+ pvpArena: pvpArena,
163
+ soulWarsZeal: soulWarsZeal,
164
+ riftsClosed: riftsClosed,
165
+ clues: clues,
166
+ bosses: bosses
167
+ };
168
+ return stats;
169
+ }
170
+ exports.parseStats = parseStats;
171
+ /**
172
+ * Fetches stats from the OSRS API and consolidates the info into a player object.
173
+ *
174
+ * **Note:** This function will make up to 5 separate network requests.
175
+ * As such, it is highly subject to the performance of the official OSRS API.
176
+ *
177
+ * @param rsn Username of the player.
178
+ * @returns Player object.
179
+ */
180
+ function getStats(rsn) {
181
+ return __awaiter(this, void 0, void 0, function () {
182
+ var mainRes, otherResponses, ironRes, hcRes, ultRes, formattedName, player;
183
+ return __generator(this, function (_a) {
184
+ switch (_a.label) {
185
+ case 0:
186
+ if (typeof rsn !== 'string') {
187
+ throw Error('RSN must be a string');
188
+ }
189
+ else if (!/^[a-zA-Z0-9 _]+$/.test(rsn)) {
190
+ throw Error('RSN contains invalid character');
191
+ }
192
+ else if (rsn.length > 12 || rsn.length < 1) {
193
+ throw Error('RSN must be between 1 and 12 characters');
194
+ }
195
+ return [4 /*yield*/, utils_1.httpGet(utils_1.getStatsURL('main', rsn))];
196
+ case 1:
197
+ mainRes = _a.sent();
198
+ if (!(mainRes.status === 200)) return [3 /*break*/, 3];
199
+ return [4 /*yield*/, Promise.all([
200
+ utils_1.httpGet(utils_1.getStatsURL('ironman', rsn)).catch(function (err) { return err; }),
201
+ utils_1.httpGet(utils_1.getStatsURL('hardcore', rsn)).catch(function (err) { return err; }),
202
+ utils_1.httpGet(utils_1.getStatsURL('ultimate', rsn)).catch(function (err) { return err; }),
203
+ getRSNFormat(rsn).catch(function () { return undefined; })
204
+ ])];
205
+ case 2:
206
+ otherResponses = _a.sent();
207
+ ironRes = otherResponses[0], hcRes = otherResponses[1], ultRes = otherResponses[2], formattedName = otherResponses[3];
208
+ player = {
209
+ name: formattedName !== null && formattedName !== void 0 ? formattedName : rsn,
210
+ mode: 'main',
211
+ dead: false,
212
+ deulted: false,
213
+ deironed: false
214
+ };
215
+ player.main = parseStats(mainRes.data);
216
+ if (ironRes.status === 200) {
217
+ player.ironman = parseStats(ironRes.data);
218
+ if (hcRes.status === 200) {
219
+ player.mode = 'hardcore';
220
+ player.hardcore = parseStats(hcRes.data);
221
+ if (player.ironman.skills.overall.xp !== player.hardcore.skills.overall.xp) {
222
+ player.dead = true;
223
+ player.mode = 'ironman';
224
+ }
225
+ if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
226
+ player.deironed = true;
227
+ player.mode = 'main';
228
+ }
229
+ }
230
+ else if (ultRes.status === 200) {
231
+ player.mode = 'ultimate';
232
+ player.ultimate = parseStats(ultRes.data);
233
+ if (player.ironman.skills.overall.xp !== player.ultimate.skills.overall.xp) {
234
+ player.deulted = true;
235
+ player.mode = 'ironman';
236
+ }
237
+ if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
238
+ player.deironed = true;
239
+ player.mode = 'main';
240
+ }
241
+ }
242
+ else {
243
+ player.mode = 'ironman';
244
+ if (player.main.skills.overall.xp !== player.ironman.skills.overall.xp) {
245
+ player.deironed = true;
246
+ player.mode = 'main';
247
+ }
248
+ }
249
+ }
250
+ return [2 /*return*/, player];
251
+ case 3: throw Error('Player not found');
252
+ }
253
+ });
254
+ });
255
+ }
256
+ exports.getStats = getStats;
257
+ /**
258
+ * Fetches stats from the OSRS API and returns them as an object.
259
+ *
260
+ * @param rsn Username of the player.
261
+ * @param mode Gamemode to fetch ranks for.
262
+ * @returns Stats object.
263
+ */
264
+ function getStatsByGamemode(rsn, mode) {
265
+ if (mode === void 0) { mode = 'main'; }
266
+ return __awaiter(this, void 0, void 0, function () {
267
+ var response, stats;
268
+ return __generator(this, function (_a) {
269
+ switch (_a.label) {
270
+ case 0:
271
+ if (typeof rsn !== 'string') {
272
+ throw Error('RSN must be a string');
273
+ }
274
+ else if (!/^[a-zA-Z0-9 _]+$/.test(rsn)) {
275
+ throw Error('RSN contains invalid character');
276
+ }
277
+ else if (rsn.length > 12 || rsn.length < 1) {
278
+ throw Error('RSN must be between 1 and 12 characters');
279
+ }
280
+ else if (!utils_1.GAMEMODES.includes(mode)) {
281
+ throw Error('Invalid game mode');
282
+ }
283
+ return [4 /*yield*/, utils_1.httpGet(utils_1.getStatsURL(mode, rsn))];
284
+ case 1:
285
+ response = _a.sent();
286
+ if (response.status !== 200) {
287
+ throw Error('Player not found');
288
+ }
289
+ stats = parseStats(response.data);
290
+ return [2 /*return*/, stats];
291
+ }
292
+ });
293
+ });
294
+ }
295
+ exports.getStatsByGamemode = getStatsByGamemode;
296
+ function getSkillPage(skill, mode, page) {
297
+ if (mode === void 0) { mode = 'main'; }
298
+ if (page === void 0) { page = 1; }
299
+ return __awaiter(this, void 0, void 0, function () {
300
+ var url, response, dom, playersHTML, players;
301
+ return __generator(this, function (_a) {
302
+ switch (_a.label) {
303
+ case 0:
304
+ if (!utils_1.GAMEMODES.includes(mode)) {
305
+ throw Error('Invalid game mode');
306
+ }
307
+ else if (!Number.isInteger(page) || page < 1) {
308
+ throw Error('Page must be an integer greater than 0');
309
+ }
310
+ else if (!utils_1.SKILLS.includes(skill)) {
311
+ throw Error('Invalid skill');
312
+ }
313
+ url = utils_1.getSkillPageURL(mode, skill, page);
314
+ return [4 /*yield*/, utils_1.httpGet(url)];
315
+ case 1:
316
+ response = _a.sent();
317
+ dom = new jsdom_1.JSDOM(response.data);
318
+ playersHTML = dom.window.document.querySelectorAll('.personal-hiscores__row');
319
+ players = [];
320
+ playersHTML.forEach(function (row) {
321
+ var rankEl = row.querySelector('td');
322
+ var nameEl = row.querySelector('td a');
323
+ var levelEl = row.querySelector('td.left + td');
324
+ var xpEl = row.querySelector('td.left + td + td');
325
+ var isDead = !!row.querySelector('td img');
326
+ players.push({
327
+ name: utils_1.rsnFromElement(nameEl),
328
+ rank: utils_1.numberFromElement(rankEl),
329
+ level: utils_1.numberFromElement(levelEl),
330
+ xp: utils_1.numberFromElement(xpEl),
331
+ dead: isDead
332
+ });
333
+ });
334
+ return [2 /*return*/, players];
335
+ }
336
+ });
337
+ });
338
+ }
339
+ exports.getSkillPage = getSkillPage;
340
+ /**
341
+ * Screen scrapes a hiscores page of an activity or boss and returns an array of up to 25 players.
342
+ *
343
+ * @param activity Name of the activity or boss to fetch hiscores for.
344
+ * @param mode Gamemode to fetch ranks for.
345
+ * @param page Page number.
346
+ * @returns Array of `PlayerActivityRow` objects.
347
+ */
348
+ function getActivityPage(activity, mode, page) {
349
+ if (mode === void 0) { mode = 'main'; }
350
+ if (page === void 0) { page = 1; }
351
+ return __awaiter(this, void 0, void 0, function () {
352
+ var url, response, dom, playersHTML, players;
353
+ return __generator(this, function (_a) {
354
+ switch (_a.label) {
355
+ case 0:
356
+ if (!utils_1.GAMEMODES.includes(mode)) {
357
+ throw Error('Invalid game mode');
358
+ }
359
+ else if (!Number.isInteger(page) || page < 1) {
360
+ throw Error('Page must be an integer greater than 0');
361
+ }
362
+ else if (!utils_1.ACTIVITIES.includes(activity)) {
363
+ throw Error('Invalid activity');
364
+ }
365
+ url = utils_1.getActivityPageURL(mode, activity, page);
366
+ return [4 /*yield*/, utils_1.httpGet(url)];
367
+ case 1:
368
+ response = _a.sent();
369
+ dom = new jsdom_1.JSDOM(response.data);
370
+ playersHTML = dom.window.document.querySelectorAll('.personal-hiscores__row');
371
+ players = [];
372
+ playersHTML.forEach(function (row) {
373
+ var rankEl = row.querySelector('td');
374
+ var nameEl = row.querySelector('td a');
375
+ var scoreEl = row.querySelector('td.left + td');
376
+ var isDead = !!row.querySelector('td img');
377
+ players.push({
378
+ name: utils_1.rsnFromElement(nameEl),
379
+ rank: utils_1.numberFromElement(rankEl),
380
+ score: utils_1.numberFromElement(scoreEl),
381
+ dead: isDead
382
+ });
383
+ });
384
+ return [2 /*return*/, players];
385
+ }
386
+ });
387
+ });
388
+ }
389
+ exports.getActivityPage = getActivityPage;