mirror of
				https://github.com/maxswa/osrs-json-hiscores.git
				synced 2025-10-15 10:19:04 +00:00 
			
		
		
		
	Compare commits
	
		
			21 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | eaa3d4a299 | ||
|   | a92fa7fffe | ||
|   | 90f2939761 | ||
|   | 12046246ef | ||
|   | adf73e59c4 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | f2fcbad1c4 | ||
|   | 0f47310814 | ||
|   | 30530fde01 | ||
|   | 2c0268939d | ||
|   | 0142783d43 | ||
|   | 468b43f66f | ||
|   | d5bbe2a169 | ||
|   | 26d06da24b | ||
|   | 582a5c01fd | ||
|   | 0138dcd5fd | ||
|   | f1730d44ec | ||
|   | ae73fef5ed | ||
|   | 8bf1f6cdbc | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 50d8365e87 | ||
|   | 8f9c9777e5 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 470d788327 | 
							
								
								
									
										120
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								README.md
									
									
									
									
									
								
							| @@ -68,17 +68,17 @@ const topPage = await getSkillPage('overall'); | ||||
| `getStats` will return a full player object with gamemode.   | ||||
| `getStatsByGameMode` will return a stats object and accepts a gamemode parameter: | ||||
|  | ||||
| | Game mode        | Param  | | ||||
| | ---------------- | :----: | | ||||
| | Regular          | `main` | | ||||
| | Ironman          | `iron` | | ||||
| | Hardcore Ironman |  `hc`  | | ||||
| | Ultimate Ironman | `ult`  | | ||||
| | Deadman Mode     | `dmm`  | | ||||
| | Seasonal Deadman | `sdmm` | | ||||
| | DMM Tournament   | `dmmt` | | ||||
| | Game mode        |    Param     | | ||||
| | ---------------- | :----------: | | ||||
| | Regular          |    `main`    | | ||||
| | Ironman          |  `ironman`   | | ||||
| | Hardcore Ironman |  `hardcore`  | | ||||
| | Ultimate Ironman |  `ultimate`  | | ||||
| | Deadman Mode     |  `deadman`   | | ||||
| | Tournament       | `tournament` | | ||||
| | Leagues          |  `seasonal`  | | ||||
|  | ||||
| `getSkillPage` and `getActivityPage` require a skill/activity and optionally a gamemode and page: | ||||
| `getSkillPage` and `getActivityPage` require a skill / activity and optionally a gamemode and page: | ||||
|  | ||||
| ```javascript | ||||
| hiscores | ||||
| @@ -87,27 +87,82 @@ hiscores | ||||
|   .catch(err => console.error(err)); | ||||
| ``` | ||||
|  | ||||
| Activities consist of all levels of clue scrolls as well as minigames: | ||||
| Activities consist of all levels of clue scrolls as well as minigames and bosses: | ||||
|  | ||||
| ### Clue Scrolls | ||||
|  | ||||
| | Type     |      Param      | | ||||
| | -------- | :-------------: | | ||||
| | All      |   `allclues`    | | ||||
| | Beginner | `beginnerclues` | | ||||
| | Easy     |   `easyclues`   | | ||||
| | Medium   |  `mediumclues`  | | ||||
| | Hard     |   `hardclues`   | | ||||
| | Elite    |  `eliteclues`   | | ||||
| | Master   |  `masterclues`  | | ||||
| | All      |   `allClues`    | | ||||
| | Beginner | `beginnerClues` | | ||||
| | Easy     |   `easyClues`   | | ||||
| | Medium   |  `mediumClues`  | | ||||
| | Hard     |   `hardClues`   | | ||||
| | Elite    |  `eliteClues`   | | ||||
| | Master   |  `masterClues`  | | ||||
|  | ||||
| ### Minigames | ||||
|  | ||||
| | Minigame               |   Param    | | ||||
| | ---------------------- | :--------: | | ||||
| | Bounty Hunter (Rogue)  | `roguebh`  | | ||||
| | Bounty Hunter (Hunter) | `hunterbh` | | ||||
| | Last Man Standing      |   `lms`    | | ||||
| | Minigame               |       Param       | | ||||
| | ---------------------- | :---------------: | | ||||
| | Bounty Hunter (Rogue)  |     `rogueBH`     | | ||||
| | Bounty Hunter (Hunter) |    `hunterBH`     | | ||||
| | Last Man Standing      | `lastManStanding` | | ||||
|  | ||||
| ### Leagues | ||||
|  | ||||
| | Activity      |     Param      | | ||||
| | ------------- | :------------: | | ||||
| | League Points | `leaguePoints` | | ||||
|  | ||||
| ### Bosses | ||||
|  | ||||
| | Boss Name                        |             Param              | | ||||
| | -------------------------------- | :----------------------------: | | ||||
| | Abyssal Sire                     |         `abyssalSire`          | | ||||
| | Alchemical Hydra                 |       `alchemicalHydra`        | | ||||
| | Barrows Chests                   |           `barrows`            | | ||||
| | Bryophyta                        |          `bryophyta`           | | ||||
| | Callisto                         |           `callisto`           | | ||||
| | Cerberus                         |           `cerberus`           | | ||||
| | Chambers Of Xeric                |       `chambersOfXeric`        | | ||||
| | Chambers Of Xeric Challenge Mode | `chambersOfXericChallengeMode` | | ||||
| | Chaos Elemental                  |        `chaosElemental`        | | ||||
| | Chaos Fanatic                    |         `chaosFanatic`         | | ||||
| | Commander Zilyana                |       `commanderZilyana`       | | ||||
| | Corporeal Beast                  |        `corporealBeast`        | | ||||
| | Crazy Archaeologist              |      `crazyArchaeologist`      | | ||||
| | Dagannoth Prime                  |        `dagannothPrime`        | | ||||
| | Dagannoth Rex                    |         `dagannothRex`         | | ||||
| | Dagannoth Supreme                |       `dagannothSupreme`       | | ||||
| | Deranged Archaeologist           |    `derangedArchaeologist`     | | ||||
| | General Graardor                 |       `generalGraardor`        | | ||||
| | Giant Mole                       |          `giantMole`           | | ||||
| | Grotesque Guardians              |      `grotesqueGuardians`      | | ||||
| | Hespori                          |           `hespori`            | | ||||
| | Kalphite Queen                   |        `kalphiteQueen`         | | ||||
| | King Black Dragon                |       `kingBlackDragon`        | | ||||
| | Kraken                           |            `kraken`            | | ||||
| | Kreearra                         |           `kreeArra`           | | ||||
| | K'ril Tsutsaroth                 |        `krilTsutsaroth`        | | ||||
| | Mimic                            |            `mimic`             | | ||||
| | The Nightmare of Ashihama        |          `nightmare`           | | ||||
| | Obor                             |             `obor`             | | ||||
| | Sarachnis                        |          `sarachnis`           | | ||||
| | Scorpia                          |           `scorpia`            | | ||||
| | Skotizo                          |           `skotizo`            | | ||||
| | Gauntlet                         |           `gauntlet`           | | ||||
| | Corrupted Gauntlet               |      `corruptedGauntlet`       | | ||||
| | Theatre Of Blood                 |        `theatreOfBlood`        | | ||||
| | Thermonuclear Smoke Devil        |   `thermonuclearSmokeDevil`    | | ||||
| | TzKal-Zuk                        |           `tzKalZuk`           | | ||||
| | TzTok-Jad                        |           `tzTokJad`           | | ||||
| | Venenatis                        |          `venenatis`           | | ||||
| | Vetion                           |            `vetion`            | | ||||
| | Vorkath                          |           `vorkath`            | | ||||
| | Wintertodt                       |          `wintertodt`          | | ||||
| | Zalcano                          |           `zalcano`            | | ||||
| | Zulrah                           |            `zulrah`            | | ||||
|  | ||||
| ## What you'll get | ||||
|  | ||||
| @@ -115,7 +170,7 @@ Activities consist of all levels of clue scrolls as well as minigames: | ||||
|  | ||||
| ```javascript | ||||
| { | ||||
|   rsn: 'Lynx Titan', | ||||
|   name: 'Lynx Titan', | ||||
|   mode: 'main', | ||||
|   dead: false, | ||||
|   deulted: false, | ||||
| @@ -128,8 +183,10 @@ Activities consist of all levels of clue scrolls as well as minigames: | ||||
|       // ... | ||||
|     }, | ||||
|     clues: {}, | ||||
|     bh: {}, | ||||
|     lms: {} | ||||
|     leaguePoints: {}, | ||||
|     bountyHunter: {}, | ||||
|     lastManStanding: {}, | ||||
|     bosses: {} | ||||
|   } | ||||
| } | ||||
| ``` | ||||
| @@ -138,9 +195,18 @@ Activities consist of all levels of clue scrolls as well as minigames: | ||||
|  | ||||
| ```javascript | ||||
| [ | ||||
|   { rank: 1, rsn: 'Lynx Titan', level: 2277, xp: 4600000000, dead: false }, | ||||
|   { rank: 1, name: 'Lynx Titan', level: 2277, xp: 4600000000, dead: false }, | ||||
|   {}, | ||||
|   {}, | ||||
|   // ... | ||||
| ]; | ||||
| ``` | ||||
|  | ||||
| ## Helpful Extras | ||||
|  | ||||
| Get the properly formatted name of any skill, boss, clue or other activity: | ||||
|  | ||||
| ```javascript | ||||
| // kril === "K'ril Tsutsaroth" | ||||
| const kril = FORMATTED_BOSS_NAMES['krilTsutsaroth']; | ||||
| ``` | ||||
|   | ||||
| @@ -1,322 +1,404 @@ | ||||
| import { | ||||
|   parseStats, | ||||
|   getRSNFormat, | ||||
|   getSkillPage, | ||||
|   getStats, | ||||
|   getStatsByGamemode, | ||||
|   getRSNFormat, | ||||
|   Stats, | ||||
| } from '../src/index'; | ||||
| import { PlayerSkillRow, Player, Stats } from '../src/types'; | ||||
| import axios, { AxiosError } from 'axios'; | ||||
|  | ||||
| test('Parse CSV to json', () => { | ||||
|   const csv = `40258,2063,218035714 | ||||
|   20554, 99, 21102621 | ||||
|   39059, 99, 15364425 | ||||
|   14245, 99, 26556827 | ||||
|   19819, 99, 33511407 | ||||
|   27857, 99, 25774115 | ||||
|   44278, 91, 6081159 | ||||
|   40110, 99, 15128024 | ||||
|   178948, 90, 5347474 | ||||
|   175463, 81, 2355494 | ||||
|   138677, 90, 5356303 | ||||
|   77587, 91, 5904710 | ||||
|   158478, 85, 3570485 | ||||
|   93958, 83, 2684426 | ||||
|   39179, 88, 4425107 | ||||
|   138406, 77, 1591377 | ||||
|   33399, 90, 5866307 | ||||
|   1794, 99, 15057674 | ||||
|   45551, 91, 6363261 | ||||
|   121165, 90, 5748493 | ||||
|   89460, 88, 4624078 | ||||
|   53099, 80, 2008229 | ||||
|   169127, 73, 1067670 | ||||
|   115543, 82, 2546048 | ||||
|     -1, -1 | ||||
|     -1, -1 | ||||
|   32875, 500 | ||||
|   24817, 476 | ||||
|   212728, 1 | ||||
|   94827, 20 | ||||
|   59099, 74 | ||||
|   24642, 231 | ||||
|   5206, 99 | ||||
|   6293, 51`; | ||||
|   const csv = `246,2277,1338203419 | ||||
|   615,99,77438259 | ||||
|   428,99,69176307 | ||||
|   425,99,115218641 | ||||
|   138,99,181425111 | ||||
|   160,99,169725807 | ||||
|   97,99,50666171 | ||||
|   144,99,93155913 | ||||
|   2108,99,53198880 | ||||
|   5750,99,19589494 | ||||
|   295,99,76386488 | ||||
|   1304,99,32252994 | ||||
|   847,99,54325931 | ||||
|   534,99,26379932 | ||||
|   7213,99,13246799 | ||||
|   2475,99,18161285 | ||||
|   1837,99,14746134 | ||||
|   668,99,23961670 | ||||
|   3841,99,17970837 | ||||
|   265,99,56230978 | ||||
|   821,99,62123353 | ||||
|   169,99,43127930 | ||||
|   810,99,37688883 | ||||
|   92,99,32005622 | ||||
|   -1,-1 | ||||
|   -1,-1 | ||||
|   -1,-1 | ||||
|   32,12148 | ||||
|   3105,76 | ||||
|   1997,505 | ||||
|   127,4259 | ||||
|   361,915 | ||||
|   392,250 | ||||
|   1,6143 | ||||
|   4814,898 | ||||
|   382,2780 | ||||
|   944,3000 | ||||
|   1981,1452 | ||||
|   4981,23 | ||||
|   888,1046 | ||||
|   613,4856 | ||||
|   102,4038 | ||||
|   156,334 | ||||
|   6240,133 | ||||
|   4569,250 | ||||
|   6893,603 | ||||
|   1,17798 | ||||
|   9320,125 | ||||
|   1030,2802 | ||||
|   4342,1655 | ||||
|   966,2951 | ||||
|   10151,1 | ||||
|   1288,2407 | ||||
|   377,4669 | ||||
|   545,1567 | ||||
|   6083,94 | ||||
|   264,2897 | ||||
|   4052,1277 | ||||
|   41643,1477 | ||||
|   625,2391 | ||||
|   120,2981 | ||||
|   1,109 | ||||
|   3,22666 | ||||
|   26,323 | ||||
|   201,1101 | ||||
|   82,3404 | ||||
|   5085,61 | ||||
|   63,375 | ||||
|   2870,6 | ||||
|   6984,138 | ||||
|   4043,2000 | ||||
|   489,8 | ||||
|   967,47 | ||||
|   11155,223 | ||||
|   1940,272 | ||||
|   8623,1340 | ||||
|   605,1694 | ||||
|   -1,-1 | ||||
|   3867,4583`; | ||||
|  | ||||
|   expect(parseStats(csv)).toStrictEqual({ | ||||
|   const expectedOutput: Stats = { | ||||
|     skills: { | ||||
|       overall: { rank: 40258, level: 2063, xp: 218035714 }, | ||||
|       attack: { rank: 20554, level: 99, xp: 21102621 }, | ||||
|       defence: { rank: 39059, level: 99, xp: 15364425 }, | ||||
|       strength: { rank: 14245, level: 99, xp: 26556827 }, | ||||
|       hitpoints: { rank: 19819, level: 99, xp: 33511407 }, | ||||
|       ranged: { rank: 27857, level: 99, xp: 25774115 }, | ||||
|       prayer: { rank: 44278, level: 91, xp: 6081159 }, | ||||
|       magic: { rank: 40110, level: 99, xp: 15128024 }, | ||||
|       cooking: { rank: 178948, level: 90, xp: 5347474 }, | ||||
|       woodcutting: { rank: 175463, level: 81, xp: 2355494 }, | ||||
|       fletching: { rank: 138677, level: 90, xp: 5356303 }, | ||||
|       fishing: { rank: 77587, level: 91, xp: 5904710 }, | ||||
|       firemaking: { rank: 158478, level: 85, xp: 3570485 }, | ||||
|       crafting: { rank: 93958, level: 83, xp: 2684426 }, | ||||
|       smithing: { rank: 39179, level: 88, xp: 4425107 }, | ||||
|       mining: { rank: 138406, level: 77, xp: 1591377 }, | ||||
|       herblore: { rank: 33399, level: 90, xp: 5866307 }, | ||||
|       agility: { rank: 1794, level: 99, xp: 15057674 }, | ||||
|       thieving: { rank: 45551, level: 91, xp: 6363261 }, | ||||
|       slayer: { rank: 121165, level: 90, xp: 5748493 }, | ||||
|       farming: { rank: 89460, level: 88, xp: 4624078 }, | ||||
|       runecraft: { rank: 53099, level: 80, xp: 2008229 }, | ||||
|       hunter: { rank: 169127, level: 73, xp: 1067670 }, | ||||
|       construction: { rank: 115543, level: 82, xp: 2546048 }, | ||||
|       overall: { rank: 246, level: 2277, xp: 1338203419 }, | ||||
|       attack: { rank: 615, level: 99, xp: 77438259 }, | ||||
|       defence: { rank: 428, level: 99, xp: 69176307 }, | ||||
|       strength: { rank: 425, level: 99, xp: 115218641 }, | ||||
|       hitpoints: { rank: 138, level: 99, xp: 181425111 }, | ||||
|       ranged: { rank: 160, level: 99, xp: 169725807 }, | ||||
|       prayer: { rank: 97, level: 99, xp: 50666171 }, | ||||
|       magic: { rank: 144, level: 99, xp: 93155913 }, | ||||
|       cooking: { rank: 2108, level: 99, xp: 53198880 }, | ||||
|       woodcutting: { rank: 5750, level: 99, xp: 19589494 }, | ||||
|       fletching: { rank: 295, level: 99, xp: 76386488 }, | ||||
|       fishing: { rank: 1304, level: 99, xp: 32252994 }, | ||||
|       firemaking: { rank: 847, level: 99, xp: 54325931 }, | ||||
|       crafting: { rank: 534, level: 99, xp: 26379932 }, | ||||
|       smithing: { rank: 7213, level: 99, xp: 13246799 }, | ||||
|       mining: { rank: 2475, level: 99, xp: 18161285 }, | ||||
|       herblore: { rank: 1837, level: 99, xp: 14746134 }, | ||||
|       agility: { rank: 668, level: 99, xp: 23961670 }, | ||||
|       thieving: { rank: 3841, level: 99, xp: 17970837 }, | ||||
|       slayer: { rank: 265, level: 99, xp: 56230978 }, | ||||
|       farming: { rank: 821, level: 99, xp: 62123353 }, | ||||
|       runecraft: { rank: 169, level: 99, xp: 43127930 }, | ||||
|       hunter: { rank: 810, level: 99, xp: 37688883 }, | ||||
|       construction: { rank: 92, level: 99, xp: 32005622 }, | ||||
|     }, | ||||
|     bh: { | ||||
|     leaguePoints: { rank: -1, score: -1 }, | ||||
|     bountyHunter: { | ||||
|       rogue: { rank: -1, score: -1 }, | ||||
|       hunter: { rank: -1, score: -1 }, | ||||
|     }, | ||||
|     lms: { rank: 32875, score: 500 }, | ||||
|     lastManStanding: { rank: 4814, score: 898 }, | ||||
|     clues: { | ||||
|       all: { rank: 24817, score: 476 }, | ||||
|       beginner: { rank: 212728, score: 1 }, | ||||
|       easy: { rank: 94827, score: 20 }, | ||||
|       medium: { rank: 59099, score: 74 }, | ||||
|       hard: { rank: 24642, score: 231 }, | ||||
|       elite: { rank: 5206, score: 99 }, | ||||
|       master: { rank: 6293, score: 51 }, | ||||
|       all: { rank: 32, score: 12148 }, | ||||
|       beginner: { rank: 3105, score: 76 }, | ||||
|       easy: { rank: 1997, score: 505 }, | ||||
|       medium: { rank: 127, score: 4259 }, | ||||
|       hard: { rank: 361, score: 915 }, | ||||
|       elite: { rank: 392, score: 250 }, | ||||
|       master: { rank: 1, score: 6143 }, | ||||
|     }, | ||||
|     bosses: { | ||||
|       abyssalSire: { rank: 382, score: 2780 }, | ||||
|       alchemicalHydra: { rank: 944, score: 3000 }, | ||||
|       barrows: { rank: 1981, score: 1452 }, | ||||
|       bryophyta: { rank: 4981, score: 23 }, | ||||
|       callisto: { rank: 888, score: 1046 }, | ||||
|       cerberus: { rank: 613, score: 4856 }, | ||||
|       chambersOfXeric: { rank: 102, score: 4038 }, | ||||
|       chambersOfXericChallengeMode: { rank: 156, score: 334 }, | ||||
|       chaosElemental: { rank: 6240, score: 133 }, | ||||
|       chaosFanatic: { rank: 4569, score: 250 }, | ||||
|       commanderZilyana: { rank: 6893, score: 603 }, | ||||
|       corporealBeast: { rank: 1, score: 17798 }, | ||||
|       crazyArchaeologist: { rank: 9320, score: 125 }, | ||||
|       dagannothPrime: { rank: 1030, score: 2802 }, | ||||
|       dagannothRex: { rank: 4342, score: 1655 }, | ||||
|       dagannothSupreme: { rank: 966, score: 2951 }, | ||||
|       derangedArchaeologist: { rank: 10151, score: 1 }, | ||||
|       generalGraardor: { rank: 1288, score: 2407 }, | ||||
|       giantMole: { rank: 377, score: 4669 }, | ||||
|       grotesqueGuardians: { rank: 545, score: 1567 }, | ||||
|       hespori: { rank: 6083, score: 94 }, | ||||
|       kalphiteQueen: { rank: 264, score: 2897 }, | ||||
|       kingBlackDragon: { rank: 4052, score: 1277 }, | ||||
|       kraken: { rank: 41643, score: 1477 }, | ||||
|       kreeArra: { rank: 625, score: 2391 }, | ||||
|       krilTsutsaroth: { rank: 120, score: 2981 }, | ||||
|       mimic: { rank: 1, score: 109 }, | ||||
|       nightmare: { rank: 3, score: 22666 }, | ||||
|       obor: { rank: 26, score: 323 }, | ||||
|       sarachnis: { rank: 201, score: 1101 }, | ||||
|       scorpia: { rank: 82, score: 3404 }, | ||||
|       skotizo: { rank: 5085, score: 61 }, | ||||
|       gauntlet: { rank: 63, score: 375 }, | ||||
|       corruptedGauntlet: { rank: 2870, score: 6 }, | ||||
|       theatreOfBlood: { rank: 6984, score: 138 }, | ||||
|       thermonuclearSmokeDevil: { rank: 4043, score: 2000 }, | ||||
|       tzKalZuk: { rank: 489, score: 8 }, | ||||
|       tzTokJad: { rank: 967, score: 47 }, | ||||
|       venenatis: { rank: 11155, score: 223 }, | ||||
|       vetion: { rank: 1940, score: 272 }, | ||||
|       vorkath: { rank: 8623, score: 1340 }, | ||||
|       wintertodt: { rank: 605, score: 1694 }, | ||||
|       zalcano: { rank: -1, score: -1 }, | ||||
|       zulrah: { rank: 3867, score: 4583 }, | ||||
|     }, | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| test('Get rsn format', async done => { | ||||
|   const callback = (data: string) => { | ||||
|     expect(data).toBe('Lynx Titan'); | ||||
|     done(); | ||||
|   }; | ||||
|  | ||||
|   getRSNFormat('lYnX tiTaN').then(callback); | ||||
|   expect(parseStats(csv)).toStrictEqual(expectedOutput); | ||||
| }); | ||||
|  | ||||
| test('Get attack top page', async done => { | ||||
|   const callback = (data: PlayerSkillRow[]) => { | ||||
|     expect(data).toMatchObject([ | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 1, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 2, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { rsn: 'Drakon', rank: 3, level: 99, xp: 200000000, dead: false }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 4, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 5, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 6, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 7, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 8, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 9, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 10, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 11, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 12, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 13, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 14, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 15, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 16, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 17, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 18, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 19, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 20, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 21, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 22, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 23, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 24, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|       { | ||||
|         rsn: expect.any(String), | ||||
|         rank: 25, | ||||
|         level: 99, | ||||
|         xp: 200000000, | ||||
|         dead: false, | ||||
|       }, | ||||
|     ]); | ||||
|     done(); | ||||
|   }; | ||||
|  | ||||
|   getSkillPage('attack').then(callback); | ||||
| test('Get name format', async () => { | ||||
|   jest.setTimeout(30000); | ||||
|   const data = await getRSNFormat('lYnX tiTaN'); | ||||
|   expect(data).toBe('Lynx Titan'); | ||||
| }); | ||||
|  | ||||
| test('Get non-existant player', async done => { | ||||
|   const callback = (err: AxiosError) => { | ||||
| test('Get attack top page', async () => { | ||||
|   jest.setTimeout(30000); | ||||
|   const data = await getSkillPage('attack'); | ||||
|   expect(data).toMatchObject([ | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 1, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 2, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { name: 'Drakon', rank: 3, level: 99, xp: 200000000, dead: false }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 4, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 5, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 6, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 7, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 8, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 9, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 10, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 11, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 12, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 13, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 14, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 15, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 16, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 17, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 18, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 19, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 20, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 21, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 22, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 23, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 24, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|     { | ||||
|       name: expect.any(String), | ||||
|       rank: 25, | ||||
|       level: 99, | ||||
|       xp: 200000000, | ||||
|       dead: false, | ||||
|     }, | ||||
|   ]); | ||||
| }); | ||||
|  | ||||
| test('Get non-existant player', async () => { | ||||
|   jest.setTimeout(30000); | ||||
|   getStats('fishy').catch(err => { | ||||
|     if (err.response) { | ||||
|       expect(err.response.status).toBe(404); | ||||
|     } | ||||
|     done(); | ||||
|   }; | ||||
|  | ||||
|   getStats('fishy').catch(callback); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| test('Get stats by gamemode', async done => { | ||||
|   const callback = (stats: Stats) => { | ||||
|     expect(stats.skills).toStrictEqual({ | ||||
|       overall: { rank: 1, level: 2277, xp: 4600000000 }, | ||||
|       attack: { rank: 15, level: 99, xp: 200000000 }, | ||||
|       defence: { rank: 27, level: 99, xp: 200000000 }, | ||||
|       strength: { rank: 18, level: 99, xp: 200000000 }, | ||||
|       hitpoints: { rank: 7, level: 99, xp: 200000000 }, | ||||
|       ranged: { rank: 7, level: 99, xp: 200000000 }, | ||||
|       prayer: { rank: 11, level: 99, xp: 200000000 }, | ||||
|       magic: { rank: 32, level: 99, xp: 200000000 }, | ||||
|       cooking: { rank: 158, level: 99, xp: 200000000 }, | ||||
|       woodcutting: { rank: 15, level: 99, xp: 200000000 }, | ||||
|       fletching: { rank: 12, level: 99, xp: 200000000 }, | ||||
|       fishing: { rank: 9, level: 99, xp: 200000000 }, | ||||
|       firemaking: { rank: 49, level: 99, xp: 200000000 }, | ||||
|       crafting: { rank: 4, level: 99, xp: 200000000 }, | ||||
|       smithing: { rank: 3, level: 99, xp: 200000000 }, | ||||
|       mining: { rank: 25, level: 99, xp: 200000000 }, | ||||
|       herblore: { rank: 5, level: 99, xp: 200000000 }, | ||||
|       agility: { rank: 24, level: 99, xp: 200000000 }, | ||||
|       thieving: { rank: 12, level: 99, xp: 200000000 }, | ||||
|       slayer: { rank: 2, level: 99, xp: 200000000 }, | ||||
|       farming: { rank: 19, level: 99, xp: 200000000 }, | ||||
|       runecraft: { rank: 7, level: 99, xp: 200000000 }, | ||||
|       hunter: { rank: 4, level: 99, xp: 200000000 }, | ||||
|       construction: { rank: 4, level: 99, xp: 200000000 }, | ||||
|     }); | ||||
|     done(); | ||||
|   }; | ||||
|  | ||||
|   getStatsByGamemode('Lynx Titan').then(callback); | ||||
| test('Get stats by gamemode', async () => { | ||||
|   jest.setTimeout(30000); | ||||
|   const { skills } = await getStatsByGamemode('Lynx Titan'); | ||||
|   expect(skills).toMatchObject({ | ||||
|     overall: { rank: expect.any(Number), level: 2277, xp: 4600000000 }, | ||||
|     attack: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     defence: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     strength: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     hitpoints: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     ranged: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     prayer: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     magic: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     cooking: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     woodcutting: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     fletching: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     fishing: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     firemaking: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     crafting: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     smithing: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     mining: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     herblore: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     agility: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     thieving: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     slayer: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     farming: { rank: expect.any(Number), level: 99, xp: 200000000 }, | ||||
|     runecraft: { 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 }, | ||||
|   }); | ||||
| }); | ||||
|   | ||||
| @@ -3,5 +3,6 @@ | ||||
|     "^.+\\.(t|j)sx?$": "ts-jest" | ||||
|   }, | ||||
|   "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", | ||||
|   "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"] | ||||
|   "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"], | ||||
|   "testEnvironment": "node" | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "osrs-json-hiscores", | ||||
|   "version": "1.2.2", | ||||
|   "version": "2.1.0", | ||||
|   "description": "The Oldschool Runescape API wrapper that does more!", | ||||
|   "main": "lib/index.js", | ||||
|   "types": "lib/index.d.ts", | ||||
| @@ -10,6 +10,7 @@ | ||||
|   "scripts": { | ||||
|     "dev": "watch 'yarn run build' src", | ||||
|     "build": "tsc", | ||||
|     "format": "prettier --write \"src/**/*.ts\"", | ||||
|     "test": "jest --config jestconfig.json", | ||||
|     "prepublish": "yarn run build", | ||||
|     "release": "np" | ||||
| @@ -43,6 +44,7 @@ | ||||
|     "@types/jest": "^24.0.14", | ||||
|     "jest": "^24.8.0", | ||||
|     "np": "^5.0.3", | ||||
|     "prettier": "^1.19.1", | ||||
|     "ts-jest": "^24.0.2", | ||||
|     "tslint": "^5.17.0", | ||||
|     "tslint-config-airbnb": "^5.11.1", | ||||
|   | ||||
							
								
								
									
										120
									
								
								src/hiscores.ts
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								src/hiscores.ts
									
									
									
									
									
								
							| @@ -13,6 +13,8 @@ import { | ||||
|   PlayerSkillRow, | ||||
|   ActivityName, | ||||
|   PlayerActivityRow, | ||||
|   Bosses, | ||||
|   Boss, | ||||
| } from './types'; | ||||
| import { | ||||
|   getStatsURL, | ||||
| @@ -26,6 +28,7 @@ import { | ||||
|   numberFromElement, | ||||
|   rsnFromElement, | ||||
|   getActivityPageURL, | ||||
|   BOSSES, | ||||
| } from './utils'; | ||||
|  | ||||
| export async function getStats(rsn: string): Promise<Player> { | ||||
| @@ -40,16 +43,16 @@ export async function getStats(rsn: string): Promise<Player> { | ||||
|   const mainRes = await axios(getStatsURL('main', rsn)); | ||||
|   if (mainRes.status === 200) { | ||||
|     const otherResponses = await Promise.all([ | ||||
|       axios(getStatsURL('iron', rsn)).catch(err => err), | ||||
|       axios(getStatsURL('hc', rsn)).catch(err => err), | ||||
|       axios(getStatsURL('ult', rsn)).catch(err => err), | ||||
|       getRSNFormat(rsn), | ||||
|       axios(getStatsURL('ironman', rsn)).catch(err => err), | ||||
|       axios(getStatsURL('hardcore', rsn)).catch(err => err), | ||||
|       axios(getStatsURL('ultimate', rsn)).catch(err => err), | ||||
|       getRSNFormat(rsn).catch(() => undefined), | ||||
|     ]); | ||||
|  | ||||
|     const [ironRes, hcRes, ultRes, formattedName] = otherResponses; | ||||
|  | ||||
|     const player: Player = { | ||||
|       rsn: formattedName, | ||||
|       name: formattedName || rsn, | ||||
|       mode: 'main', | ||||
|       dead: false, | ||||
|       deulted: false, | ||||
| @@ -58,32 +61,42 @@ export async function getStats(rsn: string): Promise<Player> { | ||||
|     player.main = parseStats(mainRes.data); | ||||
|  | ||||
|     if (ironRes.status === 200) { | ||||
|       player.iron = parseStats(ironRes.data); | ||||
|       player.ironman = parseStats(ironRes.data); | ||||
|       if (hcRes.status === 200) { | ||||
|         player.mode = 'hc'; | ||||
|         player.hc = parseStats(hcRes.data); | ||||
|         if (player.iron.skills.overall.xp !== player.hc.skills.overall.xp) { | ||||
|         player.mode = 'hardcore'; | ||||
|         player.hardcore = parseStats(hcRes.data); | ||||
|         if ( | ||||
|           player.ironman.skills.overall.xp !== player.hardcore.skills.overall.xp | ||||
|         ) { | ||||
|           player.dead = true; | ||||
|           player.mode = 'iron'; | ||||
|           player.mode = 'ironman'; | ||||
|         } | ||||
|         if (player.main.skills.overall.xp !== player.iron.skills.overall.xp) { | ||||
|         if ( | ||||
|           player.main.skills.overall.xp !== player.ironman.skills.overall.xp | ||||
|         ) { | ||||
|           player.deironed = true; | ||||
|           player.mode = 'main'; | ||||
|         } | ||||
|       } else if (ultRes.status === 200) { | ||||
|         player.mode = 'ult'; | ||||
|         player.ult = parseStats(ultRes.data); | ||||
|         if (player.iron.skills.overall.xp !== player.ult.skills.overall.xp) { | ||||
|         player.mode = 'ultimate'; | ||||
|         player.ultimate = parseStats(ultRes.data); | ||||
|         if ( | ||||
|           player.ironman.skills.overall.xp !== player.ultimate.skills.overall.xp | ||||
|         ) { | ||||
|           player.deulted = true; | ||||
|           player.mode = 'iron'; | ||||
|           player.mode = 'ironman'; | ||||
|         } | ||||
|         if (player.main.skills.overall.xp !== player.iron.skills.overall.xp) { | ||||
|         if ( | ||||
|           player.main.skills.overall.xp !== player.ironman.skills.overall.xp | ||||
|         ) { | ||||
|           player.deironed = true; | ||||
|           player.mode = 'main'; | ||||
|         } | ||||
|       } else { | ||||
|         player.mode = 'iron'; | ||||
|         if (player.main.skills.overall.xp !== player.iron.skills.overall.xp) { | ||||
|         player.mode = 'ironman'; | ||||
|         if ( | ||||
|           player.main.skills.overall.xp !== player.ironman.skills.overall.xp | ||||
|         ) { | ||||
|           player.deironed = true; | ||||
|           player.mode = 'main'; | ||||
|         } | ||||
| @@ -112,7 +125,7 @@ export async function getStatsByGamemode( | ||||
|   if (response.status !== 200) { | ||||
|     throw Error('Player not found'); | ||||
|   } | ||||
|   const stats: Stats = parseStats(response.data); | ||||
|   const stats = parseStats(response.data); | ||||
|  | ||||
|   return stats; | ||||
| } | ||||
| @@ -138,14 +151,15 @@ export async function getSkillPage( | ||||
|   const players: PlayerSkillRow[] = playersHTML.map(row => { | ||||
|     const cells = row.children.filter(el => el.name === 'td'); | ||||
|     const [rankEl, nameCell, levelEl, xpEl] = cells; | ||||
|     const [nameEl] = nameCell.children.filter(el => el.name === 'a'); | ||||
|     const nameEl = nameCell.children.find(el => el.name === 'a'); | ||||
|     const isDead = !!nameCell.children.find(el => el.name === 'img'); | ||||
|  | ||||
|     return { | ||||
|       rsn: rsnFromElement(nameEl), | ||||
|       name: rsnFromElement(nameEl), | ||||
|       rank: numberFromElement(rankEl), | ||||
|       level: numberFromElement(levelEl), | ||||
|       xp: numberFromElement(xpEl), | ||||
|       dead: nameCell.children.length === 4, | ||||
|       dead: isDead, | ||||
|     }; | ||||
|   }); | ||||
|  | ||||
| @@ -173,13 +187,14 @@ export async function getActivityPage( | ||||
|   const players: PlayerActivityRow[] = playersHTML.map(row => { | ||||
|     const cells = row.children.filter(el => el.name === 'td'); | ||||
|     const [rankEl, nameCell, scoreEl] = cells; | ||||
|     const [nameEl] = nameCell.children.filter(el => el.name === 'a'); | ||||
|     const nameEl = nameCell.children.find(el => el.name === 'a'); | ||||
|     const isDead = !!nameCell.children.find(el => el.name === 'img'); | ||||
|  | ||||
|     return { | ||||
|       rsn: rsnFromElement(nameEl), | ||||
|       name: rsnFromElement(nameEl), | ||||
|       rank: numberFromElement(rankEl), | ||||
|       score: numberFromElement(scoreEl), | ||||
|       dead: nameCell.children.length === 4, | ||||
|       dead: isDead, | ||||
|     }; | ||||
|   }); | ||||
|  | ||||
| @@ -238,42 +253,43 @@ export function parseStats(csv: string): Stats { | ||||
|       return activity; | ||||
|     }); | ||||
|  | ||||
|   const [leaguePoints] = activityObjects.splice(0, 1); | ||||
|   const bhObjects = activityObjects.splice(0, BH_MODES.length); | ||||
|   const [lms] = activityObjects.splice(0, 1); | ||||
|   const clueObjects = activityObjects.splice(0, CLUES.length); | ||||
|   const [lastManStanding] = activityObjects.splice(0, 1); | ||||
|   const bossObjects = activityObjects.splice(0, BOSSES.length); | ||||
|  | ||||
|   const skills: Skills = skillObjects.reduce<Skills>( | ||||
|     (prev, curr, index) => { | ||||
|       const newSkills = { ...prev }; | ||||
|       newSkills[SKILLS[index]] = curr; | ||||
|       return newSkills; | ||||
|     }, | ||||
|     {} as Skills | ||||
|   ); | ||||
|   const skills: Skills = skillObjects.reduce<Skills>((prev, curr, index) => { | ||||
|     const newSkills = { ...prev }; | ||||
|     newSkills[SKILLS[index]] = curr; | ||||
|     return newSkills; | ||||
|   }, {} as Skills); | ||||
|  | ||||
|   const bh: BH = bhObjects.reduce<BH>( | ||||
|     (prev, curr, index) => { | ||||
|       const newBH = { ...prev }; | ||||
|       newBH[BH_MODES[index]] = curr; | ||||
|       return newBH; | ||||
|     }, | ||||
|     {} as BH | ||||
|   ); | ||||
|   const bountyHunter: BH = bhObjects.reduce<BH>((prev, curr, index) => { | ||||
|     const newBH = { ...prev }; | ||||
|     newBH[BH_MODES[index]] = curr; | ||||
|     return newBH; | ||||
|   }, {} as BH); | ||||
|  | ||||
|   const clues: Clues = clueObjects.reduce<Clues>( | ||||
|     (prev, curr, index) => { | ||||
|       const newClues = { ...prev }; | ||||
|       newClues[CLUES[index]] = curr; | ||||
|       return newClues; | ||||
|     }, | ||||
|     {} as Clues | ||||
|   ); | ||||
|   const clues: Clues = clueObjects.reduce<Clues>((prev, curr, index) => { | ||||
|     const newClues = { ...prev }; | ||||
|     newClues[CLUES[index]] = curr; | ||||
|     return newClues; | ||||
|   }, {} as Clues); | ||||
|  | ||||
|   const bosses: Bosses = bossObjects.reduce<Bosses>((prev, curr, index) => { | ||||
|     const newBosses = { ...prev }; | ||||
|     newBosses[BOSSES[index]] = curr; | ||||
|     return newBosses; | ||||
|   }, {} as Bosses); | ||||
|  | ||||
|   const stats: Stats = { | ||||
|     skills, | ||||
|     bh, | ||||
|     lms, | ||||
|     leaguePoints, | ||||
|     bountyHunter, | ||||
|     lastManStanding, | ||||
|     clues, | ||||
|     bosses, | ||||
|   }; | ||||
|  | ||||
|   return stats; | ||||
|   | ||||
| @@ -2,5 +2,6 @@ import * as hiscores from './hiscores'; | ||||
|  | ||||
| export * from './hiscores'; | ||||
| export * from './types'; | ||||
| export * from './utils'; | ||||
|  | ||||
| export default hiscores; | ||||
|   | ||||
							
								
								
									
										92
									
								
								src/types.ts
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								src/types.ts
									
									
									
									
									
								
							| @@ -1,4 +1,11 @@ | ||||
| export type Gamemode = 'main' | 'iron' | 'hc' | 'ult' | 'dmm' | 'sdmm' | 'dmmt'; | ||||
| export type Gamemode = | ||||
|   | 'main' | ||||
|   | 'ironman' | ||||
|   | 'ultimate' | ||||
|   | 'hardcore' | ||||
|   | 'deadman' | ||||
|   | 'seasonal' | ||||
|   | 'tournament'; | ||||
|  | ||||
| export interface Skill { | ||||
|   rank: number; | ||||
| @@ -54,29 +61,80 @@ export type BHType = 'rogue' | 'hunter'; | ||||
|  | ||||
| export type BH = { [Type in BHType]: Activity }; | ||||
|  | ||||
| export type Boss = | ||||
|   | 'abyssalSire' | ||||
|   | 'alchemicalHydra' | ||||
|   | 'barrows' | ||||
|   | 'bryophyta' | ||||
|   | 'callisto' | ||||
|   | 'cerberus' | ||||
|   | 'chambersOfXeric' | ||||
|   | 'chambersOfXericChallengeMode' | ||||
|   | 'chaosElemental' | ||||
|   | 'chaosFanatic' | ||||
|   | 'commanderZilyana' | ||||
|   | 'corporealBeast' | ||||
|   | 'crazyArchaeologist' | ||||
|   | 'dagannothPrime' | ||||
|   | 'dagannothRex' | ||||
|   | 'dagannothSupreme' | ||||
|   | 'derangedArchaeologist' | ||||
|   | 'generalGraardor' | ||||
|   | 'giantMole' | ||||
|   | 'grotesqueGuardians' | ||||
|   | 'hespori' | ||||
|   | 'kalphiteQueen' | ||||
|   | 'kingBlackDragon' | ||||
|   | 'kraken' | ||||
|   | 'kreeArra' | ||||
|   | 'krilTsutsaroth' | ||||
|   | 'mimic' | ||||
|   | 'nightmare' | ||||
|   | 'obor' | ||||
|   | 'sarachnis' | ||||
|   | 'scorpia' | ||||
|   | 'skotizo' | ||||
|   | 'gauntlet' | ||||
|   | 'corruptedGauntlet' | ||||
|   | 'theatreOfBlood' | ||||
|   | 'thermonuclearSmokeDevil' | ||||
|   | 'tzKalZuk' | ||||
|   | 'tzTokJad' | ||||
|   | 'venenatis' | ||||
|   | 'vetion' | ||||
|   | 'vorkath' | ||||
|   | 'wintertodt' | ||||
|   | 'zalcano' | ||||
|   | 'zulrah'; | ||||
|  | ||||
| export type Bosses = { [Type in Boss]: Activity }; | ||||
|  | ||||
| export type ActivityName = | ||||
|   | 'hunterbh' | ||||
|   | 'roguebh' | ||||
|   | 'lms' | ||||
|   | 'allclues' | ||||
|   | 'beginnerclues' | ||||
|   | 'easyclues' | ||||
|   | 'mediumclues' | ||||
|   | 'hardclues' | ||||
|   | 'eliteclues' | ||||
|   | 'masterclues'; | ||||
|   | 'leaguePoints' | ||||
|   | 'hunterBH' | ||||
|   | 'rogueBH' | ||||
|   | 'lastManStanding' | ||||
|   | 'allClues' | ||||
|   | 'beginnerClues' | ||||
|   | 'easyClues' | ||||
|   | 'mediumClues' | ||||
|   | 'hardClues' | ||||
|   | 'eliteClues' | ||||
|   | 'masterClues' | ||||
|   | Boss; | ||||
|  | ||||
| export interface Stats { | ||||
|   skills: Skills; | ||||
|   clues: Clues; | ||||
|   bh: BH; | ||||
|   lms: Activity; | ||||
|   leaguePoints: Activity; | ||||
|   bountyHunter: BH; | ||||
|   lastManStanding: Activity; | ||||
|   bosses: Bosses; | ||||
| } | ||||
|  | ||||
| export type Modes = { [M in Gamemode]?: Stats }; | ||||
|  | ||||
| export interface Player extends Modes { | ||||
|   rsn: string; | ||||
|   name: string; | ||||
|   mode: Gamemode; | ||||
|   dead: boolean; | ||||
|   deulted: boolean; | ||||
| @@ -84,11 +142,11 @@ export interface Player extends Modes { | ||||
| } | ||||
|  | ||||
| export interface PlayerSkillRow extends Skill { | ||||
|   rsn: string; | ||||
|   name: string; | ||||
|   dead: boolean; | ||||
| } | ||||
|  | ||||
| export interface PlayerActivityRow extends Activity { | ||||
|   rsn: string; | ||||
|   name: string; | ||||
|   dead: boolean; | ||||
| } | ||||
|   | ||||
| @@ -1,16 +1,28 @@ | ||||
| import { SkillName, ClueType, BHType, Gamemode } from '../types'; | ||||
| import { | ||||
|   BHType, | ||||
|   Boss, | ||||
|   ClueType, | ||||
|   Gamemode, | ||||
|   SkillName, | ||||
|   ActivityName, | ||||
| } from '../types'; | ||||
|  | ||||
| export const BASE_URL = 'http://services.runescape.com/m=hiscore_oldschool'; | ||||
| export const BASE_URL = 'https://secure.runescape.com/m=hiscore_oldschool'; | ||||
| export const STATS_URL = 'index_lite.ws?player='; | ||||
| export const SCORES_URL = 'overall.ws?'; | ||||
| export const GAMEMODE_URL = { | ||||
|   dmm: '_deadman/', | ||||
|   dmmt: '_tournament/', | ||||
|   hc: '_hardcore_ironman/', | ||||
|   iron: '_ironman/', | ||||
|   main: '/', | ||||
|   sdmm: '_seasonal/', | ||||
|   ult: '_ultimate/', | ||||
|  | ||||
| export type GamemodeUrl = { | ||||
|   [key in Gamemode]: string; | ||||
| }; | ||||
|  | ||||
| export const GAMEMODE_URL: GamemodeUrl = { | ||||
|   main: `${BASE_URL}/`, | ||||
|   ironman: `${BASE_URL}_ironman/`, | ||||
|   hardcore: `${BASE_URL}_hardcore_ironman/`, | ||||
|   ultimate: `${BASE_URL}_ultimate/`, | ||||
|   deadman: `${BASE_URL}_deadman/`, | ||||
|   seasonal: `${BASE_URL}_seasonal/`, | ||||
|   tournament: `${BASE_URL}_tournament/`, | ||||
| }; | ||||
| export const SKILLS: SkillName[] = [ | ||||
|   'overall', | ||||
| @@ -48,24 +60,180 @@ export const CLUES: ClueType[] = [ | ||||
|   'master', | ||||
| ]; | ||||
| export const BH_MODES: BHType[] = ['rogue', 'hunter']; | ||||
| export const ACTIVITIES = [ | ||||
|   'hunterbh', | ||||
|   'roguebh', | ||||
|   'lms', | ||||
|   'allclues', | ||||
|   'beginnerclues', | ||||
|   'easyclues', | ||||
|   'mediumclues', | ||||
|   'hardclues', | ||||
|   'eliteclues', | ||||
|   'masterclues', | ||||
| ]; | ||||
| export const GAMEMODES: Gamemode[] = [ | ||||
|   'main', | ||||
|   'iron', | ||||
|   'hc', | ||||
|   'ult', | ||||
|   'dmm', | ||||
|   'sdmm', | ||||
|   'dmmt', | ||||
|   'ironman', | ||||
|   'hardcore', | ||||
|   'ultimate', | ||||
|   'deadman', | ||||
|   'seasonal', | ||||
|   'tournament', | ||||
| ]; | ||||
| export const BOSSES: Boss[] = [ | ||||
|   'abyssalSire', | ||||
|   'alchemicalHydra', | ||||
|   'barrows', | ||||
|   'bryophyta', | ||||
|   'callisto', | ||||
|   'cerberus', | ||||
|   'chambersOfXeric', | ||||
|   'chambersOfXericChallengeMode', | ||||
|   'chaosElemental', | ||||
|   'chaosFanatic', | ||||
|   'commanderZilyana', | ||||
|   'corporealBeast', | ||||
|   'crazyArchaeologist', | ||||
|   'dagannothPrime', | ||||
|   'dagannothRex', | ||||
|   'dagannothSupreme', | ||||
|   'derangedArchaeologist', | ||||
|   'generalGraardor', | ||||
|   'giantMole', | ||||
|   'grotesqueGuardians', | ||||
|   'hespori', | ||||
|   'kalphiteQueen', | ||||
|   'kingBlackDragon', | ||||
|   'kraken', | ||||
|   'kreeArra', | ||||
|   'krilTsutsaroth', | ||||
|   'mimic', | ||||
|   'nightmare', | ||||
|   'obor', | ||||
|   'sarachnis', | ||||
|   'scorpia', | ||||
|   'skotizo', | ||||
|   'gauntlet', | ||||
|   'corruptedGauntlet', | ||||
|   'theatreOfBlood', | ||||
|   'thermonuclearSmokeDevil', | ||||
|   'tzKalZuk', | ||||
|   'tzTokJad', | ||||
|   'venenatis', | ||||
|   'vetion', | ||||
|   'vorkath', | ||||
|   'wintertodt', | ||||
|   'zalcano', | ||||
|   'zulrah', | ||||
| ]; | ||||
| export const ACTIVITIES: ActivityName[] = [ | ||||
|   'leaguePoints', | ||||
|   'hunterBH', | ||||
|   'rogueBH', | ||||
|   'allClues', | ||||
|   'beginnerClues', | ||||
|   'easyClues', | ||||
|   'mediumClues', | ||||
|   'hardClues', | ||||
|   'eliteClues', | ||||
|   'masterClues', | ||||
|   'lastManStanding', | ||||
|   ...BOSSES, | ||||
| ]; | ||||
|  | ||||
| export type FormattedBossNames = { | ||||
|   [key in Boss]: string; | ||||
| }; | ||||
|  | ||||
| export const FORMATTED_BOSS_NAMES: FormattedBossNames = { | ||||
|   abyssalSire: 'Abyssal Sire', | ||||
|   alchemicalHydra: 'Alchemical Hydra', | ||||
|   barrows: 'Barrows Chests', | ||||
|   bryophyta: 'Bryophyta', | ||||
|   callisto: 'Callisto', | ||||
|   cerberus: 'Cerberus', | ||||
|   chambersOfXeric: 'Chambers of Xeric', | ||||
|   chambersOfXericChallengeMode: 'Chambers of Xeric: Challenge Mode', | ||||
|   chaosElemental: 'Chaos Elemental', | ||||
|   chaosFanatic: 'Chaos Fanatic', | ||||
|   commanderZilyana: 'Commander Zilyana', | ||||
|   corporealBeast: 'Corporeal Beast', | ||||
|   crazyArchaeologist: 'Crazy Archaeologist', | ||||
|   dagannothPrime: 'Dagannoth Prime', | ||||
|   dagannothRex: 'Dagannoth Rex', | ||||
|   dagannothSupreme: 'Dagannoth Supreme', | ||||
|   derangedArchaeologist: 'Deranged Archaeologist', | ||||
|   generalGraardor: 'General Graardor', | ||||
|   giantMole: 'Giant Mole', | ||||
|   grotesqueGuardians: 'Grotesque Guardians', | ||||
|   hespori: 'Hespori', | ||||
|   kalphiteQueen: 'Kalphite Queen', | ||||
|   kingBlackDragon: 'King Black Dragon', | ||||
|   kraken: 'Kraken', | ||||
|   kreeArra: "Kree'Arra", | ||||
|   krilTsutsaroth: "K'ril Tsutsaroth", | ||||
|   mimic: 'Mimic', | ||||
|   nightmare: 'The Nightmare of Ashihama', | ||||
|   obor: 'Obor', | ||||
|   sarachnis: 'Sarachnis', | ||||
|   scorpia: 'Scorpia', | ||||
|   skotizo: 'Skotizo', | ||||
|   gauntlet: 'The Gauntlet', | ||||
|   corruptedGauntlet: 'The Corrupted Gauntlet', | ||||
|   theatreOfBlood: 'Theatre of Blood', | ||||
|   thermonuclearSmokeDevil: 'Thermonuclear Smoke Devil', | ||||
|   tzKalZuk: 'TzKal-Zuk', | ||||
|   tzTokJad: 'TzTok-Jad', | ||||
|   venenatis: 'Venenatis', | ||||
|   vetion: "Vet'ion", | ||||
|   vorkath: 'Vorkath', | ||||
|   wintertodt: 'Wintertodt', | ||||
|   zalcano: 'Zalcano', | ||||
|   zulrah: 'Zulrah', | ||||
| }; | ||||
|  | ||||
| export type FormattedSkillNames = { | ||||
|   [key in SkillName]: string; | ||||
| }; | ||||
|  | ||||
| export const FORMATTED_SKILL_NAMES: FormattedSkillNames = { | ||||
|   overall: 'Overall', | ||||
|   attack: 'Attack', | ||||
|   defence: 'Defence', | ||||
|   strength: 'Strength', | ||||
|   hitpoints: 'Hitpoints', | ||||
|   ranged: 'Ranged', | ||||
|   prayer: 'Prayer', | ||||
|   magic: 'Magic', | ||||
|   cooking: 'Cooking', | ||||
|   woodcutting: 'Woodcutting', | ||||
|   fletching: 'Fletching', | ||||
|   fishing: 'Fishing', | ||||
|   firemaking: 'Firemaking', | ||||
|   crafting: 'Crafting', | ||||
|   smithing: 'Smithing', | ||||
|   mining: 'Mining', | ||||
|   herblore: 'Herblore', | ||||
|   agility: 'Agility', | ||||
|   thieving: 'Thieving', | ||||
|   slayer: 'Slayer', | ||||
|   farming: 'Farming', | ||||
|   runecraft: 'Runecraft', | ||||
|   hunter: 'Hunter', | ||||
|   construction: 'Construction', | ||||
| }; | ||||
|  | ||||
| export type FormattedClueNames = { | ||||
|   [key in ClueType]: string; | ||||
| }; | ||||
|  | ||||
| export const FORMATTED_CLUE_NAMES: FormattedClueNames = { | ||||
|   all: 'Clue Scrolls (all)', | ||||
|   beginner: 'Clue Scrolls (beginner)', | ||||
|   easy: 'Clue Scrolls (easy)', | ||||
|   medium: 'Clue Scrolls (medium)', | ||||
|   hard: 'Clue Scrolls (hard)', | ||||
|   elite: 'Clue Scrolls (elite)', | ||||
|   master: 'Clue Scrolls (master)', | ||||
| }; | ||||
|  | ||||
| export type FormattedBHNames = { | ||||
|   [key in BHType]: string; | ||||
| }; | ||||
|  | ||||
| export const FORMATTED_BH_NAMES: FormattedBHNames = { | ||||
|   rogue: 'Bounty Hunter - Rogue', | ||||
|   hunter: 'Bounty Hunter - Hunter', | ||||
| }; | ||||
|  | ||||
| export const FORMATTED_LMS = 'Last Man Standing'; | ||||
| export const FORMATTED_LEAGUE_POINTS = 'League Points'; | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import { Gamemode, SkillName, ActivityName } from '../types'; | ||||
| import { | ||||
|   BASE_URL, | ||||
|   GAMEMODE_URL, | ||||
|   STATS_URL, | ||||
|   SCORES_URL, | ||||
| @@ -9,19 +8,19 @@ import { | ||||
| } from './constants'; | ||||
|  | ||||
| export const getStatsURL = (gamemode: Gamemode, rsn: string) => | ||||
|   `${BASE_URL}${GAMEMODE_URL[gamemode]}${STATS_URL}${encodeURIComponent(rsn)}`; | ||||
|   `${GAMEMODE_URL[gamemode]}${STATS_URL}${encodeURIComponent(rsn)}`; | ||||
|  | ||||
| export const getPlayerTableURL = (gamemode: Gamemode, rsn: string) => | ||||
|   `${BASE_URL}${ | ||||
|     GAMEMODE_URL[gamemode] | ||||
|   }${SCORES_URL}table=0&user=${encodeURIComponent(rsn)}`; | ||||
|   `${GAMEMODE_URL[gamemode]}${SCORES_URL}table=0&user=${encodeURIComponent( | ||||
|     rsn | ||||
|   )}`; | ||||
|  | ||||
| export const getSkillPageURL = ( | ||||
|   gamemode: Gamemode, | ||||
|   skill: SkillName, | ||||
|   page: number | ||||
| ) => | ||||
|   `${BASE_URL}${GAMEMODE_URL[gamemode]}${SCORES_URL}table=${SKILLS.indexOf( | ||||
|   `${GAMEMODE_URL[gamemode]}${SCORES_URL}table=${SKILLS.indexOf( | ||||
|     skill | ||||
|   )}&page=${page}`; | ||||
|  | ||||
| @@ -30,7 +29,7 @@ export const getActivityPageURL = ( | ||||
|   activity: ActivityName, | ||||
|   page: number | ||||
| ) => | ||||
|   `${BASE_URL}${ | ||||
|   `${ | ||||
|     GAMEMODE_URL[gamemode] | ||||
|   }${SCORES_URL}category_type=1&table=${ACTIVITIES.indexOf( | ||||
|     activity | ||||
| @@ -42,7 +41,7 @@ export const numberFromElement = (el: CheerioElement) => { | ||||
|   return parseInt(number, 10); | ||||
| }; | ||||
|  | ||||
| export const rsnFromElement = (el: CheerioElement) => { | ||||
|   const innerText = el.firstChild.data; | ||||
| export const rsnFromElement = (el: CheerioElement | undefined) => { | ||||
|   const innerText = el?.firstChild.data; | ||||
|   return innerText ? innerText.replace(/\uFFFD/g, ' ') : ''; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user