mirror of
https://github.com/maxswa/osrs-json-hiscores.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c52bfd883 | ||
|
|
947d994cdf | ||
|
|
130446ab74 | ||
|
|
f96e7e3e2d | ||
|
|
90d66b6b2c | ||
|
|
14cedb5877 | ||
|
|
4703812b52 | ||
|
|
a11ac96f68 | ||
|
|
f97caa6a15 | ||
|
|
e7e54741d2 | ||
|
|
062e5e02b2 | ||
|
|
ed7036f9c0 | ||
|
|
74aba3e818 | ||
|
|
09fe7ed539 | ||
|
|
7a78e1ea0a | ||
|
|
7a4163aed2 | ||
|
|
85464d02fe |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.html linguist-vendored
|
||||||
10
README.md
10
README.md
@@ -3,6 +3,7 @@
|
|||||||
[](https://www.npmjs.com/package/osrs-json-hiscores)
|
[](https://www.npmjs.com/package/osrs-json-hiscores)
|
||||||
[](https://npm-stat.com/charts.html?package=osrs-json-hiscores)
|
[](https://npm-stat.com/charts.html?package=osrs-json-hiscores)
|
||||||
[](https://github.com/maxswa/osrs-json-hiscores/blob/master/src/types.ts)
|
[](https://github.com/maxswa/osrs-json-hiscores/blob/master/src/types.ts)
|
||||||
|
[](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!**
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ Activities consist of all levels of clue scrolls as well as minigames and bosses
|
|||||||
### Bosses
|
### Bosses
|
||||||
|
|
||||||
| Boss Name | Param |
|
| Boss Name | Param |
|
||||||
| -------------------------------- | :----------------------------: |
|
| --------------------------------- | :----------------------------: |
|
||||||
| Abyssal Sire | `abyssalSire` |
|
| Abyssal Sire | `abyssalSire` |
|
||||||
| Alchemical Hydra | `alchemicalHydra` |
|
| Alchemical Hydra | `alchemicalHydra` |
|
||||||
| Barrows Chests | `barrows` |
|
| Barrows Chests | `barrows` |
|
||||||
@@ -127,7 +128,7 @@ Activities consist of all levels of clue scrolls as well as minigames and bosses
|
|||||||
| Callisto | `callisto` |
|
| Callisto | `callisto` |
|
||||||
| Cerberus | `cerberus` |
|
| Cerberus | `cerberus` |
|
||||||
| Chambers Of Xeric | `chambersOfXeric` |
|
| Chambers Of Xeric | `chambersOfXeric` |
|
||||||
| Chambers Of Xeric Challenge Mode | `chambersOfXericChallengeMode` |
|
| Chambers Of Xeric: Challenge Mode | `chambersOfXericChallengeMode` |
|
||||||
| Chaos Elemental | `chaosElemental` |
|
| Chaos Elemental | `chaosElemental` |
|
||||||
| Chaos Fanatic | `chaosFanatic` |
|
| Chaos Fanatic | `chaosFanatic` |
|
||||||
| Commander Zilyana | `commanderZilyana` |
|
| Commander Zilyana | `commanderZilyana` |
|
||||||
@@ -153,9 +154,10 @@ Activities consist of all levels of clue scrolls as well as minigames and bosses
|
|||||||
| Scorpia | `scorpia` |
|
| Scorpia | `scorpia` |
|
||||||
| Skotizo | `skotizo` |
|
| Skotizo | `skotizo` |
|
||||||
| Tempoross | `tempoross` |
|
| Tempoross | `tempoross` |
|
||||||
| Gauntlet | `gauntlet` |
|
| The Gauntlet | `gauntlet` |
|
||||||
| Corrupted Gauntlet | `corruptedGauntlet` |
|
| The Corrupted Gauntlet | `corruptedGauntlet` |
|
||||||
| Theatre Of Blood | `theatreOfBlood` |
|
| Theatre Of Blood | `theatreOfBlood` |
|
||||||
|
| Theatre Of Blood: Hard Mode | `theatreOfBloodHardMode` |
|
||||||
| Thermonuclear Smoke Devil | `thermonuclearSmokeDevil` |
|
| Thermonuclear Smoke Devil | `thermonuclearSmokeDevil` |
|
||||||
| TzKal-Zuk | `tzKalZuk` |
|
| TzKal-Zuk | `tzKalZuk` |
|
||||||
| TzTok-Jad | `tzTokJad` |
|
| TzTok-Jad | `tzTokJad` |
|
||||||
|
|||||||
82
__tests__/fysadStatsSeasonal.csv
Normal file
82
__tests__/fysadStatsSeasonal.csv
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
1,2277,4600000000
|
||||||
|
15,99,200000000
|
||||||
|
28,99,200000000
|
||||||
|
18,99,200000000
|
||||||
|
7,99,200000000
|
||||||
|
8,99,200000000
|
||||||
|
11,99,200000000
|
||||||
|
32,99,200000000
|
||||||
|
159,99,200000000
|
||||||
|
15,99,200000000
|
||||||
|
12,99,200000000
|
||||||
|
9,99,200000000
|
||||||
|
48,99,200000000
|
||||||
|
4,99,200000000
|
||||||
|
3,99,200000000
|
||||||
|
25,99,200000000
|
||||||
|
5,99,200000000
|
||||||
|
23,99,200000000
|
||||||
|
12,99,200000000
|
||||||
|
2,99,200000000
|
||||||
|
19,99,200000000
|
||||||
|
7,99,200000000
|
||||||
|
4,99,200000000
|
||||||
|
4,99,200000000
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
347584,22
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-1,-1
|
||||||
|
-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.
|
@@ -10,7 +10,9 @@ import {
|
|||||||
Stats,
|
Stats,
|
||||||
getPlayerTableURL,
|
getPlayerTableURL,
|
||||||
getSkillPageURL,
|
getSkillPageURL,
|
||||||
getStatsURL
|
getStatsURL,
|
||||||
|
BOSSES,
|
||||||
|
Boss
|
||||||
} from '../src/index';
|
} from '../src/index';
|
||||||
|
|
||||||
const B0ATY_NAME = 'B0ATY';
|
const B0ATY_NAME = 'B0ATY';
|
||||||
@@ -19,6 +21,7 @@ const LYNX_TITAN_SPACE_NAME = 'lYnX tiTaN';
|
|||||||
const LYNX_TITAN_UNDERSCORE_NAME = 'lYnX_tiTaN';
|
const LYNX_TITAN_UNDERSCORE_NAME = 'lYnX_tiTaN';
|
||||||
const LYNX_TITAN_HYPHEN_NAME = 'lYnX-tiTaN';
|
const LYNX_TITAN_HYPHEN_NAME = 'lYnX-tiTaN';
|
||||||
const LYNX_TITAN_FORMATTED_NAME = 'Lynx Titan';
|
const LYNX_TITAN_FORMATTED_NAME = 'Lynx Titan';
|
||||||
|
const FYSAD_FORMATTED_NAME = 'Fysad';
|
||||||
|
|
||||||
const attackTopPage = readFileSync(`${__dirname}/attackTopPage.html`, 'utf8');
|
const attackTopPage = readFileSync(`${__dirname}/attackTopPage.html`, 'utf8');
|
||||||
const b0atyNamePage = readFileSync(`${__dirname}/b0atyNamePage.html`, 'utf8');
|
const b0atyNamePage = readFileSync(`${__dirname}/b0atyNamePage.html`, 'utf8');
|
||||||
@@ -27,6 +30,7 @@ const lynxTitanNamePage = readFileSync(
|
|||||||
`${__dirname}/lynxTitanNamePage.html`,
|
`${__dirname}/lynxTitanNamePage.html`,
|
||||||
'utf8'
|
'utf8'
|
||||||
);
|
);
|
||||||
|
const fysadStatsSeasonal = readFileSync(`${__dirname}/fysadStatsSeasonal.csv`, 'utf8');
|
||||||
|
|
||||||
jest.spyOn(axios, 'get').mockImplementation((url) => {
|
jest.spyOn(axios, 'get').mockImplementation((url) => {
|
||||||
const lynxUrls = [
|
const lynxUrls = [
|
||||||
@@ -46,6 +50,9 @@ jest.spyOn(axios, 'get').mockImplementation((url) => {
|
|||||||
if (getStatsURL('main', LYNX_TITAN_FORMATTED_NAME) === url) {
|
if (getStatsURL('main', LYNX_TITAN_FORMATTED_NAME) === url) {
|
||||||
return Promise.resolve({ status: 200, data: lynxTitanStats });
|
return Promise.resolve({ status: 200, data: lynxTitanStats });
|
||||||
}
|
}
|
||||||
|
if (getStatsURL('seasonal', FYSAD_FORMATTED_NAME) === url) {
|
||||||
|
return Promise.resolve({ status: 200, data: fysadStatsSeasonal });
|
||||||
|
}
|
||||||
throw new Error(`No mock response for URL: ${url}`);
|
throw new Error(`No mock response for URL: ${url}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -122,6 +129,7 @@ test('Parse CSV to json', () => {
|
|||||||
63,375
|
63,375
|
||||||
2870,6
|
2870,6
|
||||||
6984,138
|
6984,138
|
||||||
|
23,923141
|
||||||
4043,2000
|
4043,2000
|
||||||
489,8
|
489,8
|
||||||
967,47
|
967,47
|
||||||
@@ -212,6 +220,7 @@ test('Parse CSV to json', () => {
|
|||||||
gauntlet: { rank: 63, score: 375 },
|
gauntlet: { rank: 63, score: 375 },
|
||||||
corruptedGauntlet: { rank: 2870, score: 6 },
|
corruptedGauntlet: { rank: 2870, score: 6 },
|
||||||
theatreOfBlood: { rank: 6984, score: 138 },
|
theatreOfBlood: { rank: 6984, score: 138 },
|
||||||
|
theatreOfBloodHardMode: { rank: 23, score: 923141 },
|
||||||
thermonuclearSmokeDevil: { rank: 4043, score: 2000 },
|
thermonuclearSmokeDevil: { rank: 4043, score: 2000 },
|
||||||
tzKalZuk: { rank: 489, score: 8 },
|
tzKalZuk: { rank: 489, score: 8 },
|
||||||
tzTokJad: { rank: 967, score: 47 },
|
tzTokJad: { rank: 967, score: 47 },
|
||||||
@@ -439,7 +448,8 @@ test('Get non-existent player', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Get stats by gamemode', async () => {
|
test('Get stats by gamemode', async () => {
|
||||||
const { skills } = await getStatsByGamemode(LYNX_TITAN_FORMATTED_NAME);
|
const { skills, bosses } = await getStatsByGamemode(LYNX_TITAN_FORMATTED_NAME);
|
||||||
|
|
||||||
expect(skills).toMatchObject({
|
expect(skills).toMatchObject({
|
||||||
overall: { rank: expect.any(Number), level: 2277, xp: 4600000000 },
|
overall: { rank: expect.any(Number), level: 2277, xp: 4600000000 },
|
||||||
attack: { rank: expect.any(Number), level: 99, xp: 200000000 },
|
attack: { rank: expect.any(Number), level: 99, xp: 200000000 },
|
||||||
@@ -466,4 +476,21 @@ test('Get stats by gamemode', async () => {
|
|||||||
hunter: { rank: expect.any(Number), level: 99, xp: 200000000 },
|
hunter: { rank: expect.any(Number), level: 99, xp: 200000000 },
|
||||||
construction: { rank: expect.any(Number), level: 99, xp: 200000000 }
|
construction: { rank: expect.any(Number), level: 99, xp: 200000000 }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const bossKeys = Object.keys(bosses);
|
||||||
|
expect(bossKeys).toStrictEqual(BOSSES);
|
||||||
|
|
||||||
|
expect.assertions(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Get stats by game mode seasonal (omit TOB: Hard Mode from bosses)', async () => {
|
||||||
|
const {bosses} = await getStatsByGamemode(FYSAD_FORMATTED_NAME, 'seasonal');
|
||||||
|
const bossKeys = Object.keys(bosses);
|
||||||
|
|
||||||
|
const filteredBosses = BOSSES.filter(boss => boss !== 'theatreOfBloodHardMode');
|
||||||
|
|
||||||
|
expect(bossKeys).toStrictEqual(filteredBosses);
|
||||||
|
expect(bossKeys).not.toContain<Boss>('theatreOfBloodHardMode');
|
||||||
|
|
||||||
|
expect.assertions(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
3,99,200000000
|
3,99,200000000
|
||||||
25,99,200000000
|
25,99,200000000
|
||||||
5,99,200000000
|
5,99,200000000
|
||||||
24,99,200000000
|
23,99,200000000
|
||||||
12,99,200000000
|
12,99,200000000
|
||||||
2,99,200000000
|
2,99,200000000
|
||||||
19,99,200000000
|
19,99,200000000
|
||||||
@@ -29,7 +29,8 @@
|
|||||||
-1,-1
|
-1,-1
|
||||||
-1,-1
|
-1,-1
|
||||||
-1,-1
|
-1,-1
|
||||||
344430,22
|
347584,22
|
||||||
|
-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.
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrs-json-hiscores",
|
"name": "osrs-json-hiscores",
|
||||||
"version": "2.4.2",
|
"version": "2.5.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",
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export async function getRSNFormat(rsn: string): Promise<string> {
|
|||||||
* @param csv Raw CSV from the official OSRS API.
|
* @param csv Raw CSV from the official OSRS API.
|
||||||
* @returns Parsed stats object.
|
* @returns Parsed stats object.
|
||||||
*/
|
*/
|
||||||
export function parseStats(csv: string): Stats {
|
export function parseStats(csv: string, mode: Gamemode = 'main'): Stats {
|
||||||
const splitCSV = csv
|
const splitCSV = csv
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.filter((entry) => !!entry)
|
.filter((entry) => !!entry)
|
||||||
@@ -97,11 +97,17 @@ export function parseStats(csv: string): Stats {
|
|||||||
return activity;
|
return activity;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** `seasonal` API results don't currently include TOB: Hard Mode, so it needs to be filtered out in that case. */
|
||||||
|
const filteredBosses =
|
||||||
|
mode === 'seasonal'
|
||||||
|
? BOSSES.filter((boss) => boss !== 'theatreOfBloodHardMode')
|
||||||
|
: BOSSES;
|
||||||
|
|
||||||
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, soulWarsZeal] = activityObjects.splice(0, 2);
|
const [lastManStanding, soulWarsZeal] = activityObjects.splice(0, 2);
|
||||||
const bossObjects = activityObjects.splice(0, BOSSES.length);
|
const bossObjects = activityObjects.splice(0, filteredBosses.length);
|
||||||
|
|
||||||
const skills: Skills = skillObjects.reduce<Skills>((prev, curr, index) => {
|
const skills: Skills = skillObjects.reduce<Skills>((prev, curr, index) => {
|
||||||
const newSkills = { ...prev };
|
const newSkills = { ...prev };
|
||||||
@@ -123,7 +129,7 @@ export function parseStats(csv: string): Stats {
|
|||||||
|
|
||||||
const bosses: Bosses = bossObjects.reduce<Bosses>((prev, curr, index) => {
|
const bosses: Bosses = bossObjects.reduce<Bosses>((prev, curr, index) => {
|
||||||
const newBosses = { ...prev };
|
const newBosses = { ...prev };
|
||||||
newBosses[BOSSES[index]] = curr;
|
newBosses[filteredBosses[index]] = curr;
|
||||||
return newBosses;
|
return newBosses;
|
||||||
}, {} as Bosses);
|
}, {} as Bosses);
|
||||||
|
|
||||||
@@ -250,7 +256,7 @@ export async function getStatsByGamemode(
|
|||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
throw Error('Player not found');
|
throw Error('Player not found');
|
||||||
}
|
}
|
||||||
const stats = parseStats(response.data);
|
const stats = parseStats(response.data, mode);
|
||||||
|
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ export type Boss =
|
|||||||
| 'gauntlet'
|
| 'gauntlet'
|
||||||
| 'corruptedGauntlet'
|
| 'corruptedGauntlet'
|
||||||
| 'theatreOfBlood'
|
| 'theatreOfBlood'
|
||||||
|
| 'theatreOfBloodHardMode'
|
||||||
| 'thermonuclearSmokeDevil'
|
| 'thermonuclearSmokeDevil'
|
||||||
| 'tzKalZuk'
|
| 'tzKalZuk'
|
||||||
| 'tzTokJad'
|
| 'tzTokJad'
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ export const BOSSES: Boss[] = [
|
|||||||
'gauntlet',
|
'gauntlet',
|
||||||
'corruptedGauntlet',
|
'corruptedGauntlet',
|
||||||
'theatreOfBlood',
|
'theatreOfBlood',
|
||||||
|
'theatreOfBloodHardMode',
|
||||||
'thermonuclearSmokeDevil',
|
'thermonuclearSmokeDevil',
|
||||||
'tzKalZuk',
|
'tzKalZuk',
|
||||||
'tzTokJad',
|
'tzTokJad',
|
||||||
@@ -173,6 +174,7 @@ export const FORMATTED_BOSS_NAMES: FormattedBossNames = {
|
|||||||
gauntlet: 'The Gauntlet',
|
gauntlet: 'The Gauntlet',
|
||||||
corruptedGauntlet: 'The Corrupted Gauntlet',
|
corruptedGauntlet: 'The Corrupted Gauntlet',
|
||||||
theatreOfBlood: 'Theatre of Blood',
|
theatreOfBlood: 'Theatre of Blood',
|
||||||
|
theatreOfBloodHardMode: 'Theatre of Blood: Hard Mode',
|
||||||
thermonuclearSmokeDevil: 'Thermonuclear Smoke Devil',
|
thermonuclearSmokeDevil: 'Thermonuclear Smoke Devil',
|
||||||
tzKalZuk: 'TzKal-Zuk',
|
tzKalZuk: 'TzKal-Zuk',
|
||||||
tzTokJad: 'TzTok-Jad',
|
tzTokJad: 'TzTok-Jad',
|
||||||
|
|||||||
@@ -4,7 +4,12 @@
|
|||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"outDir": "./lib",
|
"outDir": "./lib",
|
||||||
"strict": true
|
"strict": true,
|
||||||
|
"lib": ["ES2015", "DOM", "DOM.Iterable"],
|
||||||
|
"typeRoots": [
|
||||||
|
"./node_modules/@types",
|
||||||
|
"./src/@types"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
"exclude": ["node_modules", "**/__tests__/*"]
|
"exclude": ["node_modules", "**/__tests__/*"]
|
||||||
|
|||||||
@@ -6364,9 +6364,9 @@ write-file-atomic@^3.0.0:
|
|||||||
typedarray-to-buffer "^3.1.5"
|
typedarray-to-buffer "^3.1.5"
|
||||||
|
|
||||||
ws@^7.2.3:
|
ws@^7.2.3:
|
||||||
version "7.4.2"
|
version "7.4.6"
|
||||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd"
|
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
|
||||||
integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==
|
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
|
||||||
|
|
||||||
xdg-basedir@^4.0.0:
|
xdg-basedir@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user