UNPKG

@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
"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