minehut-ts
Version:
Incomplete minehut library
869 lines (868 loc) • 30.6 kB
JavaScript
"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);
}));
});
}