Compare commits

..

24 Commits

Author SHA1 Message Date
maxswa
f45ae67813 Add wilderness boss variants. 2023-04-12 12:42:37 -04:00
maxswa
7724636b40 v2.12.1 2023-03-19 23:33:33 -04:00
maxswa
3954b04acc Add publishConfig to package.json 2023-03-19 23:33:03 -04:00
Max Swartwout
ee7389455c Merge pull request #68 from maxswa/add-options
Add `validateRSN`, `GetStatsOptions`
2023-03-19 23:28:34 -04:00
maxswa
54c11635e0 Add GetStatsOptions for getStats 2023-03-19 23:14:10 -04:00
maxswa
dc799cf363 Add validateRSN helper function. 2023-03-19 22:38:45 -04:00
maxswa
d4c7aaff2a v2.12.0 2023-02-19 18:31:43 -05:00
Max Swartwout
03c089ebff Merge pull request #66 from maxswa/account-builds
Add new `Gamemode`s
2023-02-19 18:31:00 -05:00
Max Swartwout
96641d875a Merge pull request #65 from maxswa/dependabot/npm_and_yarn/http-cache-semantics-4.1.1
Bump http-cache-semantics from 4.1.0 to 4.1.1
2023-02-19 18:28:33 -05:00
maxswa
b2bdd3d2ce Add new Gamemodes 2023-02-19 18:27:56 -05:00
dependabot[bot]
a4ddfaf199 Bump http-cache-semantics from 4.1.0 to 4.1.1
Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/kornelski/http-cache-semantics/releases)
- [Commits](https://github.com/kornelski/http-cache-semantics/compare/v4.1.0...v4.1.1)

---
updated-dependencies:
- dependency-name: http-cache-semantics
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-03 04:54:08 +00:00
maxswa
efbcdfc709 v2.11.0 2023-01-13 11:21:51 -05:00
Max Swartwout
fe913aba1f Merge pull request #64 from davidvorona/add-muspah
Add phantom muspah
2023-01-12 15:30:21 -05:00
Max Swartwout
1497653bab Merge pull request #63 from maxswa/dependabot/npm_and_yarn/json5-1.0.2
Bump json5 from 1.0.1 to 1.0.2
2023-01-12 15:29:38 -05:00
David Vorona
f76de38eb1 Add phantom muspah 2023-01-11 11:45:59 -08:00
dependabot[bot]
2f1d10b309 Bump json5 from 1.0.1 to 1.0.2
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-06 22:36:14 +00:00
Max Swartwout
f08424cb81 Update build badge in README 2022-12-19 12:24:03 -05:00
maxswa
69088db3b6 v2.10.2 2022-12-15 23:24:59 +00:00
Max Swartwout
9cc89735cd Merge pull request #61 from maxswa/get-rsn-format-highlight-row
Fix `getRSNFormat`
2022-12-15 18:15:34 -05:00
Max Swartwout
a126ae4fc7 Merge pull request #58 from maxswa/dependabot/npm_and_yarn/minimatch-3.1.2
Bump minimatch from 3.0.4 to 3.1.2
2022-12-15 18:11:34 -05:00
Max Swartwout
52f3df1838 Merge pull request #59 from maxswa/dependabot/npm_and_yarn/qs-6.5.3
Bump qs from 6.5.2 to 6.5.3
2022-12-15 18:11:23 -05:00
maxswa
2891bbddc4 Fix getRSNFormat 2022-12-15 18:09:21 -05:00
dependabot[bot]
e2ea2fe33d Bump qs from 6.5.2 to 6.5.3
Bumps [qs](https://github.com/ljharb/qs) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.5.2...v6.5.3)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-09 06:28:03 +00:00
dependabot[bot]
240628d9cc Bump minimatch from 3.0.4 to 3.1.2
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-04 19:14:24 +00:00
12 changed files with 4382 additions and 2900 deletions

View File

@@ -3,7 +3,7 @@
[![npm](https://img.shields.io/npm/v/osrs-json-hiscores.svg?style=flat-square)](https://www.npmjs.com/package/osrs-json-hiscores) [![npm](https://img.shields.io/npm/v/osrs-json-hiscores.svg?style=flat-square)](https://www.npmjs.com/package/osrs-json-hiscores)
[![downloads](https://img.shields.io/npm/dm/osrs-json-hiscores.svg?style=flat-square)](https://npm-stat.com/charts.html?package=osrs-json-hiscores) [![downloads](https://img.shields.io/npm/dm/osrs-json-hiscores.svg?style=flat-square)](https://npm-stat.com/charts.html?package=osrs-json-hiscores)
[![types](https://img.shields.io/npm/types/osrs-json-hiscores.svg?style=flat-square)](https://github.com/maxswa/osrs-json-hiscores/blob/master/src/types.ts) [![types](https://img.shields.io/npm/types/osrs-json-hiscores.svg?style=flat-square)](https://github.com/maxswa/osrs-json-hiscores/blob/master/src/types.ts)
[![build](https://img.shields.io/github/workflow/status/maxswa/osrs-json-hiscores/CI?style=flat-square)](https://github.com/maxswa/osrs-json-hiscores/actions/workflows/main.yml?query=branch%3Amain) [![build](https://img.shields.io/github/actions/workflow/status/maxswa/osrs-json-hiscores/main.yml?style=flat-square&branch=main)](https://github.com/maxswa/osrs-json-hiscores/actions/workflows/main.yml?query=branch%3Amain)
**The Old School Runescape API wrapper that does more!** **The Old School Runescape API wrapper that does more!**
@@ -125,9 +125,11 @@ Activities consist of all levels of clue scrolls as well as minigames and bosses
| --------------------------------- | :----------------------------: | | --------------------------------- | :----------------------------: |
| Abyssal Sire | `abyssalSire` | | Abyssal Sire | `abyssalSire` |
| Alchemical Hydra | `alchemicalHydra` | | Alchemical Hydra | `alchemicalHydra` |
| Artio | `artio` |
| Barrows Chests | `barrows` | | Barrows Chests | `barrows` |
| Bryophyta | `bryophyta` | | Bryophyta | `bryophyta` |
| Callisto | `callisto` | | Callisto | `callisto` |
| Cal'varion | `calvarion` |
| Cerberus | `cerberus` | | Cerberus | `cerberus` |
| Chambers Of Xeric | `chambersOfXeric` | | Chambers Of Xeric | `chambersOfXeric` |
| Chambers Of Xeric: Challenge Mode | `chambersOfXericChallengeMode` | | Chambers Of Xeric: Challenge Mode | `chambersOfXericChallengeMode` |
@@ -154,9 +156,11 @@ Activities consist of all levels of clue scrolls as well as minigames and bosses
| The Nightmare of Ashihama | `nightmare` | | The Nightmare of Ashihama | `nightmare` |
| Phosani's Nightmare | `phosanisNightmare` | | Phosani's Nightmare | `phosanisNightmare` |
| Obor | `obor` | | Obor | `obor` |
| Phantom Muspah | `phantomMuspah` |
| Sarachnis | `sarachnis` | | Sarachnis | `sarachnis` |
| Scorpia | `scorpia` | | Scorpia | `scorpia` |
| Skotizo | `skotizo` | | Skotizo | `skotizo` |
| Spindel | `spindel` |
| Tempoross | `tempoross` | | Tempoross | `tempoross` |
| The Gauntlet | `gauntlet` | | The Gauntlet | `gauntlet` |
| The Corrupted Gauntlet | `corruptedGauntlet` | | The Corrupted Gauntlet | `corruptedGauntlet` |

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -92,9 +92,11 @@ test('Parse CSV to json', () => {
25,1110 25,1110
382,2780 382,2780
944,3000 944,3000
704,892
1981,1452 1981,1452
4981,23 4981,23
888,1046 888,1046
444,792
613,4856 613,4856
102,4038 102,4038
156,334 156,334
@@ -121,9 +123,11 @@ test('Parse CSV to json', () => {
3,22666 3,22666
2,84 2,84
26,323 26,323
44,6233
201,1101 201,1101
82,3404 82,3404
5085,61 5085,61
678,903
18823,23 18823,23
63,375 63,375
2870,6 2870,6
@@ -189,9 +193,11 @@ test('Parse CSV to json', () => {
bosses: { bosses: {
abyssalSire: { rank: 382, score: 2780 }, abyssalSire: { rank: 382, score: 2780 },
alchemicalHydra: { rank: 944, score: 3000 }, alchemicalHydra: { rank: 944, score: 3000 },
artio: { rank: 704, score: 892 },
barrows: { rank: 1981, score: 1452 }, barrows: { rank: 1981, score: 1452 },
bryophyta: { rank: 4981, score: 23 }, bryophyta: { rank: 4981, score: 23 },
callisto: { rank: 888, score: 1046 }, callisto: { rank: 888, score: 1046 },
calvarion: { rank: 444, score: 792 },
cerberus: { rank: 613, score: 4856 }, cerberus: { rank: 613, score: 4856 },
chambersOfXeric: { rank: 102, score: 4038 }, chambersOfXeric: { rank: 102, score: 4038 },
chambersOfXericChallengeMode: { rank: 156, score: 334 }, chambersOfXericChallengeMode: { rank: 156, score: 334 },
@@ -218,9 +224,11 @@ test('Parse CSV to json', () => {
nightmare: { rank: 3, score: 22666 }, nightmare: { rank: 3, score: 22666 },
phosanisNightmare: { rank: 2, score: 84 }, phosanisNightmare: { rank: 2, score: 84 },
obor: { rank: 26, score: 323 }, obor: { rank: 26, score: 323 },
phantomMuspah: { rank: 44, score: 6233 },
sarachnis: { rank: 201, score: 1101 }, sarachnis: { rank: 201, score: 1101 },
scorpia: { rank: 82, score: 3404 }, scorpia: { rank: 82, score: 3404 },
skotizo: { rank: 5085, score: 61 }, skotizo: { rank: 5085, score: 61 },
spindel: { rank: 678, score: 903 },
tempoross: { rank: 18823, score: 23 }, tempoross: { rank: 18823, score: 23 },
gauntlet: { rank: 63, score: 375 }, gauntlet: { rank: 63, score: 375 },
corruptedGauntlet: { rank: 2870, score: 6 }, corruptedGauntlet: { rank: 2870, score: 6 },
@@ -503,3 +511,50 @@ test('Get stats by gamemode', async () => {
expect.assertions(2); expect.assertions(2);
}); });
describe('Get stats options', () => {
const rsn = 'player';
let axiosMock: jest.Mock;
beforeEach(() => {
axios.get = jest.fn(
(url) =>
new Promise<any>((resolve) =>
resolve(
url === getPlayerTableURL('main', rsn)
? { data: lynxTitanNamePage }
: { status: 200, data: lynxTitanStats }
)
)
);
axiosMock = axios.get as any;
axiosMock.mockClear();
});
it('fetches all gamemodes and formatted RSN when no options provided', async () => {
await getStats(rsn);
expect(axiosMock.mock.calls.map((val) => val[0])).toEqual([
getStatsURL('main', rsn),
getPlayerTableURL('main', rsn),
getStatsURL('ironman', rsn),
getStatsURL('hardcore', rsn),
getStatsURL('ultimate', rsn)
]);
});
it('skips fetching formatted RSN when option is provided', async () => {
await getStats(rsn, { shouldGetFormattedRsn: false });
expect(
axiosMock.mock.calls.some(
(val) => val[0] === getPlayerTableURL('main', rsn)
)
).toBeFalsy();
});
it('skips fetching game mode when option is provided', async () => {
await getStats(rsn, {
otherGamemodes: ['ironman', 'ultimate']
});
expect(
axiosMock.mock.calls.some(
(val) => val[0] === getStatsURL('hardcore', rsn)
)
).toBeFalsy();
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -85,4 +85,8 @@
-1,-1 -1,-1
-1,-1 -1,-1
-1,-1 -1,-1
-1,-1
-1,-1
-1,-1
-1,-1
-1,-1 -1,-1
Can't render this file because it has a wrong number of fields in line 25.

View File

@@ -1,6 +1,6 @@
{ {
"name": "osrs-json-hiscores", "name": "osrs-json-hiscores",
"version": "2.10.1", "version": "2.12.1",
"description": "The Old School Runescape API wrapper that does more!", "description": "The Old School Runescape API wrapper that does more!",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
@@ -30,6 +30,9 @@
"stats", "stats",
"skills" "skills"
], ],
"publishConfig": {
"registry": "https://registry.npmjs.org"
},
"author": "maxswa", "author": "maxswa",
"license": "ISC", "license": "ISC",
"bugs": { "bugs": {

View File

@@ -1,4 +1,5 @@
import { JSDOM } from 'jsdom'; import { AxiosResponse } from 'axios';
import { BinaryData, JSDOM } from 'jsdom';
import { import {
Player, Player,
Activity, Activity,
@@ -12,7 +13,8 @@ import {
PlayerSkillRow, PlayerSkillRow,
ActivityName, ActivityName,
PlayerActivityRow, PlayerActivityRow,
Bosses Bosses,
GetStatsOptions
} from './types'; } from './types';
import { import {
getStatsURL, getStatsURL,
@@ -28,7 +30,8 @@ import {
getActivityPageURL, getActivityPageURL,
httpGet, httpGet,
BOSSES, BOSSES,
INVALID_FORMAT_ERROR INVALID_FORMAT_ERROR,
validateRSN
} from './utils'; } from './utils';
/** /**
@@ -38,24 +41,19 @@ import {
* @returns Formatted version of the rsn. * @returns Formatted version of the rsn.
*/ */
export async function getRSNFormat(rsn: string): Promise<string> { export async function getRSNFormat(rsn: string): Promise<string> {
if (typeof rsn !== 'string') { validateRSN(rsn);
throw Error('RSN must be a string');
} else if (!/^[a-zA-Z0-9 _-]+$/.test(rsn)) {
throw Error('RSN contains invalid character');
} else if (rsn.length > 12 || rsn.length < 1) {
throw Error('RSN must be between 1 and 12 characters');
}
const url = getPlayerTableURL('main', rsn); const url = getPlayerTableURL('main', rsn);
try { try {
const response = await httpGet(url); const response = await httpGet<string | Buffer | BinaryData | undefined>(
const dom = new JSDOM(response.data); url
const spans = dom.window.document.querySelectorAll(
'span[style="color:#AA0022;"]'
); );
if (spans.length >= 2) { const dom = new JSDOM(response.data);
const nameSpan = spans[1]; const anchor = dom.window.document.querySelector(
return rsnFromElement(nameSpan); '.personal-hiscores__row.personal-hiscores__row--type-highlight a'
);
if (anchor) {
return rsnFromElement(anchor);
} }
throw Error('Player not found'); throw Error('Player not found');
} catch { } catch {
@@ -75,7 +73,10 @@ export function parseStats(csv: string): Stats {
.filter((entry) => !!entry) .filter((entry) => !!entry)
.map((stat) => stat.split(',')); .map((stat) => stat.split(','));
if (splitCSV.length !== SKILLS.length + BH_MODES.length + CLUES.length + BOSSES.length + 5) { if (
splitCSV.length !==
SKILLS.length + BH_MODES.length + CLUES.length + BOSSES.length + 5
) {
throw Error(INVALID_FORMAT_ERROR); throw Error(INVALID_FORMAT_ERROR);
} }
@@ -105,7 +106,12 @@ export function parseStats(csv: string): Stats {
const [leaguePoints] = activityObjects.splice(0, 1); const [leaguePoints] = activityObjects.splice(0, 1);
const bhObjects = activityObjects.splice(0, BH_MODES.length); const bhObjects = activityObjects.splice(0, BH_MODES.length);
const clueObjects = activityObjects.splice(0, CLUES.length); const clueObjects = activityObjects.splice(0, CLUES.length);
const [lastManStanding, pvpArena, soulWarsZeal, riftsClosed] = activityObjects.splice(0, 4); const [
lastManStanding,
pvpArena,
soulWarsZeal,
riftsClosed
] = activityObjects.splice(0, 4);
const bossObjects = activityObjects.splice(0, BOSSES.length); const bossObjects = activityObjects.splice(0, BOSSES.length);
const skills: Skills = skillObjects.reduce<Skills>((prev, curr, index) => { const skills: Skills = skillObjects.reduce<Skills>((prev, curr, index) => {
@@ -156,25 +162,36 @@ export function parseStats(csv: string): Stats {
* @param rsn Username of the player. * @param rsn Username of the player.
* @returns Player object. * @returns Player object.
*/ */
export async function getStats(rsn: string): Promise<Player> { export async function getStats(
if (typeof rsn !== 'string') { rsn: string,
throw Error('RSN must be a string'); options?: GetStatsOptions
} else if (!/^[a-zA-Z0-9 _-]+$/.test(rsn)) { ): Promise<Player> {
throw Error('RSN contains invalid character'); validateRSN(rsn);
} else if (rsn.length > 12 || rsn.length < 1) { const otherGamemodes = options?.otherGamemodes ?? [
throw Error('RSN must be between 1 and 12 characters'); 'ironman',
} 'hardcore',
'ultimate'
];
const shouldGetFormattedRsn = options?.shouldGetFormattedRsn ?? true;
const mainRes = await httpGet(getStatsURL('main', rsn)); const mainRes = await httpGet<string>(getStatsURL('main', rsn));
if (mainRes.status === 200) { if (mainRes.status === 200) {
const otherResponses = await Promise.all([ const emptyResponse: AxiosResponse<string> = {
httpGet(getStatsURL('ironman', rsn)).catch((err) => err), status: 404,
httpGet(getStatsURL('hardcore', rsn)).catch((err) => err), data: '',
httpGet(getStatsURL('ultimate', rsn)).catch((err) => err), statusText: '',
getRSNFormat(rsn).catch(() => undefined) headers: {},
]); config: {}
};
const [ironRes, hcRes, ultRes, formattedName] = otherResponses; const getModeStats = async (
mode: Extract<Gamemode, 'ironman' | 'hardcore' | 'ultimate'>
): Promise<AxiosResponse<string>> =>
otherGamemodes.includes(mode)
? httpGet<string>(getStatsURL(mode, rsn)).catch((err) => err)
: emptyResponse;
const formattedName = shouldGetFormattedRsn
? await getRSNFormat(rsn).catch(() => undefined)
: undefined;
const player: Player = { const player: Player = {
name: formattedName ?? rsn, name: formattedName ?? rsn,
@@ -185,8 +202,11 @@ export async function getStats(rsn: string): Promise<Player> {
}; };
player.main = parseStats(mainRes.data); player.main = parseStats(mainRes.data);
const ironRes = await getModeStats('ironman');
if (ironRes.status === 200) { if (ironRes.status === 200) {
player.ironman = parseStats(ironRes.data); player.ironman = parseStats(ironRes.data);
const hcRes = await getModeStats('hardcore');
const ultRes = await getModeStats('ultimate');
if (hcRes.status === 200) { if (hcRes.status === 200) {
player.mode = 'hardcore'; player.mode = 'hardcore';
player.hardcore = parseStats(hcRes.data); player.hardcore = parseStats(hcRes.data);
@@ -244,16 +264,11 @@ export async function getStatsByGamemode(
rsn: string, rsn: string,
mode: Gamemode = 'main' mode: Gamemode = 'main'
): Promise<Stats> { ): Promise<Stats> {
if (typeof rsn !== 'string') { validateRSN(rsn);
throw Error('RSN must be a string'); if (!GAMEMODES.includes(mode)) {
} else if (!/^[a-zA-Z0-9 _-]+$/.test(rsn)) {
throw Error('RSN contains invalid character');
} else if (rsn.length > 12 || rsn.length < 1) {
throw Error('RSN must be between 1 and 12 characters');
} else if (!GAMEMODES.includes(mode)) {
throw Error('Invalid game mode'); throw Error('Invalid game mode');
} }
const response = await httpGet(getStatsURL(mode, rsn)); const response = await httpGet<string>(getStatsURL(mode, rsn));
if (response.status !== 200) { if (response.status !== 200) {
throw Error('Player not found'); throw Error('Player not found');
} }
@@ -276,7 +291,7 @@ export async function getSkillPage(
} }
const url = getSkillPageURL(mode, skill, page); const url = getSkillPageURL(mode, skill, page);
const response = await httpGet(url); const response = await httpGet<string | Buffer | BinaryData | undefined>(url);
const dom = new JSDOM(response.data); const dom = new JSDOM(response.data);
const playersHTML = dom.window.document.querySelectorAll( const playersHTML = dom.window.document.querySelectorAll(
'.personal-hiscores__row' '.personal-hiscores__row'
@@ -324,7 +339,7 @@ export async function getActivityPage(
} }
const url = getActivityPageURL(mode, activity, page); const url = getActivityPageURL(mode, activity, page);
const response = await httpGet(url); const response = await httpGet<string | Buffer | BinaryData | undefined>(url);
const dom = new JSDOM(response.data); const dom = new JSDOM(response.data);
const playersHTML = dom.window.document.querySelectorAll( const playersHTML = dom.window.document.querySelectorAll(
'.personal-hiscores__row' '.personal-hiscores__row'

View File

@@ -5,7 +5,10 @@ export type Gamemode =
| 'hardcore' | 'hardcore'
| 'deadman' | 'deadman'
| 'seasonal' | 'seasonal'
| 'tournament'; | 'tournament'
| 'skiller'
| 'oneDefence'
| 'freshStart';
export interface Skill { export interface Skill {
rank: number; rank: number;
@@ -64,9 +67,11 @@ export type BH = { [Type in BHType]: Activity };
export type Boss = export type Boss =
| 'abyssalSire' | 'abyssalSire'
| 'alchemicalHydra' | 'alchemicalHydra'
| 'artio'
| 'barrows' | 'barrows'
| 'bryophyta' | 'bryophyta'
| 'callisto' | 'callisto'
| 'calvarion'
| 'cerberus' | 'cerberus'
| 'chambersOfXeric' | 'chambersOfXeric'
| 'chambersOfXericChallengeMode' | 'chambersOfXericChallengeMode'
@@ -93,9 +98,11 @@ export type Boss =
| 'nightmare' | 'nightmare'
| 'phosanisNightmare' | 'phosanisNightmare'
| 'obor' | 'obor'
| 'phantomMuspah'
| 'sarachnis' | 'sarachnis'
| 'scorpia' | 'scorpia'
| 'skotizo' | 'skotizo'
| 'spindel'
| 'tempoross' | 'tempoross'
| 'gauntlet' | 'gauntlet'
| 'corruptedGauntlet' | 'corruptedGauntlet'
@@ -162,3 +169,16 @@ export interface PlayerActivityRow extends Activity {
name: string; name: string;
dead: boolean; dead: boolean;
} }
export interface GetStatsOptions {
/**
* Other game modes to fetch ranks for.
* @defaultvalue `['ironman', 'hardcore', 'ultimate']`
*/
otherGamemodes?: Extract<Gamemode, 'ironman' | 'hardcore' | 'ultimate'>[];
/**
* If true, the formatted RSN will be fetched. Otherwise it will return the provided, unformatted RSN.
* @defaultvalue `true`
*/
shouldGetFormattedRsn?: boolean;
}

View File

@@ -22,7 +22,10 @@ export const GAMEMODE_URL: GamemodeUrl = {
ultimate: `${BASE_URL}_ultimate/`, ultimate: `${BASE_URL}_ultimate/`,
deadman: `${BASE_URL}_deadman/`, deadman: `${BASE_URL}_deadman/`,
seasonal: `${BASE_URL}_seasonal/`, seasonal: `${BASE_URL}_seasonal/`,
tournament: `${BASE_URL}_tournament/` tournament: `${BASE_URL}_tournament/`,
skiller: `${BASE_URL}_skiller/`,
oneDefence: `${BASE_URL}_skiller_defence/`,
freshStart: `${BASE_URL}_fresh_start/`
}; };
export const SKILLS: SkillName[] = [ export const SKILLS: SkillName[] = [
'overall', 'overall',
@@ -72,9 +75,11 @@ export const GAMEMODES: Gamemode[] = [
export const BOSSES: Boss[] = [ export const BOSSES: Boss[] = [
'abyssalSire', 'abyssalSire',
'alchemicalHydra', 'alchemicalHydra',
'artio',
'barrows', 'barrows',
'bryophyta', 'bryophyta',
'callisto', 'callisto',
'calvarion',
'cerberus', 'cerberus',
'chambersOfXeric', 'chambersOfXeric',
'chambersOfXericChallengeMode', 'chambersOfXericChallengeMode',
@@ -101,9 +106,11 @@ export const BOSSES: Boss[] = [
'nightmare', 'nightmare',
'phosanisNightmare', 'phosanisNightmare',
'obor', 'obor',
'phantomMuspah',
'sarachnis', 'sarachnis',
'scorpia', 'scorpia',
'skotizo', 'skotizo',
'spindel',
'tempoross', 'tempoross',
'gauntlet', 'gauntlet',
'corruptedGauntlet', 'corruptedGauntlet',
@@ -146,9 +153,11 @@ export type FormattedBossNames = {
export const FORMATTED_BOSS_NAMES: FormattedBossNames = { export const FORMATTED_BOSS_NAMES: FormattedBossNames = {
abyssalSire: 'Abyssal Sire', abyssalSire: 'Abyssal Sire',
alchemicalHydra: 'Alchemical Hydra', alchemicalHydra: 'Alchemical Hydra',
artio: 'Artio',
barrows: 'Barrows Chests', barrows: 'Barrows Chests',
bryophyta: 'Bryophyta', bryophyta: 'Bryophyta',
callisto: 'Callisto', callisto: 'Callisto',
calvarion: "Cal'varion",
cerberus: 'Cerberus', cerberus: 'Cerberus',
chambersOfXeric: 'Chambers of Xeric', chambersOfXeric: 'Chambers of Xeric',
chambersOfXericChallengeMode: 'Chambers of Xeric: Challenge Mode', chambersOfXericChallengeMode: 'Chambers of Xeric: Challenge Mode',
@@ -175,9 +184,11 @@ export const FORMATTED_BOSS_NAMES: FormattedBossNames = {
nightmare: 'The Nightmare of Ashihama', nightmare: 'The Nightmare of Ashihama',
phosanisNightmare: "Phosani's Nightmare", phosanisNightmare: "Phosani's Nightmare",
obor: 'Obor', obor: 'Obor',
phantomMuspah: 'Phantom Muspah',
sarachnis: 'Sarachnis', sarachnis: 'Sarachnis',
scorpia: 'Scorpia', scorpia: 'Scorpia',
skotizo: 'Skotizo', skotizo: 'Skotizo',
spindel: 'Spindel',
tempoross: 'Tempoross', tempoross: 'Tempoross',
gauntlet: 'The Gauntlet', gauntlet: 'The Gauntlet',
corruptedGauntlet: 'The Corrupted Gauntlet', corruptedGauntlet: 'The Corrupted Gauntlet',

View File

@@ -96,10 +96,25 @@ export const rsnFromElement = (el: Element | null) => {
* @param url URL to run a `GET` request against. * @param url URL to run a `GET` request against.
* @returns Axios response. * @returns Axios response.
*/ */
export const httpGet = (url: string) => export const httpGet = <Response>(url: string) =>
axios.get(url, { axios.get<Response>(url, {
headers: { headers: {
// without User-Agent header requests may be rejected by DDoS protection mechanism // without User-Agent header requests may be rejected by DDoS protection mechanism
'User-Agent': ua.firefox(80) 'User-Agent': ua.firefox(80)
} }
}); });
/**
* Validates that a provided RSN has the same username restrictions as Jagex.
* @param rsn Username to validate.
* @throws Error if the RSN fails validation.
*/
export const validateRSN = (rsn: string) => {
if (typeof rsn !== 'string') {
throw Error('RSN must be a string');
} else if (!/^[a-zA-Z0-9 _-]+$/.test(rsn)) {
throw Error('RSN contains invalid character');
} else if (rsn.length > 12 || rsn.length < 1) {
throw Error('RSN must be between 1 and 12 characters');
}
};

View File

@@ -1186,9 +1186,9 @@ babel-preset-jest@^26.6.2:
babel-preset-current-node-syntax "^1.0.0" babel-preset-current-node-syntax "^1.0.0"
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.0" version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base@^0.11.1: base@^0.11.1:
version "0.11.2" version "0.11.2"
@@ -1576,7 +1576,7 @@ component-emitter@^1.2.1:
concat-map@0.0.1: concat-map@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
configstore@^5.0.1: configstore@^5.0.1:
version "5.0.1" version "5.0.1"
@@ -2804,9 +2804,9 @@ html-escaper@^2.0.0:
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
http-cache-semantics@^4.0.0: http-cache-semantics@^4.0.0:
version "4.1.0" version "4.1.1"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
http-signature@~1.2.0: http-signature@~1.2.0:
version "1.2.0" version "1.2.0"
@@ -3823,9 +3823,9 @@ json5@2.x, json5@^2.1.2:
minimist "^1.2.5" minimist "^1.2.5"
json5@^1.0.1: json5@^1.0.1:
version "1.0.1" version "1.0.2"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
dependencies: dependencies:
minimist "^1.2.0" minimist "^1.2.0"
@@ -4279,9 +4279,9 @@ min-indent@^1.0.0:
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
minimatch@^3.0.4: minimatch@^3.0.4:
version "3.0.4" version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies: dependencies:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
@@ -4295,9 +4295,9 @@ minimist-options@^4.0.2:
kind-of "^6.0.3" kind-of "^6.0.3"
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.6" version "1.2.7"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
mixin-deep@^1.2.0: mixin-deep@^1.2.0:
version "1.3.2" version "1.3.2"
@@ -4996,9 +4996,9 @@ pupa@^2.0.1:
escape-goat "^2.0.0" escape-goat "^2.0.0"
qs@~6.5.2: qs@~6.5.2:
version "6.5.2" version "6.5.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
queue-microtask@^1.2.2: queue-microtask@^1.2.2:
version "1.2.3" version "1.2.3"