377 lines
14 KiB
JavaScript
377 lines
14 KiB
JavaScript
/** @param {NS} ns */
|
|
export async function main(ns) {
|
|
ns.tprint("This is just a function library, it doesn't do anything.");
|
|
}
|
|
|
|
// Custom color coding.
|
|
const cCyan = "\u001b[36m";
|
|
const cGreen = "\u001b[32m";
|
|
const cRed = "\u001b[31m";
|
|
const cReset = "\u001b[0m";
|
|
|
|
/** @param {NS} ns */
|
|
export function getCracks(ns) {
|
|
let cracks = {};
|
|
if (ns.fileExists("BruteSSH.exe", "home")) {
|
|
cracks["BruteSSH.exe"] = ns.brutessh;
|
|
};
|
|
if (ns.fileExists("FTPCrack.exe", "home")) {
|
|
cracks["FTPCrack.exe"] = ns.ftpcrack;
|
|
};
|
|
if (ns.fileExists("relaySMTP.exe", "home")) {
|
|
cracks["relaySMTP.exe"] = ns.relaysmtp;
|
|
};
|
|
if (ns.fileExists("HTTPWorm.exe", "home")) {
|
|
cracks["HTTPWorm.exe"] = ns.httpworm;
|
|
};
|
|
if (ns.fileExists("SQLInject.exe", "home")) {
|
|
cracks["SQLInject.exe"] = ns.sqlinject;
|
|
};
|
|
return cracks;
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export function scanServerList(ns) {
|
|
const home = "home";
|
|
let serverList = [];
|
|
let unscanned = [];
|
|
|
|
unscanned.push(home);
|
|
while (unscanned.length > 0) {
|
|
let currentServer = unscanned.pop();
|
|
if (!serverList.some(obj => obj["serverName"] === currentServer)) {
|
|
let maxRam = ns.getServerMaxRam(currentServer);
|
|
let minPorts = ns.getServerNumPortsRequired(currentServer);
|
|
let minSecLevel = ns.getServerMinSecurityLevel(currentServer);
|
|
let minHackLevel = ns.getServerRequiredHackingLevel(currentServer);
|
|
let rootAccess = ns.hasRootAccess(currentServer);
|
|
let serverMoney = ns.getServerMaxMoney(currentServer);
|
|
let serverFiles = ns.ls(currentServer);
|
|
let serverStats = ns.getServer(currentServer);
|
|
let serverOrgs = serverStats.organizationName;
|
|
let serverCores = serverStats.cpuCores;
|
|
|
|
serverList.push({
|
|
serverName: currentServer,
|
|
maxRam: maxRam,
|
|
maxMoney: serverMoney,
|
|
minSec: minSecLevel,
|
|
minPorts: minPorts,
|
|
minHackLvl: minHackLevel,
|
|
rootAccess: rootAccess,
|
|
openPorts: 0,
|
|
serverOrgs: serverOrgs,
|
|
serverCores: serverCores,
|
|
serverFiles: serverFiles,
|
|
});
|
|
let neighbours = ns.scan(currentServer);
|
|
for (let i = 0; i < neighbours.length; i++) {
|
|
let neighbour = neighbours[i];
|
|
if (serverList.some(obj => obj["serverName"] === neighbour)) {
|
|
continue
|
|
}
|
|
unscanned.push(neighbour);
|
|
}
|
|
}
|
|
}
|
|
ns.write("serverList.txt", JSON.stringify(serverList), "w");
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export function findBestTarget(ns, maxSec, maxPorts, currentHackLevel, manualTargetOverride) {
|
|
if (!ns.fileExists("serverList.txt", "home")) scanServerList();
|
|
let serverList = JSON.parse(ns.read("serverList.txt"));
|
|
let bestEntry = "";
|
|
if (manualTargetOverride && manualTargetOverride.length > 0) {
|
|
bestEntry = manualTargetOverride;
|
|
} else {
|
|
bestEntry = null;
|
|
let nMaxMoneyPerChance = 0;
|
|
let nBestMoneyPerChance = 0;
|
|
serverList.forEach((entry) => {
|
|
if (entry.minSec <= maxSec && entry.minPorts <= maxPorts && entry.minHackLvl <= currentHackLevel) {
|
|
nMaxMoneyPerChance = (entry.maxMoney * ns.hackAnalyzeChance(entry.serverName)) / entry.minSec;
|
|
if (nMaxMoneyPerChance > nBestMoneyPerChance) {
|
|
nBestMoneyPerChance = nMaxMoneyPerChance;
|
|
bestEntry = entry.serverName;
|
|
}
|
|
}
|
|
})
|
|
}
|
|
ns.write("bestTarget.txt", JSON.stringify(serverList.find((entry) => entry.serverName === bestEntry)), "w");
|
|
}
|
|
|
|
|
|
/** @param {NS} ns */
|
|
export function crackingAndRooting(ns, cracks) {
|
|
if (!ns.fileExists("serverList.txt", "home")) scanServerList();
|
|
let serverList = JSON.parse(ns.read("serverList.txt"));
|
|
let newServerList = serverList.map((entry) => {
|
|
let cracked = false;
|
|
let openPorts = entry.openPorts || 0;
|
|
if (entry.minPorts === 0 || (entry.minPorts > openPorts && entry.minPorts <= Object.keys(cracks).length)) {
|
|
for (let k = 0; k < entry.minPorts; k++) {
|
|
cracks[Object.keys(cracks)[k]](entry.serverName);
|
|
entry.openPorts = k;
|
|
}
|
|
cracked = true;
|
|
}
|
|
if (!ns.hasRootAccess(entry.serverName) && cracked === true) {
|
|
ns.nuke(entry.serverName);
|
|
if (ns.hasRootAccess(entry.serverName)) {
|
|
entry.rootAccess = true;
|
|
}
|
|
}
|
|
return entry
|
|
})
|
|
ns.write("serverList.txt", JSON.stringify(newServerList), "w");
|
|
ns.tprint("Cracking and rooting done");
|
|
}
|
|
|
|
|
|
/** @param {NS} ns */
|
|
export function copyAndRunScript(ns, funnyScript, currentServer) {
|
|
let bestTarget = JSON.parse(ns.read("bestTarget.txt"));
|
|
let serverList = JSON.parse(ns.read("serverList.txt"));
|
|
let bestEntry = serverList.find((entry) => entry.serverName === bestTarget.serverName)
|
|
let currentEntry = serverList.find((entry) => entry.serverName === currentServer)
|
|
|
|
if (currentEntry.rootAccess === true && bestEntry.rootAccess === true) {
|
|
if (currentEntry.serverName !== "home") {
|
|
ns.print("killed threads on: " + currentEntry.serverName + ns.killall(currentEntry.serverName, true));
|
|
} else {
|
|
ns.print("killed threads on: " + currentEntry.serverName + ns.scriptKill(funnyScript[0], currentEntry.serverName));
|
|
};
|
|
if (currentEntry.maxRam > 0) {
|
|
ns.scp(funnyScript, currentEntry.serverName, "home");
|
|
let maxProcesses = 1;
|
|
if (currentEntry.maxRam >= 8) {
|
|
maxProcesses = Math.max(Math.floor((currentEntry.maxRam) / 8), 1);
|
|
} else {
|
|
maxProcesses = 1
|
|
};
|
|
for (let n = 1; n <= maxProcesses; n++) {
|
|
ns.exec(funnyScript[0], currentEntry.serverName, 1, bestTarget.serverName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export async function purchaseAndUpgradeServers(ns) {
|
|
ns.disableLog("sleep");
|
|
ns.disableLog("getServerMoneyAvailable");
|
|
ns.disableLog("getServerMaxRam");
|
|
let maxPurchasedServers = ns.getPurchasedServerLimit();
|
|
let purchasedServers = [];
|
|
let pServcount = listPurchasedServers(ns).length;
|
|
let currentMoney = 0;
|
|
let serverList = [];
|
|
while (pServcount < maxPurchasedServers) {
|
|
purchasedServers = listPurchasedServers(ns);
|
|
currentMoney = ns.getServerMoneyAvailable("home");
|
|
let targetRamInitial = 16;
|
|
if (ns.getPurchasedServerCost(targetRamInitial) < currentMoney) {
|
|
let sFrontZero = "0";
|
|
if (pServcount > 9) {
|
|
sFrontZero = "";
|
|
}
|
|
let hostname = ns.purchaseServer("pserv-" + sFrontZero + pServcount, targetRamInitial);
|
|
ns.tprint("Purchased " + cCyan + hostname + cReset);
|
|
ns.toast("Purchased " + hostname, "info", 10000);
|
|
pServcount = listPurchasedServers(ns).length;
|
|
serverList = JSON.parse(ns.read("serverList.txt"));
|
|
serverList.push({
|
|
serverName: hostname,
|
|
maxRam: 16,
|
|
maxMoney: 0,
|
|
minSec: 0,
|
|
minPorts: 5,
|
|
minHackLvl: 1,
|
|
rootAccess: true,
|
|
openPorts: 0,
|
|
});
|
|
ns.write("serverList.txt", JSON.stringify(serverList), "w");
|
|
continue
|
|
} else {
|
|
await ns.sleep(5000);
|
|
}
|
|
}
|
|
let i = 5;
|
|
while (i < 21) {
|
|
let targetRam = 2 ** i;
|
|
purchasedServers = listPurchasedServers(ns);
|
|
for (let currentServer of purchasedServers) {
|
|
currentMoney = ns.getServerMoneyAvailable("home");
|
|
if (ns.getServerMaxRam(currentServer) < targetRam) {
|
|
if (ns.getPurchasedServerUpgradeCost(currentServer, targetRam) < currentMoney) {
|
|
if (ns.upgradePurchasedServer(currentServer, targetRam)) {
|
|
ns.print(currentServer + " upgraded to " + targetRam + " GB RAM");
|
|
serverList = JSON.parse(ns.read("serverList.txt"));
|
|
let newServerList = serverList.map((entry) => { if (entry.serverName === currentServer) { entry.maxRam = targetRam } { entry.serverOrgs = "" } { entry.serverCores = 1 } { entry.serverFiles = [] } return entry });
|
|
ns.write("serverList.txt", JSON.stringify(newServerList), "w");
|
|
ns.tprint(cCyan + "Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB" + cReset);
|
|
ns.toast("Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB", "info", 10000);
|
|
}
|
|
} else {
|
|
await ns.sleep(5000);
|
|
continue
|
|
}
|
|
};
|
|
}
|
|
++i;
|
|
}
|
|
ns.tprint("Extiting purchaseServers script!")
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export function listPurchasedServers(ns) {
|
|
return ns.getPurchasedServers();
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export function getSetting(ns, sSetting) {
|
|
let oSettings = JSON.parse(ns.read("settings.txt"));
|
|
let settingEntry = oSettings.setting[sSetting];
|
|
//ns.tprint(oSettings.setting[sSetting])
|
|
//ns.tprint("settingEntry = "+settingEntry);
|
|
return settingEntry;
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export function getGrowThreads(ns, sTarget, nHackThreads, nCores) {
|
|
let nHackAmountPercent = ns.hackAnalyze(sTarget) * nHackThreads;
|
|
let nGrowthThreads = ns.growthAnalyze(sTarget, 1 + nHackAmountPercent, nCores);
|
|
return nGrowthThreads;
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export async function ExecuteAndWait(ns, sScript, ...args) {
|
|
if (!ns.isRunning(sScript, ...args)) { ns.exec(sScript, ...args); }
|
|
while (ns.isRunning(sScript, ...args)) { await ns.sleep(100); }
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export async function RunAndWait(ns, sScript, ...args) {
|
|
if (!ns.isRunning(sScript, ...args)) { ns.run(sScript, ...args); }
|
|
while (ns.isRunning(sScript, ...args)) { await ns.sleep(100); }
|
|
}
|
|
|
|
/** @param {NS} ns */
|
|
export function listWorkServers(ns) {
|
|
ns.disableLog("ALL");
|
|
const sFileName = "serverList.txt";
|
|
if (!ns.fileExists(sFileName, "home")) { ns.print(`ERROR ${sFileName} does not exist.`); return false; };
|
|
let serverList = JSON.parse(ns.read(sFileName));
|
|
let sortedList = sortJsonArrayByKey(serverList, "serverCores", "maxRam").reverse();
|
|
|
|
let nTotalWorkerRAM = 0;
|
|
let nTotalFreeRAM = 0;
|
|
|
|
const nServerColumnWidth = 20;
|
|
const nValueColumnWidth = 10;
|
|
const nCoresWidth = 5;
|
|
|
|
ns.printRaw("┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓");
|
|
ns.printRaw("┃ Server ┃ Free / Max RAM ┃ Cores ┃");
|
|
ns.printRaw("┣━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━┫");
|
|
sortedList.forEach((entry) => {
|
|
if (entry.rootAccess && entry.maxRam >= 1) {
|
|
let sServerName = entry.serverName.padEnd(nServerColumnWidth, ' ');
|
|
let nFreeRAM = entry.maxRam - ns.getServerUsedRam(entry.serverName);
|
|
let sFreeRAM = ns.formatRam(nFreeRAM).padStart(nValueColumnWidth, ' ');
|
|
let sMaxRam = ns.formatRam(entry.maxRam).padStart(nValueColumnWidth, ' ');
|
|
let sCores = entry.serverCores.toLocaleString("en-US").padStart(nCoresWidth, ' ');
|
|
ns.printRaw(`┃ ${sServerName} ┃ ${sFreeRAM} / ${sMaxRam} ┃ ${sCores} ┃`);
|
|
nTotalWorkerRAM += entry.maxRam;
|
|
nTotalFreeRAM += nFreeRAM;
|
|
}
|
|
});
|
|
ns.printRaw("┗━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━┛");
|
|
ns.printRaw(`Total Free: ${Math.floor(nTotalFreeRAM).toLocaleString("en-US")} / ${nTotalWorkerRAM.toLocaleString("en-US")} GB`);
|
|
}
|
|
|
|
export function sortJsonArrayByKey(array, primaryKey, secondaryKey) {
|
|
|
|
if (typeof (array) === "string") {
|
|
array = JSON.parse(array);
|
|
}
|
|
return array.sort((a, b) => {
|
|
const xPrimary = a[primaryKey];
|
|
const yPrimary = b[primaryKey];
|
|
|
|
// Handle null or undefined values for primary key
|
|
if (xPrimary === null || yPrimary === null || xPrimary === undefined || yPrimary === undefined) {
|
|
return 0;
|
|
}
|
|
|
|
// Compare primary keys
|
|
const primaryComparison = compareValues(xPrimary, yPrimary);
|
|
if (primaryComparison !== 0) {
|
|
return primaryComparison;
|
|
}
|
|
|
|
// If primary keys are equal, compare secondary keys
|
|
const xSecondary = a[secondaryKey];
|
|
const ySecondary = b[secondaryKey];
|
|
|
|
// Handle null or undefined values for secondary key
|
|
if (xSecondary === null || ySecondary === null || xSecondary === undefined || ySecondary === undefined) {
|
|
return 0;
|
|
}
|
|
|
|
return compareValues(xSecondary, ySecondary);
|
|
});
|
|
|
|
function compareValues(x, y) {
|
|
// Handle numeric and string comparisons differently
|
|
if (typeof x === 'string' && typeof y === 'string') {
|
|
return x.localeCompare(y); // For string comparison
|
|
} else {
|
|
return x - y; // For numeric comparison
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/** @param {NS} ns */
|
|
export async function distributeScript(ns, sScript, nThreads, [...args]) {
|
|
//ns.tail();
|
|
ns.disableLog("ALL");
|
|
|
|
const sListName = "serverList.txt";
|
|
|
|
if (!ns.fileExists(sListName, "home")) { ns.print(`ERROR ${sListName} does not exist.`); return false; };
|
|
let sServerList = ns.read(sListName);
|
|
let aSortedList = sortJsonArrayByKey(sServerList, "serverCores", "maxRam").reverse();
|
|
ns.print(sScript);
|
|
ns.print(nThreads);
|
|
ns.print(...args);
|
|
|
|
const nScriptSize = ns.getScriptRam(sScript, "home");
|
|
let nTotalSize = nScriptSize * nThreads;
|
|
|
|
ns.print("nScriptSize = " + nScriptSize);
|
|
ns.print("nTotalSize = " + nTotalSize);
|
|
|
|
aSortedList.forEach((entry) => {
|
|
let sHost = entry.serverName;
|
|
ns.print("sHost = " + sHost)
|
|
|
|
let nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
|
|
if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nTotalSize) {
|
|
ns.scp(sScript, sHost);
|
|
ns.exec(sScript, sHost, nThreads, ...args);
|
|
nThreads = 0;
|
|
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
|
|
}
|
|
else if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nScriptSize) {
|
|
let nThreadsDist = Math.floor(nFreeRAM / nScriptSize);
|
|
ns.scp(sScript, sHost);
|
|
ns.print("room for : " + nThreadsDist + " scripts");
|
|
ns.exec(sScript, sHost, nThreadsDist, ...args);
|
|
nThreads -= nThreadsDist;
|
|
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
|
|
}
|
|
});
|
|
} |