Skip to content
This repository has been archived by the owner on Dec 11, 2024. It is now read-only.

Commit

Permalink
Ratelimits
Browse files Browse the repository at this point in the history
  • Loading branch information
Kathund committed Aug 20, 2024
1 parent e9d9880 commit 69be5bd
Show file tree
Hide file tree
Showing 8 changed files with 475 additions and 270 deletions.
2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
"aaron-bond.better-comments",
"vitest.explorer"
]
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# Todo List for Reborn-ts

- [ ] Add Ratelimiting back
- [x] Add Ratelimiting back
- [ ] Allow for queue mode. For when key is limited
- [ ] Change how raw option works
- [ ] Rewrtie SkyblockUtils
Expand Down
668 changes: 409 additions & 259 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions src/Client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import CacheHandler from './Private/CacheHandler';
import { ClientOptions } from './typings/Client';
import RateLimit from './Private/RateLimit';
import Requests from './Private/Requests';
import Updater from './Private/Updater';
import Errors from './Errors';
Expand All @@ -13,20 +14,23 @@ class Client {
declare cacheHandler: CacheHandler;
declare updater: Updater;
declare errors: Errors;
declare rateLimit: RateLimit;

readonly key: string;

declare interval: NodeJS.Timeout;

constructor(key: string, options?: ClientOptions) {
this.key = key;
if (!this.key.length) throw new Error(this.errors.NO_API_KEY);

this.options = this.parasOptions(options);
this.requests = new Requests(this);
this.cacheHandler = new CacheHandler(this);
this.updater = new Updater(this);
this.errors = new Errors();

this.key = key;
if (!this.key.length) throw new Error(this.errors.NO_API_KEY);
this.rateLimit = new RateLimit(this);
if ('NONE' !== this.options.rateLimit) this.rateLimit.initialize();

for (const func in API) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand All @@ -41,7 +45,12 @@ class Client {
// eslint-disable-next-line no-console
console.warn(this.errors.MULTIPLE_INSTANCES);
const found = clients.find((x) => x.key === key);
if (found) return found;
if (found) {
this.destroy();
Object.assign(this, found);
return;
}
return;
}

if (this.options.checkForUpdates) {
Expand All @@ -60,6 +69,7 @@ class Client {
const clientIndex = clients.findIndex((client) => client.key === this.key);
if (-1 !== clientIndex) clients.splice(clientIndex, 1);
if (this.interval) clearInterval(this.interval);
if (this.rateLimit.interval) clearInterval(this.rateLimit.interval);
}

private parasOptions(options?: ClientOptions): ClientOptions {
Expand Down
2 changes: 2 additions & 0 deletions src/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class Errors {
NO_SKYBLOCK_PROFILES: string = '[Hypixel-API-Reborn] The player has no skyblock profiles.';
BAD_AUCTION_FILTER: string =
'[Hypixel-API-Reborn] Unexpected filter for Client#getSkyblockAuction. Expected one of "PLAYER", "AUCTION", "PROFILE", but got something else.';
RATE_LIMIT_INIT_ERROR: string =
'[hypixel-api-reborn] An error happened whilst initializing rate limit. We strongly recommend restarting the code as this can lead to desynchronization.';
}

export default Errors;
45 changes: 45 additions & 0 deletions src/Private/RateLimit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Client from '../Client';

class RateLimit {
readonly client: Client;
declare requests: number;
declare limit: number;
declare initialized: boolean;
declare interval: NodeJS.Timeout;
constructor(client: Client) {
this.client = client;

this.requests = 0;
this.limit = 0;
this.initialized = false;

this.interval = setInterval(() => this.reset(), 300000);
}

async sync() {
const { _headers: headers } = await this.client.requests.request('/boosters', { raw: true });
if (
headers?.['ratelimit-limit'] === undefined ||
headers?.['ratelimit-remaining'] === undefined ||
headers?.['ratelimit-reset'] === undefined
) {
throw new Error(this.client.errors.RATE_LIMIT_INIT_ERROR);
}
this.requests = headers['ratelimit-limit'] - headers['ratelimit-remaining'];
this.limit = Number(headers['ratelimit-limit']);
}

reset() {
if (false === this.initialized) return;
this.requests = 0;
}

async initialize() {
if (this.initialized) return;
if ('AUTO' !== this.client.options.rateLimit) return;
await this.sync();
this.initialized = true;
}
}

export default RateLimit;
1 change: 1 addition & 0 deletions src/Private/Requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Requests {
if (!parsedRes.success && !endpoint.startsWith('/housing')) {
throw new Error(this.client.errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.statusText));
}
this.client.rateLimit.requests++;

// eslint-disable-next-line no-underscore-dangle
parsedRes._headers = res.headers;
Expand Down
7 changes: 2 additions & 5 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,5 @@
"target": "ES2022",
"strict": true
},
"include": [
"src",
"API"
],
}
"include": ["src", "API"]
}

0 comments on commit 69be5bd

Please sign in to comment.