UNPKG

minehut-ts

Version:
869 lines (868 loc) 30.6 kB
"use strict"; //Originally designed for https://github.com/MrEnxo/minetron-react var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.minetronLogin = exports.harLogin = exports.getPublicPlugins = exports.Server = exports.fetchServers = exports.uploadFile = exports.listDir = exports.FileInfo = exports.fetchServer = exports.readFile = exports.getAllServers = exports.createServer = exports._altLogin = exports.getUserInfo = void 0; //URL's must not have / at the end. const loginURL = 'https://authentication-service-prod.superleague.com/v1/user/login/ghost'; const minetronURL = 'http://minetron.ml'; const apiURL = "https://api.minehut.com"; const node_fetch_1 = __importDefault(require("node-fetch")); const uuid = __importStar(require("uuid")); let loginInfo; /** * Gets user info * * @param userId Current user id */ async function getUserInfo(userId) { return new Promise((resolve, reject) => { fetchAuthorized('/v2/user/' + userId).then((user) => { resolve({ __v: user.user.__v, birthday: user.user.birthday, createdAt: new Date(user.user.created_at), credits: user.user.credits, email: user.user.email, emailSentAt: user.user.email_sent_at, emailVerified: user.user.email_verified, flags: user.user.flags, email_code: user.user.email_code, id: user.user._id, lastLogin: new Date(user.user.last_login), lastPasswordChange: new Date(user.user.last_password_change), maxServers: user.user.max_servers, minecraftLastLinkTime: new Date(user.user.minecraft_last_link_time), minecraftLinkCode: user.user.minecraft_link_code, minecraftName: user.user.minecraft_name, minecraftUuid: user.user.minecraft_uuid, serverOrder: user.user.order_servers, servers: user.user.servers, slgProfileId: user.user.slg_profile_id, slgShadowProfileId: user.user.slg_profile_id }); }); }); } exports.getUserInfo = getUserInfo; /** * This method is intended to be used when you have another login system implemented. * Just updates internal variables then returns the argument. * * @param {LoginInfo} login Login information * @returns The login argument. */ function _altLogin(login) { loginInfo = login; return login; } exports._altLogin = _altLogin; /** * @param {string} name Name of the server you want to create. * * @returns {Promise<Server>} */ async function createServer(name) { return new Promise((resolve, reject) => { fetchAuthorized('/servers/create', 'POST', {}, { name: name, platform: 'java' }).then(res => { resolve(new Server(res.server)); }); }); } exports.createServer = createServer; /** * Get All Servers * * @returns {Promise<Array<Object>>} Array of servers */ async function getAllServers() { return new Promise((resolve, reject) => { node_fetch_1.default(apiURL + '/servers_all').then(res => res.json().then(servers => { servers.forEach((server, index, array) => { server.serverPlan = server.server_plan; delete server.server_plan; array[index] = server; }); resolve(servers); })); }); } exports.getAllServers = getAllServers; /** * Read files from minehut. * * @param {Server|string} server Server id or Server object * @param {string} path File path you want to read. * * @returns {Promise<string>} */ async function readFile(server, path) { return new Promise((resolve, reject) => { fetchAuthorized('/file/' + getServerId(server) + '/read/' + path).then(res => { if (res.error) { reject(res.error); } else { resolve(res.content); } }); }); } exports.readFile = readFile; function getServerId(server) { if (typeof server === "string") { return server; } else { return server.id; } } /** * Same as fetchServers() but returns a single server instead of an array. * * @param {string} serverName Name of the server to fetch. * * @returns {Promise<Server>} */ async function fetchServer(serverName) { return new Promise((resolve, reject) => { fetchServers().then(servers => { let selected; servers.forEach(server => { if (serverName === server.name) { selected = server; } }); if (selected) { resolve(selected); } else { reject("The server could not be found."); } }); }); } exports.fetchServer = fetchServer; class FileInfo { constructor(file, server, path) { this.name = file.name; this.directory = file.directory; this.path = path; if (file.directory) { this.blocked = false; } else { this.blocked = file.blocked; } if (typeof server === "string") { fetchServer(server).then(server => { this.server = server; }); } else { this.server = server; } } async fetch() { return new Promise((resolve, reject) => { readFile(this.server, this.path + "/" + this.name).then(res => { this.content = res; resolve(res); }); }); } async delete() { return new Promise(async (resolve, reject) => { resolve(await fetchAuthorized("/file/" + this.server.id + "/delete/" + this.path + "/" + this.name, "POST")); }); } } exports.FileInfo = FileInfo; /** * Lists the given directory. * * @param {Server|string} server The server that the directory will be listed from. Can be Server object or server id as a string. * @param {string} path Directory that will be listed. (root is /) * * @returns {Promise<File[]>} */ async function listDir(server, path) { return new Promise((resolve, reject) => { fetchAuthorized('/file/' + getServerId(server) + '/list/' + path).then(res => { if (res.error) { reject(res.error); } else { let files = []; res.files.forEach((file) => { files.push(new FileInfo(file, server, path)); }); resolve(files); } }); }); } exports.listDir = listDir; /** * Uploads your file to minehut * * @param {Server|string} The ServerID * @param {string} the filename * @param {object} File in binary * * @returns {Promise<void>} */ async function uploadFile(server, filename, file) { return new Promise((resolve, reject) => { fetchAuthorized(`/file/upload/${getServerId(server)}//${filename}`, "POST", {}, { file }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } exports.uploadFile = uploadFile; /** * Fetches all servers available to the currently logged in user. * * @returns {Promise<Array<Server>>} */ async function fetchServers() { return new Promise((resolve, reject) => { if (!loginInfo) { reject("You are not logged in."); return; } fetchAuthorized('/servers/' + loginInfo.userId + '/all_data').then(res => { if (res.expired) { reject(); } else { let servers = []; res.forEach((server) => { servers.push(new Server(server)); }); resolve(servers); } }); }); } exports.fetchServers = fetchServers; class Server { constructor(server) { this.id = server._id; this.activePlugins = server.active_plugins; this.activeServerPlan = server.active_server_plan; this.activeServerPlanDetails = server.active_server_plan_detials; this.backupSlots = server.backup_slots; this.categories = server.categories; this.created = new Date(server.creation); this.creditsPerDay = server.credits_per_day; this.exited = server.exited; this.hibernationPrepStartTime = server.hibernation_prep_start_time; this.installedContentPacks = server.installed_content_packs; this.lastOnline = new Date(server.last_online); this.maxPlayers = server.max_players; this.maxRam = server.max_ram; this.metrics = server.metrics; this.motd = server.motd; this.name = server.name; this.lowerName = server.name_lower; this.online = server.online; this.owner = server.owner; this.platform = server.platform; this.playerCount = server.player_count; this.players = server.players; this.port = server.port; this.purchasedIcons = server.purchased_icons; this.purchasedPlugins = server.purchased_plugins; this.serverIp = server.server_ip; this.serverPlan = server.server_plan; this.serverPlanDetails = server.server_plan_details; this.serverPort = server.server_port; this.serverProperites = server.server_properties; this.serviceOnline = server.service_online; this.shutdownReason = server.shutdown_reason; this.shutdownScheduled = server.shutdown_scheduled; this.startedAt = server.started_at; this.starting = server.starting; this.status = server.status; this.stoppedAt = server.stopped_at; this.stopping = server.stopping; this.storageNode = server.storage_node; this.suspended = server.suspended; this.timeNoPlayers = server.time_no_players; this.visiblity = server.visibility; } /** * Starts the server. * * @returns Promise<void> */ async start() { return new Promise((resolve, reject) => { if (this.serviceOnline) { startServer(this.id).then(resolve).catch(reject); } else { startService(this.id).then(resolve).catch(reject); } }); } /** * Hibernate the server. * * @returns Promise<void> */ async hibernate() { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/destroy_service').then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Stop the server. * * @returns Promise<void> */ async stop() { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/shutdown').then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Restart the server. * @returns Promise<void> */ async restart() { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/restart').then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Change the visibility of the server. * * @param {boolean} state Whether the server is visible or not. * @returns Promise<void> */ async changeVisibility(state) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/visibility', 'POST', {}, { visiblity: state }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Send console command to server. * * @param {string} command Console command that will be executed. * @returns Promise<void> */ async sendServerCommand(command) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/send_command', 'POST', {}, { command: command }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Change the name of the server. * * @param {string} name The new name of the server. * @returns Promise<void> */ async changeName(name) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/change_name', 'POST', {}, { name: name }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Change server.properties * * @param {string} field Field to change. * @param {string} value The value it should be. * @returns Promise */ async changeServerProperty(field, value) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/visibility', 'POST', {}, { field: field, value: value }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Install a plugin to the server. * * @param {string} plugin Plugin id. * @returns Promise<void> * @deprecated Plugin installing through the Server object is deprecated. Install through a Plugin object instead. */ async installPlugin(plugin) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/install_plugin', 'POST', {}, { plugin }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Save the world of the server. * @returns Promise<void> */ async saveWorld() { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/save', 'POST').then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * Reset the world of the server. * @returns Promise<void> */ async resetWorld() { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + this.id + '/reset_world', 'POST').then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } /** * List available backups. * * @returns Promise<{backups: Array<Backup>, rollingBackup: RollingBackup}> */ async listBackups() { return new Promise((resolve, reject) => { fetchAuthorized('/v1/server/' + this.id + '/backups').then(res => { let ret = { backups: [], rollingBackup: new RollingBackup(res.rolling_backup) }; res.backups.forEach((backup) => { ret.backups.push(new Backup(backup)); }); resolve(ret); }); }); } // I don't know why this is commented out but there should be a reason? /*async createBackup(): Promise<BackupResponse> { return new Promise((resolve, reject) => { fetchAuthorized('/v1/server/' + this.id + '/backup/create', 'POST', {}, {backup_id: uuid.v4()}).then(res => { resolve(res) }) }) }*/ async getPlugins() { return new Promise(async (resolve, reject) => { resolve((await getPublicPlugins()).filter(value => this.activePlugins.includes(value.id))); }); } async createFile(path, content = "") { return new Promise(async (resolve, reject) => { resolve(new FileInfo(await fetchAuthorized("/file/" + this.id + "/edit/" + path, "POST", {}, { content }), this, path)); }); } } exports.Server = Server; class Backup { constructor(backup) { this.id = backup._id; this.content = backup.content; this.dataRemoved = backup.data_removed; this.deleted = backup.deleted; this.description = backup.description; this.disabled = backup.disabled; this.lastBackupTime = new Date(backup.last_backup_time); this.pending = backup.pending; this.serverId = backup.server_id; this.serverModelSnapshot = { id: backup.server_model_snapshot._id, activeIcon: backup.server_model_snapshot.active_icon, activePlugins: backup.server_model_snapshot.active_plugins, backupSlots: backup.server_model_snapshot.backup_slots, categories: backup.server_model_snapshot.categories, creation: new Date(backup.server_model_snapshot.creation), creditsPerDay: backup.server_model_snapshot.credits_per_day, installedContentPacks: backup.server_model_snapshot.installed_content_packs, key: backup.server_model_snapshot.key, lastOnline: new Date(backup.server_model_snapshot.last_online), motd: backup.server_model_snapshot.motd, name: backup.server_model_snapshot.name, lowerName: backup.server_model_snapshot.name_lower, owner: backup.server_model_snapshot.owner, platform: 'java', port: backup.server_model_snapshot.port, purchasedIcons: backup.server_model_snapshot.purchased_icons, purchasedPlugins: backup.server_model_snapshot.purchased_plugins, serverPlan: backup.server_model_snapshot.server_plan, serverProperites: { allowFlight: backup.server_model_snapshot.server_properties.allow_flight, allowNether: backup.server_model_snapshot.server_properties.allow_nether, announcePlayerAchievements: backup.server_model_snapshot.server_properties.announce_player_achievements, difficulty: backup.server_model_snapshot.server_properties.difficulty, enableCommandBlocks: backup.server_model_snapshot.server_properties.enable_command_block, forceGamemode: backup.server_model_snapshot.server_properties.force_gamemode, gamemode: backup.server_model_snapshot.server_properties.gamemode, generateStructures: backup.server_model_snapshot.server_properties.generate_structures, generatorSettings: backup.server_model_snapshot.server_properties.generator_settings, hardcore: backup.server_model_snapshot.server_properties.hardcore, levelName: backup.server_model_snapshot.server_properties.level_name, levelSeed: backup.server_model_snapshot.server_properties.level_seed, levelType: backup.server_model_snapshot.server_properties.level_type, maxPlayers: backup.server_model_snapshot.server_properties.max_players, pvp: backup.server_model_snapshot.server_properties.pvp, resourcePack: backup.server_model_snapshot.server_properties.resource_pack, resourcePackSha1: backup.server_model_snapshot.server_properties.resource_pack_sha1, spawnAnimals: backup.server_model_snapshot.server_properties.spawn_animals, spawnMobs: backup.server_model_snapshot.server_properties.spawn_mobs, spawnProtection: backup.server_model_snapshot.server_properties.spawn_protection, viewDistance: backup.server_model_snapshot.server_properties.view_distance }, storageNode: backup.server_model_snapshot.storage_node, suspended: backup.server_model_snapshot.suspended, visibility: backup.server_model_snapshot.visibility }; } /** * Restore this backup. * * @returns Promise */ async restore() { return new Promise((resolve, reject) => { fetchAuthorized('/v1/server/' + this.serverId + '/backup/apply', 'POST', {}, { backup_id: this.id }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } } class RollingBackup { constructor(backup) { this.id = backup._id; this.etag = backup.etag; this.lastBackupTime = backup.last_backup_time; this.lastModified = backup.lastModified; this.metaData = backup.metaData; } } async function startServer(id) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + id + '/start', 'POST').then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(res); } }); }); } async function startService(id) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + id + '/start_service', 'POST').then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { if (res.error) { reject(res.error); } else { reject(res); } } }); }); } class Plugin { constructor(plugin) { this.id = plugin._id; this.created = new Date(plugin.created); this.credits = plugin.credits; this.description = plugin.desc; this.extendedDescription = plugin.desc_extended; this.disabled = plugin.disabled; this.fileName = plugin.file_name; this.htmlExtendedDesc = plugin.html_desc_extended; this.lastUpdated = plugin.last_updated; this.name = plugin.name; this.version = plugin.version; } /** * Install this plugin to a server. * @param {Server|string} server Server to install this plugin to. * @returns Promise<void> */ async install(server) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + getServerId(server) + '/install_plugin', 'POST', {}, { plugin: this.id }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(); } }); }); } /** * Uninstall this plugin from a server. * @param {Server|string} server Server to uninstall the plugin from. * @returns Promise<void> */ async uninstall(server) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + getServerId(server) + '/remove_plugin', 'POST', {}, { plugin: this.id }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(); } }); }); } /** * Reset plugin configurations. * * @param {Server|string} server The server the plugin data will be deleted from. * @returns Promise<void> */ async resetPlugin(server) { return new Promise((resolve, reject) => { fetchAuthorized('/server/' + getServerId(server) + '/remove_plugin_data', 'POST', {}, { plugin: this.id }).then(res => { if (JSON.stringify(res) === "{}") { resolve(); } else { reject(); } }); }); } isInstalled(server) { return server.activePlugins.includes(this.id); } } async function fetchAuthorized(endpoint, method, headers, body) { let options = {}; if (method) { options.method = method; } if (headers && JSON.stringify(headers) !== "{}") { options.headers = headers; } else { options.headers = { "Content-Type": "application/json" }; } options.headers.authorization = loginInfo.authorization; options.headers["x-session-id"] = loginInfo.xSessionId; if (body) { options.body = JSON.stringify(body); } return new Promise((resolve, reject) => { node_fetch_1.default(apiURL + endpoint, options).then(res => res.json().then(resolve).catch(reject)); }); } /** * Fetch all plugins publicly available from Minehut * * @returns {Promise<Array<Plugin>>} Resolves to array of Plugin objects. */ async function getPublicPlugins() { return new Promise((resolve, reject) => { node_fetch_1.default(apiURL + '/plugins_public').then(res => res.json().then(res => { let plugins = []; res.all.forEach((plugin) => { plugins.push(new Plugin(plugin)); }); resolve(plugins); })); }); } exports.getPublicPlugins = getPublicPlugins; /** * Login with a HAR file. Designed to be used when Minetron is not available. * * @param {string} file The HAR file as a string. * @returns {loginObject} Login object */ async function harLogin(file) { return new Promise((resolve, reject) => { let entries; try { entries = JSON.parse(file).log.entries; } catch (err) { reject(err); return; } let response; entries.forEach(value => { if (value.request.url === loginURL && value.request.method === "POST") { try { response = JSON.parse(value.response.content.text); } catch (err) { console.error("The specified file is corrupted."); return; } } }); ghostLogin(response.slgSessionData.slgUserId, response.slgSessionData.slgSessionId).then(resolve); }); } exports.harLogin = harLogin; /** * @typedef {Object} loginObject * * @property {string} userId Minehut user id * @property {Array<string>} servers Array of server id's * @property {string} authorization Authorization token * @property {string} xSessionId Current session id (minehut) * @property {string} slgSessionId Current session id (superleauge) * @property {string} xSlgUser Superleague user id */ /** * Login with minetron. Recommended form of login. * * @see https://github.com/MrEnxo/minetron-server * @param {string} token Minetron login token. * @returns {loginObject} Login object */ // Nice - Creator Of Minetron: MrEnxo async function minetronLogin(token) { return new Promise((resolve, reject) => { node_fetch_1.default(minetronURL + '/api/loginobject/' + token).then(res => res.json().then(loginobj => { if (loginobj.error) { reject(loginobj.error); return; } loginInfo = { userId: loginobj.minehutSessionData._id, servers: loginobj.minehutSessionData.servers, authorization: loginobj.minehutSessionData.token, xSessionId: loginobj.minehutSessionData.sessionId, slgSessionId: loginobj.slgSessionData.slgSessionId, xSlgUser: loginobj.slgSessionData.slgUserId }; resolve(loginInfo); })); }); } exports.minetronLogin = minetronLogin; async function ghostLogin(xSlgUser, xSlgSession) { return new Promise((resolve, reject) => { node_fetch_1.default(loginURL, { headers: { "x-slg-user": xSlgUser, "x-slg-session": xSlgSession, "Content-Type": "application/json" }, method: 'POST', body: JSON.stringify({ minehutSessionId: uuid.v4(), slgSessionId: xSlgSession }) }).then(res => res.json().then(res => { loginInfo = { userId: res.minehutSessionData._id, servers: res.minehutSessionData.servers, authorization: res.minehutSessionData.token, xSessionId: res.minehutSessionData.sessionId, slgSessionId: res.slgSessionData.slgSessionId, xSlgUser: res.slgSessionData.slgUserId }; resolve(loginInfo); })); }); }