UNPKG

pw-js-api

Version:

A PixelWalker Library, aims to be minimal with support for browsers.

340 lines 29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const PWGameClient_js_1 = tslib_1.__importDefault(require("../game/PWGameClient.js")); const Constants_js_1 = require("../util/Constants.js"); const Misc_js_1 = require("../util/Misc.js"); /** * Note if you want to join a world, use new PWGameClient() then run .init() */ class PWApiClient { constructor(email, password, options) { /** * Account details with email and password, if applicable. */ this.account = { email: "", password: "" }; this.loggedIn = false; this.options = { endpoints: { Api: Constants_js_1.Endpoint.Api, GameHTTP: Constants_js_1.Endpoint.GameHTTP, GameWS: Constants_js_1.Endpoint.GameWS, } }; if (typeof password === "object") { this.options = (0, Misc_js_1.mergeObjects)(this.options, password); password = undefined; } else if (options) this.options = (0, Misc_js_1.mergeObjects)(this.options, options); if (password === undefined) { this.token = email; this.loggedIn = true; return; } this.account.email = email; this.account.password = password; // this.token = token; } authenticate(email, password) { if (email === undefined) { if (this.account.email.length === 0 || this.account.password.length === 0) throw Error("No email/password given."); email = this.account.email; password = this.account.password; } return this.request(`${this.options.endpoints.Api}/api/collections/users/auth-with-password`, { identity: email, password }, undefined, this.options.endpoints.Api !== Constants_js_1.Endpoint.Api).then(res => { if ("token" in res) { this.token = res.token; this.loggedIn = true; } return res; }); //.then(console.log); } /** * Internal. */ getJoinKey(roomType, roomId) { return this.request(`${this.options.endpoints.Api}/api/joinkey/${roomType}/${roomId}`, undefined, true, this.options.endpoints.Api !== Constants_js_1.Endpoint.Api); } /** * This route is available to take if you chose to create an API client to then join a world, in which case this returns the Game Client instance. * * Make sure the API client is already authenticated before calling this. * * The 3rd parameter is for if you wish to customise the reconnectability of the game client. */ joinWorld(roomId, obj) { const game = new PWGameClient_js_1.default(this, obj === null || obj === void 0 ? void 0 : obj.gameSettings); return game.joinWorld(roomId, obj === null || obj === void 0 ? void 0 : obj.joinData); } // I feel like this is cursed. /** * This will be an empty array if getRoomTypes has never been used successfully at least once. */ get roomTypes() { return PWApiClient.roomTypes; } /** * Non-authenticated. This will refresh the room types each time, so make sure to check if roomTypes is available. */ getRoomTypes() { return PWApiClient.getRoomTypes(this.options.endpoints.GameHTTP); } /** * Non-authenticated. This will refresh the room types each time, so make sure to check if roomTypes is available. */ static getRoomTypes(EndpointURL = Constants_js_1.Endpoint.GameHTTP) { return this.request(`${EndpointURL}/listroomtypes`, undefined, undefined, EndpointURL !== Constants_js_1.Endpoint.GameHTTP) .then(res => { PWApiClient.roomTypes = res; return this.getListBlocks(true); }) .then(() => { return PWApiClient.roomTypes; }); } /** * Non-authenticated. Returns the mappings from the game API. * * Note: This library also exports "BlockNames" which is an enum containing the block names along with their respective id. * * @deprecated Use getListBlocks() */ getMappings() { return PWApiClient.getMappings(); } /** * Non-authenticated. Returns the mappings from the game API. * * Note: This library also exports "BlockNames" which is an enum containing the block names along with their respective id. * * @deprecated Use getListBlocks() */ static getMappings() { return this.request(`${Constants_js_1.Endpoint.GameHTTP}/mappings`); } getListBlocks(skipCache = false, toObject) { // Yes, this actually gets typescript compiler to stop moaning if (toObject) return PWApiClient.getListBlocks(skipCache, toObject, this.options.endpoints.GameHTTP); return PWApiClient.getListBlocks(skipCache, toObject, this.options.endpoints.GameHTTP); } static getListBlocks() { return tslib_1.__awaiter(this, arguments, void 0, function* (skipCache = false, toObject, EndpointURL = Constants_js_1.Endpoint.GameHTTP) { if (!skipCache) { if (this.listBlocks !== undefined && !toObject) return this.listBlocks; if (this.listBlocksObj !== undefined && toObject) return this.listBlocksObj; } return this.request(`${EndpointURL}/listblocks`, undefined, undefined, EndpointURL !== Constants_js_1.Endpoint.GameHTTP) .then(res => { const obj = {}; const arr = []; // PW doesn't sort the returned endpoint data despite data structure means it's perfectly capable for (let i = 0, len = res.length; i < len; i++) { obj[res[i].PaletteId.toUpperCase()] = res[i]; arr[res[i].Id] = res[i]; } this.listBlocksObj = obj; this.listBlocks = arr; if (toObject) return obj; else return arr; }); }); } getOwnedWorlds(page = 1, perPage = 10, query) { if (typeof page === "object") { query = page; page = 1; } return this.request(`${this.options.endpoints.Api}/api/collections/worlds/records?page=${page}&perPage=${perPage}${(0, Misc_js_1.queryToString)(query)}`, undefined, true, this.options.endpoints.Api !== Constants_js_1.Endpoint.Api); } getPlayers(page = 1, perPage = 10, query) { if (typeof page === "object") { query = page; page = 1; } return PWApiClient.getPlayers(page, perPage, query, this.options.endpoints.Api); } static getPlayers(page = 1, perPage = 10, query, EndpointURL = Constants_js_1.Endpoint.Api) { if (typeof page === "object") { if (typeof perPage === "string") { EndpointURL = perPage; perPage = 10; } query = page; page = 1; } return this.request(`${EndpointURL}/api/collections/users/records?page=${page}&perPage=${perPage}${(0, Misc_js_1.queryToString)(query)}`, undefined, undefined, EndpointURL !== Constants_js_1.Endpoint.Api); } getPublicWorlds(page = 1, perPage = 10, query) { if (typeof page === "object") { query = page; page = 1; } return PWApiClient.getPublicWorlds(page, perPage, query, this.options.endpoints.Api); } static getPublicWorlds(page = 1, perPage = 10, query, EndpointURL = Constants_js_1.Endpoint.Api) { if (typeof page === "object") { if (typeof perPage === "string") { EndpointURL = perPage; perPage = 10; } query = page; page = 1; } return this.request(`${EndpointURL}/api/collections/worlds/records?page=${page}&perPage=${perPage}${(0, Misc_js_1.queryToString)(query)}`, undefined, undefined, EndpointURL !== Constants_js_1.Endpoint.Api); } getWootedWorlds(page = 1, perPage = 10, query) { if (typeof page === "object") { query = page; page = 1; } return PWApiClient.getWootedWorlds(page, perPage, query, this.options.endpoints.Api); } static getWootedWorlds(page = 1, perPage = 10, query, EndpointURL = Constants_js_1.Endpoint.Api) { if (typeof page === "object") { if (typeof perPage === "string") { EndpointURL = perPage; perPage = 10; } query = page; page = 1; } return this.request(`${EndpointURL}/api/collections/worlds/records?page=${page}&perPage=${perPage}${(0, Misc_js_1.queryToString)(query)}`, undefined, undefined, EndpointURL !== Constants_js_1.Endpoint.Api); } /** * Returns the lobby result. */ getVisibleWorlds() { return PWApiClient.getVisibleWorlds(this.options.endpoints.GameHTTP); } /** * Returns the lobby result. */ static getVisibleWorlds(EndpointURL = Constants_js_1.Endpoint.GameHTTP) { if (this.roomTypes.length === 0) throw Error("roomTypes is empty - use getRoomTypes first!"); return this.request(`${EndpointURL}/room/list/${this.roomTypes[0]}`, undefined, undefined, EndpointURL !== Constants_js_1.Endpoint.GameHTTP); } /** * Returns the world, if it exists and is public. */ getPublicWorld(id) { return this.getPublicWorlds(1, 1, { filter: { id } }) .then(res => res.items[0]); } /** * Returns the world, if it exists and is public. */ static getPublicWorld(id) { return this.getPublicWorlds(1, 1, { filter: { id } }) .then(res => res.items[0]); } getMinimap(world, toURL = false) { if (toURL) return `${this.options.endpoints.Api}/api/files/rhrbt6wqhc4s0cp/${world.id}/${world.minimap}`; return PWApiClient.getMinimap(world, toURL, this.options.endpoints.Api); } static getMinimap(world, toURL = false, EndpointURL = Constants_js_1.Endpoint.Api) { if (toURL) return `${EndpointURL}/api/files/rhrbt6wqhc4s0cp/${world.id}/${world.minimap}`; return this.request(this.getMinimap(world, true, EndpointURL), undefined, undefined, EndpointURL !== Constants_js_1.Endpoint.Api) .then(res => { if ("message" in res) throw Error("Minimap doesn't exist, the world may be unlisted."); return res; }); } /** * Note that username is cap sensitive, and may require you to use toUppercase */ getPlayerByName(username) { return this.getPlayers(1, 1, { filter: { username } }) .then(res => res.items[0]); } /** * Note that username is cap sensitive, and may require you to use toUppercase */ static getPlayerByName(username) { return this.getPlayers(1, 1, { filter: { username } }) .then(res => res.items[0]); } // This doesn't seem to work so I commented it out, not removing it as there might be an oversight idk // getMessageTypes() { // return this.request<string[]>(`${Endpoint.GameHTTP}/message_types`) // .then(res => res instanceof Uint8Array ? [] : res ?? []); // } /** * IMPORTANT: This will return JSON for any responses that have the content-type of json, anything else will be sent back as ArrayBuffer. * If you're expecting raw bytes, make sure the endpoint is guaranteed to give you that otherwise there isn't a reason. * * This requires the manager to be authenticated, it will error if otherwise. * @param url Requires to be a full URL with endpoint unfortunately. It will throw error if it doesn't match any of the 2 HTTP endpoint URLs. * @param body If this is passed, the request will become a POST. (If you need to send a POST but has no data, just send an empty object). * @param token The API token (not join key), this is if you wish to use authenticated API calls without having to instantise an api client yourself. * @param overrideURL If true, this will skip checking if the URL truly belongs to PW (production wise). */ static request(url, body, token, overrideURL = false) { if (!overrideURL && !(url.startsWith(Constants_js_1.Endpoint.Api) || url.startsWith(Constants_js_1.Endpoint.GameHTTP) || url.startsWith(Constants_js_1.Endpoint.Client + "/atlases/"))) throw Error("URL given does not have the correct endpoint URL, this is for safety."); const headers = { // "user-agent": "PW-TS-API/0.0.1" }; if (typeof token === "string") headers["authorization"] = token; if (typeof body === "object") body = JSON.stringify(body); let method = "GET"; if (typeof body !== "undefined") { headers["content-type"] = "application/json"; method = "POST"; } let status = 0; return fetch(url, { headers, method, body: body }).then(res => { var _a; if (res.status === 403) throw Error("Forbidden access - token invalid or unauthorised."); // else if (res.status !== 200) throw Error("") status = res.status; if ((_a = res.headers.get("content-type")) === null || _a === void 0 ? void 0 : _a.startsWith("application/json")) return res.json(); else return res.arrayBuffer(); }) .then(data => { if (status > 400) throw data; else return data; }); } /** * IMPORTANT: This will return JSON for any responses that have the content-type of json, anything else will be sent back as Uint8array. * If you're expecting raw bytes, make sure the endpoint is guaranteed to give you that otherwise there isn't a reason. * * This requires the manager to be authenticated, it will error if otherwise. * @param url Requires to be a full URL with endpoint unfortunately. It will throw error if it doesn't match any of the 2 HTTP endpoint URLs. * @param body If this is passed, the request will become a POST. (If you need to send a POST but has no data, just send an empty object). * @param isAuthenticated If true, this will send the token as the header. * @param overrideURL If true, this will skip checking if the URL truly belongs to PW (production wise). */ request(url, body, isAuthenticated = false, overrideURL = false) { return PWApiClient.request(url, body, isAuthenticated ? this.token : undefined, overrideURL); } } /** * This will be an empty array if getRoomTypes has never been used successfully at least once. */ PWApiClient.roomTypes = []; exports.default = PWApiClient; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUFdBcGlDbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvYXBpL1BXQXBpQ2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNGQUFtRDtBQUduRCx1REFBZ0Q7QUFDaEQsNkNBQThEO0FBRTlEOztHQUVHO0FBQ0gsTUFBcUIsV0FBVztJQXlDNUIsWUFBWSxLQUFhLEVBQUUsUUFBb0MsRUFBRSxPQUEwQjtRQW5DM0Y7O1dBRUc7UUFDSyxZQUFPLEdBQUc7WUFDZCxLQUFLLEVBQUUsRUFBRTtZQUNULFFBQVEsRUFBRSxFQUFFO1NBQ2YsQ0FBQTtRQUlELGFBQVEsR0FBRyxLQUFLLENBQUM7UUEwQmIsSUFBSSxDQUFDLE9BQU8sR0FBRztZQUNYLFNBQVMsRUFBRTtnQkFDUCxHQUFHLEVBQUUsdUJBQVEsQ0FBQyxHQUFHO2dCQUNqQixRQUFRLEVBQUUsdUJBQVEsQ0FBQyxRQUFRO2dCQUMzQixNQUFNLEVBQUUsdUJBQVEsQ0FBQyxNQUFNO2FBQzFCO1NBQ0osQ0FBQTtRQUVELElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDL0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFBLHNCQUFZLEVBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNwRCxRQUFRLEdBQUcsU0FBUyxDQUFDO1FBQ3pCLENBQUM7YUFBTSxJQUFJLE9BQU87WUFBRSxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUEsc0JBQVksRUFBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXZFLElBQUksUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1lBQ25CLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLE9BQU87UUFDWCxDQUFDO1FBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsS0FBSyxD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