UNPKG

pw-js-api

Version:

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

338 lines 28.4 kB
import { __awaiter } from "tslib"; import PWGameClient from "../game/PWGameClient.js"; import { Endpoint } from "../util/Constants.js"; import { mergeObjects, queryToString } from "../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: Endpoint.Api, GameHTTP: Endpoint.GameHTTP, GameWS: Endpoint.GameWS, } }; if (typeof password === "object") { this.options = mergeObjects(this.options, password); password = undefined; } else if (options) this.options = 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 !== 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 !== 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(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 = Endpoint.GameHTTP) { return this.request(`${EndpointURL}/listroomtypes`, undefined, undefined, EndpointURL !== 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(`${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 __awaiter(this, arguments, void 0, function* (skipCache = false, toObject, EndpointURL = 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 !== 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}${queryToString(query)}`, undefined, true, this.options.endpoints.Api !== 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 = 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}${queryToString(query)}`, undefined, undefined, EndpointURL !== 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 = 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}${queryToString(query)}`, undefined, undefined, EndpointURL !== 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 = 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}${queryToString(query)}`, undefined, undefined, EndpointURL !== Endpoint.Api); } /** * Returns the lobby result. */ getVisibleWorlds() { return PWApiClient.getVisibleWorlds(this.options.endpoints.GameHTTP); } /** * Returns the lobby result. */ static getVisibleWorlds(EndpointURL = 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 !== 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 = Endpoint.Api) { if (toURL) return `${EndpointURL}/api/files/rhrbt6wqhc4s0cp/${world.id}/${world.minimap}`; return this.request(this.getMinimap(world, true, EndpointURL), undefined, undefined, EndpointURL !== 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(Endpoint.Api) || url.startsWith(Endpoint.GameHTTP) || url.startsWith(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 = []; export default PWApiClient; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUFdBcGlDbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvYXBpL1BXQXBpQ2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLFlBQVksTUFBTSx5QkFBeUIsQ0FBQztBQUduRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU5RDs7R0FFRztBQUNILE1BQXFCLFdBQVc7SUF5QzVCLFlBQVksS0FBYSxFQUFFLFFBQW9DLEVBQUUsT0FBMEI7UUFuQzNGOztXQUVHO1FBQ0ssWUFBTyxHQUFHO1lBQ2QsS0FBSyxFQUFFLEVBQUU7WUFDVCxRQUFRLEVBQUUsRUFBRTtTQUNmLENBQUE7UUFJRCxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBMEJiLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDWCxTQUFTLEVBQUU7Z0JBQ1AsR0FBRyxFQUFFLFFBQVEsQ0FBQyxHQUFHO2dCQUNqQixRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVE7Z0JBQzNCLE1BQU0sRUFBRSxRQUFRLENBQUMsTUFBTTthQUMxQjtTQUNKLENBQUE7UUFFRCxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxPQUFPLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDcEQsUUFBUSxHQUFHLFNBQVMsQ0FBQztRQUN6QixDQUFDO2FBQU0sSUFBSSxPQUFPO1lBQUUsSUFBSSxDQUFDLE9BQU8sR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUV2RSxJQUFJLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztZQUNuQixJQUFJLENBQUMsUUFBUSxHQUFH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