Compare commits

...

15 Commits

Author SHA1 Message Date
maxswa
175f945ab8 v2.4.0 2021-03-24 22:49:58 -04:00
maxswa
6b31e8b08c Add Tempoross to boss list. 2021-03-24 22:46:37 -04:00
maxswa
d097567a3c v2.3.2 2021-02-13 11:22:26 -05:00
maxswa
be5c093cf7 Downgrade np. 2021-02-13 11:13:52 -05:00
maxswa
db72f0c57d Bump np. 2021-02-13 11:08:57 -05:00
Max Swartwout
bd2ea21980 Merge pull request #26 from maxswa/bh-order-fix
Fixes #25 Flipped BH modes.
2021-02-13 11:07:27 -05:00
maxswa
d67837c161 Fix flipped BH modes. 2021-02-13 10:50:58 -05:00
Max Swartwout
4aa6ad2752 Add github action. 2021-02-13 10:48:31 -05:00
maxswa
2f788fabf6 v2.3.1 2021-01-12 19:56:17 -05:00
maxswa
0f5aea795c Upgrade dependencies. 2021-01-12 19:55:36 -05:00
Max Swartwout
7acb84e310 Merge pull request #21 from maxswa/dependabot/npm_and_yarn/dot-prop-4.2.1
Bump dot-prop from 4.2.0 to 4.2.1
2021-01-12 19:48:41 -05:00
Max Swartwout
9619bd2a2b Merge pull request #23 from molo-pl/master
Fixes #22 adding User-Agent request header to bypass Incapsula
2021-01-12 19:48:29 -05:00
molo-pl
55abd9f800 Fixes #22 adding User-Agent request header - post review changes 2021-01-12 23:29:25 +01:00
molo-pl
cf8a4cc26e Fixes #22 adding User-Agent request header to bypass Incapsula protection of OSRS hiscore pages 2021-01-12 16:05:47 +01:00
dependabot[bot]
ae47df31f1 Bump dot-prop from 4.2.0 to 4.2.1
Bumps [dot-prop](https://github.com/sindresorhus/dot-prop) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/sindresorhus/dot-prop/releases)
- [Commits](https://github.com/sindresorhus/dot-prop/compare/v4.2.0...v4.2.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-01-10 21:00:31 +00:00
10 changed files with 1805 additions and 1741 deletions

18
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: borales/actions-yarn@v2.0.0
with:
cmd: install
- uses: borales/actions-yarn@v2.0.0
with:
cmd: build
- uses: borales/actions-yarn@v2.0.0
with:
cmd: test

View File

@@ -152,6 +152,7 @@ Activities consist of all levels of clue scrolls as well as minigames and bosses
| Sarachnis | `sarachnis` | | Sarachnis | `sarachnis` |
| Scorpia | `scorpia` | | Scorpia | `scorpia` |
| Skotizo | `skotizo` | | Skotizo | `skotizo` |
| Tempoross | `tempoross` |
| Gauntlet | `gauntlet` | | Gauntlet | `gauntlet` |
| Corrupted Gauntlet | `corruptedGauntlet` | | Corrupted Gauntlet | `corruptedGauntlet` |
| Theatre Of Blood | `theatreOfBlood` | | Theatre Of Blood | `theatreOfBlood` |

View File

@@ -32,9 +32,9 @@ test('Parse CSV to json', () => {
169,99,43127930 169,99,43127930
810,99,37688883 810,99,37688883
92,99,32005622 92,99,32005622
-1,-1 23423,478
-1,-1 99831,23
-1,-1 89912,37
32,12148 32,12148
3105,76 3105,76
1997,505 1997,505
@@ -76,6 +76,7 @@ test('Parse CSV to json', () => {
201,1101 201,1101
82,3404 82,3404
5085,61 5085,61
18823,23
63,375 63,375
2870,6 2870,6
6984,138 6984,138
@@ -116,10 +117,10 @@ test('Parse CSV to json', () => {
hunter: { rank: 810, level: 99, xp: 37688883 }, hunter: { rank: 810, level: 99, xp: 37688883 },
construction: { rank: 92, level: 99, xp: 32005622 }, construction: { rank: 92, level: 99, xp: 32005622 },
}, },
leaguePoints: { rank: -1, score: -1 }, leaguePoints: { rank: 23423, score: 478 },
bountyHunter: { bountyHunter: {
rogue: { rank: -1, score: -1 }, hunter: { rank: 99831, score: 23 },
hunter: { rank: -1, score: -1 }, rogue: { rank: 89912, score: 37 },
}, },
lastManStanding: { rank: 4814, score: 898 }, lastManStanding: { rank: 4814, score: 898 },
soulWarsZeal: { rank: 37, score: 225 }, soulWarsZeal: { rank: 37, score: 225 },
@@ -165,6 +166,7 @@ test('Parse CSV to json', () => {
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 },
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 },
theatreOfBlood: { rank: 6984, score: 138 }, theatreOfBlood: { rank: 6984, score: 138 },

View File

@@ -1,6 +1,6 @@
{ {
"name": "osrs-json-hiscores", "name": "osrs-json-hiscores",
"version": "2.3.0", "version": "2.4.0",
"description": "The Oldschool Runescape API wrapper that does more!", "description": "The Oldschool Runescape API wrapper that does more!",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
@@ -37,15 +37,16 @@
"homepage": "https://github.com/maxswa/osrs-json-hiscores#readme", "homepage": "https://github.com/maxswa/osrs-json-hiscores#readme",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
"jsdom": "^16.3.0" "jsdom": "^16.3.0",
"useragent-generator": "^1.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^24.0.14", "@types/jest": "^26.0.20",
"@types/jsdom": "^16.2.3", "@types/jsdom": "^16.2.3",
"jest": "^24.8.0", "jest": "^26.6.3",
"np": "^5.0.3", "np": "6.5.0",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"ts-jest": "^24.0.2", "ts-jest": "^26.4.4",
"tslint": "^5.17.0", "tslint": "^5.17.0",
"tslint-config-airbnb": "^5.11.1", "tslint-config-airbnb": "^5.11.1",
"tslint-config-prettier": "^1.18.0", "tslint-config-prettier": "^1.18.0",

51
src/@types/useragent-generator.d.ts vendored Normal file
View File

@@ -0,0 +1,51 @@
declare module 'useragent-generator' {
/********************
* Google Chrome *
/*******************/
export function chrome(opt: number | string | { version: string, os?: string }): string;
export namespace chrome {
function androidPhone(opt: number | string | { version: string, androidVersion?: string, device?: string }): string;
function androidTablet(opt: number | string | { version: string, androidVersion?: string, device?: string })
: string;
function androidWebview(opt: number | string | { androidVersion: string, chromeVersion?: string, device?: string })
: string;
function chromecast(opt: number | string | { version: string }): string;
function iOS(opt: number | string | { iOSVersion: string, chromeVersion?: string, device?: string }): string;
}
export function chromium(opt: number | string | { version: string, os?: string }): string;
/***************
* Firefox *
/*************/
export function firefox(opt: number | string | { version: string, os?: string }): string;
export namespace firefox {
function androidPhone(opt: number | string | { version: string, androidVersion?: string, device?: string }): string;
function androidTablet(opt: number | string | { version: string, androidVersion?: string, device?: string })
: string;
function iOS(opt: number | string | { iOSVersion: string, device?: string }): string;
}
/**************
* Safari *
/************/
export function safari(opt: number | string | { version: string, os?: string }): string;
export namespace safari {
function iOS(opt: number | string | { iOSVersion: string, safariVersion?: string, device?: string }): string;
function iOSWebview(opt: number | string | { iOSVersion: string, safariVersion?: string, device?: string }): string;
}
/***********************
* Internet Explorer *
/*********************/
export function ie(opt: number | string | { version: string, os?: string }): string;
export namespace ie {
function windowsPhone(opt: number | string | { version: string, device?: string }): string;
}
/**********************
* Microsoft Edge *
/********************/
export function edge(opt: number | string | { version: string, chromeVersion?: string, os?: string }): string;
/************************
* Search Engine Bots *
/**********************/
export function googleBot(opt?: number | string | { version?: string }): string;
export function bingBot(opt?: number | string | { version?: string }): string;
export function yahooBot(): string;
}

View File

@@ -1,4 +1,3 @@
import axios from 'axios';
import { import {
Player, Player,
Activity, Activity,
@@ -26,6 +25,7 @@ import {
numberFromElement, numberFromElement,
rsnFromElement, rsnFromElement,
getActivityPageURL, getActivityPageURL,
httpGet,
BOSSES, BOSSES,
} from './utils'; } from './utils';
import { JSDOM } from 'jsdom'; import { JSDOM } from 'jsdom';
@@ -39,12 +39,12 @@ export async function getStats(rsn: string): Promise<Player> {
throw Error('RSN must be between 1 and 12 characters'); throw Error('RSN must be between 1 and 12 characters');
} }
const mainRes = await axios(getStatsURL('main', rsn)); const mainRes = await httpGet(getStatsURL('main', rsn));
if (mainRes.status === 200) { if (mainRes.status === 200) {
const otherResponses = await Promise.all([ const otherResponses = await Promise.all([
axios(getStatsURL('ironman', rsn)).catch(err => err), httpGet(getStatsURL('ironman', rsn)).catch(err => err),
axios(getStatsURL('hardcore', rsn)).catch(err => err), httpGet(getStatsURL('hardcore', rsn)).catch(err => err),
axios(getStatsURL('ultimate', rsn)).catch(err => err), httpGet(getStatsURL('ultimate', rsn)).catch(err => err),
getRSNFormat(rsn).catch(() => undefined), getRSNFormat(rsn).catch(() => undefined),
]); ]);
@@ -120,7 +120,7 @@ export async function getStatsByGamemode(
} else if (!GAMEMODES.includes(mode)) { } else if (!GAMEMODES.includes(mode)) {
throw Error('Invalid game mode'); throw Error('Invalid game mode');
} }
const response = await axios(getStatsURL(mode, rsn)); const response = await httpGet(getStatsURL(mode, rsn));
if (response.status !== 200) { if (response.status !== 200) {
throw Error('Player not found'); throw Error('Player not found');
} }
@@ -143,7 +143,7 @@ export async function getSkillPage(
} }
const url = getSkillPageURL(mode, skill, page); const url = getSkillPageURL(mode, skill, page);
const response = await axios(url); const response = await httpGet(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'
@@ -183,7 +183,7 @@ export async function getActivityPage(
} }
const url = getActivityPageURL(mode, activity, page); const url = getActivityPageURL(mode, activity, page);
const response = await axios(url); const response = await httpGet(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'
@@ -218,7 +218,7 @@ export async function getRSNFormat(rsn: string): Promise<string> {
const url = getPlayerTableURL('main', rsn); const url = getPlayerTableURL('main', rsn);
try { try {
const response = await axios(url); const response = await httpGet(url);
const dom = new JSDOM(response.data); const dom = new JSDOM(response.data);
const spans = dom.window.document.querySelectorAll( const spans = dom.window.document.querySelectorAll(
'span[style="color:#AA0022;"]' 'span[style="color:#AA0022;"]'

View File

@@ -94,6 +94,7 @@ export type Boss =
| 'sarachnis' | 'sarachnis'
| 'scorpia' | 'scorpia'
| 'skotizo' | 'skotizo'
| 'tempoross'
| 'gauntlet' | 'gauntlet'
| 'corruptedGauntlet' | 'corruptedGauntlet'
| 'theatreOfBlood' | 'theatreOfBlood'

View File

@@ -59,7 +59,7 @@ export const CLUES: ClueType[] = [
'elite', 'elite',
'master', 'master',
]; ];
export const BH_MODES: BHType[] = ['rogue', 'hunter']; export const BH_MODES: BHType[] = ['hunter', 'rogue'];
export const GAMEMODES: Gamemode[] = [ export const GAMEMODES: Gamemode[] = [
'main', 'main',
'ironman', 'ironman',
@@ -102,6 +102,7 @@ export const BOSSES: Boss[] = [
'sarachnis', 'sarachnis',
'scorpia', 'scorpia',
'skotizo', 'skotizo',
'tempoross',
'gauntlet', 'gauntlet',
'corruptedGauntlet', 'corruptedGauntlet',
'theatreOfBlood', 'theatreOfBlood',
@@ -168,6 +169,7 @@ export const FORMATTED_BOSS_NAMES: FormattedBossNames = {
sarachnis: 'Sarachnis', sarachnis: 'Sarachnis',
scorpia: 'Scorpia', scorpia: 'Scorpia',
skotizo: 'Skotizo', skotizo: 'Skotizo',
tempoross: 'Tempoross',
gauntlet: 'The Gauntlet', gauntlet: 'The Gauntlet',
corruptedGauntlet: 'The Corrupted Gauntlet', corruptedGauntlet: 'The Corrupted Gauntlet',
theatreOfBlood: 'Theatre of Blood', theatreOfBlood: 'Theatre of Blood',

View File

@@ -1,3 +1,5 @@
import axios from 'axios';
import * as ua from 'useragent-generator';
import { Gamemode, SkillName, ActivityName } from '../types'; import { Gamemode, SkillName, ActivityName } from '../types';
import { import {
GAMEMODE_URL, GAMEMODE_URL,
@@ -45,3 +47,12 @@ export const rsnFromElement = (el: Element | null) => {
const { innerHTML } = el || {}; const { innerHTML } = el || {};
return innerHTML?.replace(/\uFFFD/g, ' ') || ''; return innerHTML?.replace(/\uFFFD/g, ' ') || '';
}; };
export const httpGet = (url: string) => {
return axios.get(url, {
headers: {
// without User-Agent header requests may be rejected by DDoS protection mechanism
'User-Agent': ua.firefox(80)
}
});
};

3415
yarn.lock

File diff suppressed because it is too large Load Diff