added scan-analyze.ts
This commit is contained in:
parent
21e9d13e61
commit
f75ef84f95
107
src/colors.ts
Normal file
107
src/colors.ts
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { NS } from "@ns";
|
||||||
|
|
||||||
|
/** @param {NS} ns */
|
||||||
|
export async function main(ns: NS) {
|
||||||
|
ns.disableLog(`ALL`); // Failures are still logged, this just prevents unnecessary log spam.
|
||||||
|
|
||||||
|
ns.tprintf(
|
||||||
|
`\x1b[1;35mUsing colors in script output with \x1b[1;36mtprint\x1b[1;35m & \x1b[36;1mtprintf\x1b[1;35m (terminal) and \x1b[36;1mprint\x1b[1;35m & \x1b[1;36mprintf\x1b[1;35m (log)`,
|
||||||
|
);
|
||||||
|
|
||||||
|
ns.tprintf(`\n`);
|
||||||
|
|
||||||
|
ns.tprintf(`\x1b[1;36m• Using a 4-letter all-CAPS keyword at the start of the string you're printing`);
|
||||||
|
ns.tprintf(`This gives 4 foreground colors, which can be changed in the game's theme settings.`);
|
||||||
|
ns.tprintf(` ─ default color, you could use "OKAY" for alignment with other keywords.`);
|
||||||
|
ns.tprintf(`INFO ─ only the first 4 characters matter, e.g. "INFORMATION" also works.`);
|
||||||
|
ns.tprintf(`WARN ─ same story, e.g. "WARNING" can also be used.`);
|
||||||
|
ns.tprintf(`FAIL ─ "ERROR" also works, making it the only 5-letter keyword.`);
|
||||||
|
|
||||||
|
ns.tprintf(`\n`);
|
||||||
|
|
||||||
|
ns.tprintf(`\x1b[1;36m• Using an ANSI escape sequence to specify attributes`);
|
||||||
|
ns.tprintf(
|
||||||
|
`Syntax: \x1b[36m\\x1b[\x1b[35mn\x1b[36mm\x1b[m, replace \x1b[35mn\x1b[m by display attribute(s). Multiple attributes can be set in the same sequence, separated by semicolons.`,
|
||||||
|
);
|
||||||
|
ns.tprintf(` 0 ─ \x1b[mall attributes off ─ equivalent to using an empty escape sequence: \x1b[36m\\x1b[m\n`);
|
||||||
|
ns.tprintf(` 1 ─ \x1b[1mbold text ─ bold characters are wider, so they don't line up with normal text.\n`);
|
||||||
|
ns.tprintf(` 4 ─ \x1b[4munderline ─ \x1b[4;31msame \x1b[4;33mcolor \x1b[4;35mas \x1b[4;36mthe \x1b[4;37mtext.\n`);
|
||||||
|
ns.tprintf(`Example: \x1b[36m\\x1b[\x1b[35m1;4\x1b[36mm\x1b[m \x1b[mgives \x1b[1;4mbold underlined text`);
|
||||||
|
|
||||||
|
ns.tprintf(`\n`);
|
||||||
|
|
||||||
|
ns.tprintf(`\x1b[1;36m• Attributes for 8 colors`);
|
||||||
|
let palette8colors = ``;
|
||||||
|
palette8colors += `30-37 ─ 8 foreground colors:`;
|
||||||
|
for (let i = 30; i <= 37; i++) {
|
||||||
|
palette8colors += `\x1b[${i}m ${i} \x1b[m`;
|
||||||
|
}
|
||||||
|
palette8colors += `\n`;
|
||||||
|
palette8colors += `40-47 ─ 8 background colors:`;
|
||||||
|
for (let i = 40; i <= 47; i++) {
|
||||||
|
if (i < 47) {
|
||||||
|
palette8colors += `\x1b[${i};37m ${i} \x1b[m`;
|
||||||
|
} else {
|
||||||
|
palette8colors += `\x1b[${i};30m ${i} \x1b[m`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
palette8colors += `\n`;
|
||||||
|
ns.tprintf(palette8colors);
|
||||||
|
ns.tprintf(
|
||||||
|
`Example: \x1b[36m\\x1b[\x1b[35m4;33;44\x1b[36mm\x1b[m gives \x1b[4;33;44myellow underlined text on a blue background`,
|
||||||
|
);
|
||||||
|
|
||||||
|
ns.tprintf(`\n`);
|
||||||
|
|
||||||
|
ns.tprintf(`\x1b[1;36m• Attributes for 256 colors`);
|
||||||
|
let palette256colors = ``;
|
||||||
|
palette256colors += `38;5;\x1b[35mn\x1b[m ─ Set foreground color to palette index \x1b[35mn\x1b[m\n`;
|
||||||
|
palette256colors += `48;5;\x1b[35mn\x1b[m ─ Set background color to palette index \x1b[35mn\x1b[m\n`;
|
||||||
|
palette256colors += `Example: \x1b[36m\\x1b[\x1b[35m38;5;202;48;5;242\x1b[36mm\x1b[m gives \x1b[38;5;202;48;5;242morange text on a gray background\n`;
|
||||||
|
palette256colors += `\n`;
|
||||||
|
// 16 basic colors (indices 0 to 15 inclusive)
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
|
if (i <= 6 || i === 8 || i === 12) {
|
||||||
|
// Use light text for better contrast of index against background.
|
||||||
|
palette256colors += `\x1b[37;48;5;${i}m${String(i).padStart(9)}\x1b[m`;
|
||||||
|
} else {
|
||||||
|
// Use dark text for better contrast of index against background.
|
||||||
|
palette256colors += `\x1b[30;48;5;${i}m${String(i).padStart(9)}\x1b[m`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
palette256colors += `\n\n`;
|
||||||
|
// 216 colors (6×6×6 cube) (indices 16 to 231 inclusive)
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
for (let j = 16; j <= 51; j++) {
|
||||||
|
const n = i * 36 + j;
|
||||||
|
if (j < 34) {
|
||||||
|
palette256colors += `\x1b[37;48;5;${n}m${String(n).padStart(4)}\x1b[m`;
|
||||||
|
} else {
|
||||||
|
palette256colors += `\x1b[30;48;5;${n}m${String(n).padStart(4)}\x1b[m`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
palette256colors += `\n`;
|
||||||
|
}
|
||||||
|
palette256colors += `\n`;
|
||||||
|
// 24 grayscale colors (indices 232 to 255 inclusive)
|
||||||
|
for (let i = 232; i <= 255; i++) {
|
||||||
|
if (i < 244) {
|
||||||
|
palette256colors += `\x1b[37;48;5;${i}m${String(i).padStart(6)}\x1b[m`;
|
||||||
|
} else {
|
||||||
|
palette256colors += `\x1b[30;48;5;${i}m${String(i).padStart(6)}\x1b[m`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ns.tprintf(palette256colors);
|
||||||
|
|
||||||
|
ns.tprintf(`\n`);
|
||||||
|
|
||||||
|
ns.tprintf(`\x1b[1;36m• Attributes for 16 million (${Number(2 ** 24).toLocaleString()}) colors`);
|
||||||
|
let palette16Mcolors = ``;
|
||||||
|
palette16Mcolors += `38;2;\x1b[35mr;g;b\x1b[m ─ Set foreground color to \x1b[35mred\x1b[m, \x1b[35mgreen\x1b[m, \x1b[35mblue\x1b[m, where each color's value can range from 0 to 255 (0x00 to 0xff)\n`;
|
||||||
|
palette16Mcolors += `48;2;\x1b[35mr;g;b\x1b[m ─ Set background color to \x1b[35mred\x1b[m, \x1b[35mgreen\x1b[m, \x1b[35mblue\x1b[m, where each color's value can range from 0 to 255 (0x00 to 0xff)\n`;
|
||||||
|
palette16Mcolors += `Example: \x1b[36m\\x1b[\x1b[35m38;2;157;0;255;48;2;255;222;33\x1b[36mm\x1b[m gives \x1b[38;2;157;0;255;48;2;255;222;33mpurple text on a yellow background\x1b[m\n`;
|
||||||
|
palette16Mcolors += `\n`;
|
||||||
|
palette16Mcolors += `Don't worry, this script does not print the full 16 million color palette ;)\n`;
|
||||||
|
palette16Mcolors += `\n`;
|
||||||
|
ns.tprintf(palette16Mcolors);
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,5 @@
|
||||||
import { NS, Server } from "@ns";
|
import { NS, Server } from "@ns";
|
||||||
|
|
||||||
// TODO: incomplete
|
|
||||||
// define a new interface for the new analysis results
|
|
||||||
interface ServerAnalysis {
|
|
||||||
hostname: string;
|
|
||||||
hasRootAccess: boolean;
|
|
||||||
requiredHackingSkill: number;
|
|
||||||
portsRequiredForNuke: number;
|
|
||||||
maxRam: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const analyze = (ns: NS, hostnames: string[]) => {
|
export const analyze = (ns: NS, hostnames: string[]) => {
|
||||||
hostnames.forEach((hostname) => {
|
hostnames.forEach((hostname) => {
|
||||||
// skip darknet servers
|
// skip darknet servers
|
||||||
|
|
@ -21,16 +11,7 @@ export const analyze = (ns: NS, hostnames: string[]) => {
|
||||||
// get the server object for the hostname
|
// get the server object for the hostname
|
||||||
const server = ns.getServer(hostname) as Server;
|
const server = ns.getServer(hostname) as Server;
|
||||||
|
|
||||||
// create a new object that matches the ServerAnalysis interface
|
ns.tprint(server);
|
||||||
const analysis: ServerAnalysis = {
|
|
||||||
hostname: server.hostname,
|
|
||||||
hasRootAccess: server.hasAdminRights,
|
|
||||||
requiredHackingSkill: server.requiredHackingSkill ?? 0,
|
|
||||||
portsRequiredForNuke: server.numOpenPortsRequired ?? 0,
|
|
||||||
maxRam: server.maxRam,
|
|
||||||
};
|
|
||||||
|
|
||||||
ns.tprint(analysis);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,3 +81,7 @@ export const upgradeAll = (ns: NS) => {
|
||||||
ns.tprint(`Next tier (${utils.format.ram(nextRam)} GB) will cost: ${utils.format.money(nextTierCost)}`);
|
ns.tprint(`Next tier (${utils.format.ram(nextRam)} GB) will cost: ${utils.format.money(nextTierCost)}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const main = (ns: NS) => {
|
||||||
|
upgradeAll(ns);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { NS } from "@ns";
|
import { NS } from "@ns";
|
||||||
import { scan } from "../ezgame/scan";
|
import { scan } from "./scan";
|
||||||
|
|
||||||
export const killall = (ns: NS): void => {
|
export const killall = (ns: NS): void => {
|
||||||
const allHosts = scan(ns);
|
const allHosts = scan(ns);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { NS } from "@ns";
|
import { NS } from "@ns";
|
||||||
import { scan } from "../ezgame/scan";
|
import { scan } from "./scan";
|
||||||
|
|
||||||
// get root access to all the servers that we can
|
// get root access to all the servers that we can
|
||||||
// then return a list of all the servers we have root access to
|
// then return a list of all the servers we have root access to
|
||||||
|
|
|
||||||
97
src/ezgame/scan-analyze.ts
Normal file
97
src/ezgame/scan-analyze.ts
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
import { utils } from "@/utils";
|
||||||
|
import { NS, Server } from "@ns";
|
||||||
|
|
||||||
|
export interface ScanAnalyzeOptions {
|
||||||
|
excludeCloudServers?: boolean;
|
||||||
|
quiet?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerNode {
|
||||||
|
hostname: string;
|
||||||
|
parent: string | null;
|
||||||
|
children: string[];
|
||||||
|
depth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const scanAnalyze = (ns: NS, options: ScanAnalyzeOptions = {}): Map<string, ServerNode> => {
|
||||||
|
const tree = new Map<string, ServerNode>();
|
||||||
|
|
||||||
|
// start BFS from home
|
||||||
|
const queue: { hostname: string; parent: string | null; depth: number }[] = [
|
||||||
|
{ hostname: "home", parent: null, depth: 0 },
|
||||||
|
];
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
const { hostname, parent, depth } = queue.shift()!;
|
||||||
|
|
||||||
|
// skip if already visited
|
||||||
|
if (tree.has(hostname)) continue;
|
||||||
|
|
||||||
|
// get neighbors
|
||||||
|
const neighbors = ns.scan(hostname);
|
||||||
|
|
||||||
|
// children are neighbors that are not the parent
|
||||||
|
const children = neighbors.filter((neighbor) => {
|
||||||
|
if (neighbor === parent) return false;
|
||||||
|
if (options.excludeCloudServers && ns.getServer(neighbor).purchasedByPlayer) return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// add to tree
|
||||||
|
tree.set(hostname, { hostname, parent, children, depth });
|
||||||
|
|
||||||
|
// enqueue children
|
||||||
|
for (const child of children) {
|
||||||
|
if (!tree.has(child)) {
|
||||||
|
queue.push({ hostname: child, parent: hostname, depth: depth + 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.quiet) {
|
||||||
|
// we are sure that home is always in the tree since its the starting point
|
||||||
|
printTree(ns, tree.get("home") as ServerNode, tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
const printTree = (
|
||||||
|
ns: NS,
|
||||||
|
node: ServerNode,
|
||||||
|
tree: Map<string, ServerNode>,
|
||||||
|
prefix: string[] = [" "],
|
||||||
|
isLast = true,
|
||||||
|
): void => {
|
||||||
|
// ns.scan() does not return darknet servers,
|
||||||
|
// so we can just safely assume that the server type returned is just `Server`.
|
||||||
|
// always start with home
|
||||||
|
const server = ns.getServer(node.hostname) as Server;
|
||||||
|
|
||||||
|
const titlePrefix = prefix.slice(0, prefix.length - 1).join("") + (isLast ? "┗ " : "┣ ");
|
||||||
|
const infoPrefix = prefix.join("") + (node.children.length > 0 ? "┃ " : " ");
|
||||||
|
|
||||||
|
ns.tprint(`* ${titlePrefix}${node.hostname}`);
|
||||||
|
ns.tprint(
|
||||||
|
`* ${infoPrefix}Root Access: ${server.hasAdminRights ? "YES" : "NO"}, Required hacking skill: ${
|
||||||
|
server.requiredHackingSkill ?? 0
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
ns.tprint(`* ${infoPrefix}Number of open ports required to NUKE: ${server.numOpenPortsRequired ?? 0}`);
|
||||||
|
ns.tprint(`* ${infoPrefix}RAM: ${utils.format.ram(server.maxRam)}, Player purchased: ${server.purchasedByPlayer}`);
|
||||||
|
|
||||||
|
// recursive
|
||||||
|
node.children.forEach((childName, i) => {
|
||||||
|
const childNode = tree.get(childName);
|
||||||
|
if (!childNode) {
|
||||||
|
// this should never happen since we build the tree from the scan results, but just in case
|
||||||
|
throw new Error(`Child node ${childName} not found in tree`);
|
||||||
|
}
|
||||||
|
const childIsLast = i === node.children.length - 1;
|
||||||
|
printTree(ns, childNode, tree, [...prefix, childIsLast ? " " : "┃ "], childIsLast);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const main = (ns: NS) => {
|
||||||
|
scanAnalyze(ns, { quiet: false, excludeCloudServers: true });
|
||||||
|
};
|
||||||
|
|
@ -20,9 +20,6 @@ export const scan = (ns: NS, options: ScanOptions = {}): string[] => {
|
||||||
ns.scan(h).forEach((n) => allHosts.add(n));
|
ns.scan(h).forEach((n) => allHosts.add(n));
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove home from the set
|
|
||||||
allHosts.delete("home");
|
|
||||||
|
|
||||||
// now we start the filtering into another new list
|
// now we start the filtering into another new list
|
||||||
const filteredHosts = Array.from(allHosts).filter((host: string) => {
|
const filteredHosts = Array.from(allHosts).filter((host: string) => {
|
||||||
if (rootAccess !== undefined && ns.hasRootAccess(host) !== rootAccess) return false;
|
if (rootAccess !== undefined && ns.hasRootAccess(host) !== rootAccess) return false;
|
||||||
|
|
@ -40,5 +37,7 @@ export const scan = (ns: NS, options: ScanOptions = {}): string[] => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const main = (ns: NS) => {
|
export const main = (ns: NS) => {
|
||||||
ns.tprint(scan(ns));
|
const results = scan(ns);
|
||||||
|
ns.tprint(results);
|
||||||
|
ns.tprint(`Total hosts found: ${results.length}`);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { NS } from "@ns";
|
import { NS } from "@ns";
|
||||||
import { scan } from "../ezgame/scan";
|
import { scan } from "./scan";
|
||||||
|
|
||||||
export const scriptCleanup = (ns: NS) => {
|
export const scriptCleanup = (ns: NS) => {
|
||||||
// get all hosts with root access
|
// get all hosts with root access
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { NS } from "@ns";
|
import { NS } from "@ns";
|
||||||
import { scan } from "../ezgame/scan";
|
import { scan } from "./scan";
|
||||||
|
|
||||||
export const scriptPropagator = (ns: NS) => {
|
export const scriptPropagator = (ns: NS) => {
|
||||||
// get all hosts with root access
|
// get all hosts with root access
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { NS } from "@ns";
|
import { NS } from "@ns";
|
||||||
import { scan } from "../ezgame/scan";
|
import { scan } from "./scan";
|
||||||
|
|
||||||
interface StartOptions {
|
interface StartOptions {
|
||||||
threads?: number; // explicit thread count
|
threads?: number; // explicit thread count
|
||||||
|
|
@ -53,8 +53,23 @@ export const startall = (ns: NS, scriptName: string, options: StartOptions = {})
|
||||||
ns.tprint(`Hosts affected: ${hostsStartedOn}`);
|
ns.tprint(`Hosts affected: ${hostsStartedOn}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const main = (ns: NS) => {
|
export const main = async (ns: NS) => {
|
||||||
// get the arguments from the command line
|
if (ns.args.length === 0) {
|
||||||
const args = ns.args as string[];
|
const target = [
|
||||||
startall(ns, "super.js", { args: args });
|
(
|
||||||
|
await ns.prompt("You didn't specify the target in the arguments. Please specify it here.", {
|
||||||
|
type: "text",
|
||||||
|
})
|
||||||
|
).toString(),
|
||||||
|
];
|
||||||
|
if (!target) {
|
||||||
|
ns.alert("You still did not specify anything you dumb fuck. Quitting now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
startall(ns, "super.js", { args: target });
|
||||||
|
} else {
|
||||||
|
// get the arguments from the command line
|
||||||
|
const args = ns.args as string[];
|
||||||
|
startall(ns, "super.js", { args: args });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import { NS } from "@ns";
|
import { NS } from "@ns";
|
||||||
import { cloud } from "./ezgame/cloud";
|
|
||||||
|
|
||||||
export const main = (ns: NS) => {
|
export const main = async (ns: NS) => {
|
||||||
const upgradeCost = ns.cloud.getServerUpgradeCost("worker-1", 2);
|
const bruh = await ns.prompt("hello", { type: "text", choices: ["asdf1", "asdf2"] });
|
||||||
console.log(upgradeCost);
|
console.log(bruh);
|
||||||
cloud.upgradeAll(ns);
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue