@zikeji/hypixel
Version:
With IntelliSense support & test coverage, this is an unopinionated async/await API wrapper for Hypixel's Public API. It is developed in TypeScript complete with documentation, typed interfaces for all API responses, built-in rate-limit handling, flexible
316 lines • 12.2 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Client = void 0;
const events_1 = require("events");
const url_1 = require("url");
const GenericHTTPError_1 = require("./errors/GenericHTTPError");
const InvalidKeyError_1 = require("./errors/InvalidKeyError");
const guild_1 = require("./methods/guild");
const player_1 = require("./methods/player");
const recentGames_1 = require("./methods/recentGames");
const resources_1 = require("./methods/resources");
const skyblock_1 = require("./methods/skyblock");
const status_1 = require("./methods/status");
const Queue_1 = require("./util/Queue");
const Request_1 = require("./util/Request");
const ResultObject_1 = require("./util/ResultObject");
const housing_1 = require("./methods/housing");
/**
* The main API client, instantiate it with your API key.
* @example
* ```typescript
* import { Client as HypixelClient } from "@zikeji/hypixel";
* const client = new HypixelClient("legit-api-key-heye");
* ```
* @category Client
*/
class Client {
/**
* Create a new instance of the API client.
* @param key Your Hypixel API key.
* @param options Any options and customizations being applied.
*/
constructor(key, options) {
var _a, _b, _c;
/** @internal */
this.emitter = new events_1.EventEmitter();
/** @internal */
this.queue = new Queue_1.Queue();
/** @internal */
this.rateLimit = {
remaining: -1,
reset: -1,
limit: -1,
};
/**
* Returns the guild by the requested ID if found.
* @example
* ```typescript
* const guild = await client.guild.id("553490650cf26f12ae5bac8f");
* ```
* @category API
*/
this.guild = new guild_1.Guild(this);
/**
* Return's housing data, such as active public houses.
* @example
* ```typescript
* const housingData = await client.housing.active();
* console.log(housingData);
* ```
* @category API
*/
this.housing = new housing_1.Housing(this);
/**
* Returns a player's data, such as game stats.
* @example
* ```typescript
* const player = await client.player.uuid("20934ef9488c465180a78f861586b4cf");
* console.log(player);
* ```
* @category API
*/
this.player = new player_1.Player(this);
/**
* Returns recent games of a player. A maximum of 100 games are returned and recent games are only stored for up to 3 days at this time.
* @example
* ```typescript
* const response = await client.recentgames.uuid("20934ef9488c465180a78f861586b4cf");
* console.log(response);
* ```
* @category API
*/
this.recentgames = new recentGames_1.Recentgames(this);
/**
* Relatively static Hypixel resources that don't change often at all.
* @category API
*/
this.resources = new resources_1.Resources(this);
/**
* All SkyBlock related endpoints.
* @category API
*/
this.skyblock = new skyblock_1.SkyBlock(this);
/**
* Returns online status information for given player, including game, mode and map when available.
* @example
* ```typescript
* const response = await client.status.uuid("20934ef9488c465180a78f861586b4cf");
* console.log(response);
* ```
* @category API
*/
this.status = new status_1.Status(this);
if (!key || typeof key !== "string") {
throw new InvalidKeyError_1.InvalidKeyError("Invalid API key");
}
this.apiKey = key;
this.retries = (_a = options === null || options === void 0 ? void 0 : options.retries) !== null && _a !== void 0 ? _a : 3;
this.timeout = (_b = options === null || options === void 0 ? void 0 : options.timeout) !== null && _b !== void 0 ? _b : 10000;
this.userAgent = (_c = options === null || options === void 0 ? void 0 : options.userAgent) !== null && _c !== void 0 ? _c : "@zikeji/hypixel";
this.cache = options === null || options === void 0 ? void 0 : options.cache;
}
on(event, listener) {
this.emitter.on(event, listener);
return this;
}
once(event, listener) {
this.emitter.once(event, listener);
return this;
}
off(event, listener) {
this.emitter.off(event, listener);
return this;
}
/**
* Returns list of boosters.
* @example
* ```typescript
* const boosters = await client.boosters();
* console.log(boosters);
* ```
* @category API
*/
boosters() {
return __awaiter(this, void 0, void 0, function* () {
return (0, ResultObject_1.getResultObject)(yield this.call("boosters"), [
"success",
]);
});
}
/**
* Returns the current player count along with the player count of each public game + mode on the server.
* @example
* ```typescript
* const response = await client.counts();
* console.log(response);
* ```
* @category API
*/
counts() {
return __awaiter(this, void 0, void 0, function* () {
return (0, ResultObject_1.getResultObject)(yield this.call("counts"), [
"success",
]);
});
}
/**
* Returns a list of the official leaderboards and their current standings for games on the network.
* @example
* ```typescript
* const leaderboards = await client.leaderboards();
* console.log(leaderboards);
* ```
* @category API
*/
leaderboards() {
return __awaiter(this, void 0, void 0, function* () {
return (0, ResultObject_1.getResultObject)(yield this.call("leaderboards"), ["leaderboards"]);
});
}
/**
* Returns some statistics about punishments.
* @example
* ```typescript
* const response = await client.punishmentstats();
* console.log(response);
* ```
* @category API
*/
punishmentstats() {
return __awaiter(this, void 0, void 0, function* () {
return (0, ResultObject_1.getResultObject)(yield this.call("punishmentstats"), ["success"]);
});
}
/**
* The raw query method used by this library. You may use this if you need to use an undocumented method with this library.
*
* @category Custom
* @param path The path on the method you want to query.
* @param parameters Any search parameters you want to use.
* @typeParam T As all of Hypixel's API methods return a basic `{ success: boolean; cause?: string; }`, this type parameter (if using Typescript) extends an interface including those.
* @example
* Getting the ID of a guild using the [findGuild](https://github.com/HypixelDev/PublicAPI/blob/master/Documentation/methods/findGuild.md) method.
* ```javascript
* const response = await client.call("findGuild", { byName: "Mini Squid" });
* console.log(response);
* // { success: true, guild: '553490650cf26f12ae5bac8f' }
* ```
*/
call(path_1) {
return __awaiter(this, arguments, void 0, function* (path, parameters = {}) {
if (!this.cache) {
return this.executeActionableCall(this.createActionableCall(path, parameters));
}
const key = `${path.split("/").join(":")}${Object.values(parameters).length === 0
? ""
: `:${Object.values(parameters).map((v) => v.toLowerCase().replace(/-/g, ""))}`}`;
const cachedResponse = yield this.cache.get(key);
if (cachedResponse) {
cachedResponse.cached = true;
return cachedResponse;
}
const response = yield this.executeActionableCall(this.createActionableCall(path, parameters));
yield this.cache.set(key, response);
return response;
});
}
/** @internal */
executeActionableCall(call) {
return __awaiter(this, void 0, void 0, function* () {
yield this.queue.wait();
if (this.rateLimit.remaining === 0) {
const timeout = this.rateLimit.reset * 1000;
this.emitter.emit("limited", this.rateLimit.limit, new Date(Date.now() + timeout));
yield new Promise((resolve) => {
setTimeout(resolve, timeout);
});
this.emitter.emit("reset");
}
let response;
try {
response = (yield call.execute());
}
catch (error) {
/* istanbul ignore else */
if (error instanceof InvalidKeyError_1.InvalidKeyError ||
error instanceof GenericHTTPError_1.GenericHTTPError ||
/* istanbul ignore next */ call.retries === this.retries) {
throw error;
}
/* istanbul ignore next */
call.retries += 1;
/* istanbul ignore next */
return this.executeActionableCall(call);
}
finally {
this.queue.free();
}
if (typeof response === "object" && !call.noRateLimit) {
response.ratelimit = JSON.parse(JSON.stringify(this.rateLimit));
}
return response;
});
}
/** @internal */
createActionableCall(path,
/* istanbul ignore next */
parameters = {}) {
let noRateLimit = false;
let includeApiKey = true;
// No API key or rate limiting is needed on resources, skyblock/auctions, or skyblock/bazaar
if (path.startsWith("resources") ||
path === "skyblock/auctions" ||
path === "skyblock/auctions_ended" ||
path === "skyblock/bazaar") {
noRateLimit = true;
includeApiKey = false;
}
return {
execute: this.callMethod.bind(this, path, parameters, noRateLimit, includeApiKey),
retries: 0,
noRateLimit,
includeApiKey,
};
}
/** @internal */
callMethod(path, parameters, noRateLimit, includeApiKey) {
const url = new url_1.URL(`${Client.endpoint}/${path}`);
Object.keys(parameters).forEach((param) => {
url.searchParams.set(param, parameters[param]);
});
if (includeApiKey) {
url.searchParams.set("key", this.apiKey);
}
return (0, Request_1.request)({
url: url.toString(),
userAgent: this.userAgent,
timeout: this.timeout,
noRateLimit,
getRateLimitHeaders: this.getRateLimitHeaders.bind(this),
});
}
/** @internal */
getRateLimitHeaders(headers) {
Object.keys(this.rateLimit).forEach((key) => {
const headerKey = `ratelimit-${key}`;
if (headerKey in headers) {
this.rateLimit[key] = parseInt(headers[headerKey], 10);
}
});
}
}
exports.Client = Client;
/** @internal */
Client.endpoint = new url_1.URL(`https://api.hypixel.net/v2`);
exports.default = Client;
//# sourceMappingURL=Client.js.map