typescriptify it all

This commit is contained in:
Elijah R 2024-06-23 19:33:38 -04:00
parent c0e1f9c830
commit 8d5aaf4eeb
6 changed files with 261 additions and 100 deletions

2
.gitignore vendored
View file

@ -2,3 +2,5 @@ node_modules/
package-lock.json package-lock.json
yarn.lock yarn.lock
config.js config.js
config.json
dist/

View file

@ -11,9 +11,14 @@
}, },
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e", "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
"scripts": { "scripts": {
"format": "prettier *.js -w" "format": "prettier src/*.ts -w",
"build": "tsc",
"serve": "node dist/index.js"
}, },
"devDependencies": { "devDependencies": {
"prettier": "^3.3.2" "@types/node": "^20.14.8",
"@types/ws": "^8.5.10",
"prettier": "^3.3.2",
"typescript": "^5.5.2"
} }
} }

View file

@ -2,9 +2,9 @@
import * as ws from "ws"; import * as ws from "ws";
const guacutils = { const guacutils = {
parse: (string) => { parse: (string: string) => {
let pos = -1; let pos = -1;
let sections = []; let sections: string[] = [];
for (;;) { for (;;) {
let len = string.indexOf(".", pos + 1); let len = string.indexOf(".", pos + 1);
@ -29,7 +29,7 @@ const guacutils = {
return sections; return sections;
}, },
encode: (cypher) => { encode: (cypher: string[]) => {
let command = ""; let command = "";
for (var i = 0; i < cypher.length; i++) { for (var i = 0; i < cypher.length; i++) {
@ -41,22 +41,22 @@ const guacutils = {
}, },
}; };
const ConnectionState = Object.freeze({ enum ConnectionState {
CLOSED: 0, CLOSED = 0,
CONNECTING: 1, CONNECTING = 1,
CONNECTED: 2, CONNECTED = 2,
}); }
// System chat messages have a nil username. // System chat messages have a nil username.
function IsSystemChatInstruction(inst) { function IsSystemChatInstruction(inst: string[]) {
return inst[1] == ""; return inst[1] == "";
} }
class UserData { class UserData {
#_name; private _name: string;
#_rank; private _rank: number;
constructor(name, rank) { constructor(name: string, rank: number) {
this._name = name; this._name = name;
this._rank = rank; this._rank = rank;
} }
@ -68,12 +68,25 @@ class UserData {
return this._rank; return this._rank;
} }
UpdateRank(new_rank) { UpdateRank(new_rank: number) {
this._rank = new_rank; this._rank = new_rank;
} }
} }
export default class CollabVMClient { export default abstract class CollabVMClient {
abstract OnOpen(): void;
abstract OnClose(): void;
abstract OnChat(username: string, message: string): void;
abstract OnGuacamoleMessage(msg: string[]): void;
abstract OnAddUser_Bot(count: number): void;
abstract OnRemUser_Bot(count: number): void;
private _state: ConnectionState;
private _users: UserData[];
private _ws: ws.WebSocket | undefined;
private _username: string | undefined;
private _vm: string | undefined;
constructor() { constructor() {
this._state = ConnectionState.CLOSED; this._state = ConnectionState.CLOSED;
this._users = []; this._users = [];
@ -83,14 +96,16 @@ export default class CollabVMClient {
return this._state; return this._state;
} }
Connect(uri) { Connect(uri: string) {
this._ws = new ws.WebSocket(uri, "guacamole", { this._ws = new ws.WebSocket(uri, "guacamole", {
origin: "https://computernewb.com", origin: "https://computernewb.com",
}); });
this._ws.onopen = this.OnWebSocketOpen.bind(this); this._ws.on("open", () => this.OnWebSocketOpen());
this._ws.onclose = this.OnWebSocketClose.bind(this); this._ws.on("close", () => this.OnWebSocketClose());
this._ws.onerror = this.OnWebSocketError.bind(this); this._ws.on("error", () => this.OnWebSocketError());
this._ws.onmessage = this.OnWebSocketMessage.bind(this); this._ws.on("message", (msg, isBinary) =>
this.OnWebSocketMessage(msg, isBinary),
);
this._state = ConnectionState.CONNECTING; this._state = ConnectionState.CONNECTING;
} }
@ -101,25 +116,25 @@ export default class CollabVMClient {
OnWebSocketClose() { OnWebSocketClose() {
this._state = ConnectionState.CLOSED; this._state = ConnectionState.CLOSED;
this.OnClose(arguments); this.OnClose();
} }
OnWebSocketError() { OnWebSocketError() {
// fire the close handler // fire the close handler
this._state = ConnectionState.CLOSED; this._state = ConnectionState.CLOSED;
this.OnClose(arguments); this.OnClose();
} }
Close() { Close() {
this._state = ConnectionState.CLOSED; this._state = ConnectionState.CLOSED;
this._ws.close(); this._ws?.close();
} }
OnWebSocketMessage(ev) { OnWebSocketMessage(msg: Buffer | ArrayBuffer | Buffer[], isBinary: boolean) {
// cvm server should never send binary data // cvm server should never send binary data
if (typeof ev.data !== "string") return; if (isBinary) return;
let message = guacutils.parse(ev.data); let message = guacutils.parse(msg.toString("utf-8"));
if (message.length === 0) return; if (message.length === 0) return;
// Hardcoded, we need to keep this to be alive // Hardcoded, we need to keep this to be alive
@ -165,11 +180,11 @@ export default class CollabVMClient {
this.OnGuacamoleMessage(message); this.OnGuacamoleMessage(message);
} }
OnAddUser(users, count) { OnAddUser(users: string[], count: number) {
//console.log(users); //console.log(users);
for (var i = 0; i < count * 2; i += 2) { for (var i = 0; i < count * 2; i += 2) {
let name = users[i]; let name = users[i];
let rank = users[i + 1]; let rank = parseInt(users[i + 1]);
//console.log(`[${this.GetVM()}] user ${name} rank ${rank}`) //console.log(`[${this.GetVM()}] user ${name} rank ${rank}`)
@ -188,7 +203,7 @@ export default class CollabVMClient {
this.OnAddUser_Bot(this.GetUserCount()); this.OnAddUser_Bot(this.GetUserCount());
} }
OnRemUser(users, count) { OnRemUser(users: string[], count: number) {
for (var i = 0; i < count; i++) { for (var i = 0; i < count; i++) {
let saveUserTemp = this.GetUser(users[i]); let saveUserTemp = this.GetUser(users[i]);
this._users = this._users.filter((user) => user.GetName() != users[i]); this._users = this._users.filter((user) => user.GetName() != users[i]);
@ -212,7 +227,7 @@ export default class CollabVMClient {
// subtract known bots // subtract known bots
for (var i = len - 1; i != 0; --i) { for (var i = len - 1; i != 0; --i) {
// ? // ?
if (this._users[i] === undefined) return; if (this._users[i] === undefined) break;
var name = this._users[i].GetName(); var name = this._users[i].GetName();
if (KnownBots.find((elem) => name == elem) !== undefined) { if (KnownBots.find((elem) => name == elem) !== undefined) {
@ -232,7 +247,7 @@ export default class CollabVMClient {
this._users; this._users;
} }
GetUser(username) { GetUser(username: string) {
let existingUser = this._users.find((elem) => elem.GetName() == username); let existingUser = this._users.find((elem) => elem.GetName() == username);
// Apparently this can fail somehow..? // Apparently this can fail somehow..?
@ -245,7 +260,7 @@ export default class CollabVMClient {
return this._username; return this._username;
} }
Rename(name) { Rename(name: string) {
this._username = name; this._username = name;
this.SendGuacamoleMessage("rename", name); this.SendGuacamoleMessage("rename", name);
} }
@ -254,14 +269,14 @@ export default class CollabVMClient {
return this._vm; return this._vm;
} }
ConnectToVM(vm) { ConnectToVM(vm: string) {
this._vm = vm; this._vm = vm;
this.SendGuacamoleMessage("connect", vm); this.SendGuacamoleMessage("connect", vm);
} }
SendGuacamoleMessage() { SendGuacamoleMessage(...args: string[]) {
if (this._state !== ConnectionState.CONNECTED) return; if (this._state !== ConnectionState.CONNECTED) return;
this._ws.send(guacutils.encode(Array.prototype.slice.call(arguments))); this._ws?.send(guacutils.encode(args));
} }
} }

14
src/config.ts Normal file
View file

@ -0,0 +1,14 @@
export default interface Config {
BANNED_ISO: RegExp[];
ISO_DIRECTORIES: { [key: string]: string };
INSTALLBOT_VMS: {
uri: string;
id: string;
usesIde2: boolean;
hasFloppy: boolean;
}[];
BOT_PREFIX: string;
ADMIN_TOKEN: string;
kGeneralLimitBaseSeconds: number;
kRebootLimitBaseSeconds: number;
}

View file

@ -1,28 +1,39 @@
import { readFileSync } from "fs";
import CollabVMClient from "./client.js"; import CollabVMClient from "./client.js";
import { import Config from "./config.js";
BANNED_ISO,
ISO_DIRECTORIES,
INSTALLBOT_VMS,
BOT_PREFIX,
ADMIN_TOKEN,
kGeneralLimitBaseSeconds,
kRebootLimitBaseSeconds,
} from "./config.js";
function Log() { let config: Config = JSON.parse(readFileSync("config.json", "utf-8"));
function Log(...args: string[]) {
// console.log(`[AnyOSBot] [${new Date()}]`, [...arguments].join(' ')) // console.log(`[AnyOSBot] [${new Date()}]`, [...arguments].join(' '))
console.log("[AnyOSBot]", [...arguments].join(" ")); console.log("[AnyOSBot]", args.join(" "));
}
interface HelpCommand {
command: string;
help: string;
usesFloppy?: boolean | undefined;
} }
// you people SUCK man (dynamic edition, with less bugs!) // you people SUCK man (dynamic edition, with less bugs!)
// and it actually probably works without hanging or negative seconds this time. // and it actually probably works without hanging or negative seconds this time.
class RateLimit { class RateLimit {
constructor(time, factor, ident) { private _ident: string;
private _timeBase: number;
private _factor: number;
private _msUntil: number;
private _n: number;
private _limited: boolean;
private _siHandle: NodeJS.Timeout | null;
constructor(time: number, factor: number, ident: string) {
this._ident = ident; this._ident = ident;
this._timeBase = time; this._timeBase = time;
this._msUntil = 0; this._msUntil = 0;
this._n = 1; this._n = 1;
this._factor = factor; this._factor = factor;
this._limited = false;
this._siHandle = null;
} }
GetTime() { GetTime() {
@ -46,7 +57,7 @@ class RateLimit {
return ret; return ret;
} }
SetUserCount(count) { SetUserCount(count: number) {
if (count == 0) count = 1; if (count == 0) count = 1;
this._n = count; this._n = count;
@ -57,19 +68,18 @@ class RateLimit {
// TODO: this might work for the dyna ratelimit? // TODO: this might work for the dyna ratelimit?
if (this._limited) return; if (this._limited) return;
let self = this; this._msUntil = this.GetMs();
self._msUntil = this.GetMs();
Log( Log(
`Ratelimit \"${this._ident}\" started, will be done in ${self._msUntil} ms (${self._msUntil / 1000} seconds)`, `Ratelimit \"${this._ident}\" started, will be done in ${this._msUntil} ms (${this._msUntil / 1000} seconds)`,
); );
self._limited = true; this._limited = true;
this._siHandle = setInterval(() => { this._siHandle = setInterval(() => {
self._msUntil -= 1000; this._msUntil -= 1000;
if (self._msUntil <= 0) { if (this._msUntil <= 0) {
Log(`Ratelimit \"${self._ident}\" is done.`); Log(`Ratelimit \"${this._ident}\" is done.`);
clearInterval(self._siHandle); if (this._siHandle !== null) clearInterval(this._siHandle);
self._limited = false; this._limited = false;
return; return;
} }
}, 1000); }, 1000);
@ -86,7 +96,14 @@ class RateLimit {
} }
class HelperBot extends CollabVMClient { class HelperBot extends CollabVMClient {
constructor(wsUri, vmId, ide2, floppy) { private _wsUri: string;
private _vmId: string;
private _ide2: boolean;
private _hasFloppy: boolean;
private GeneralCmdLimit: RateLimit | undefined;
private RebootLimit: RateLimit | undefined;
constructor(wsUri: string, vmId: string, ide2: boolean, floppy: boolean) {
super(); super();
this._wsUri = wsUri; this._wsUri = wsUri;
@ -109,17 +126,17 @@ class HelperBot extends CollabVMClient {
this.ConnectToVM(this._vmId); this.ConnectToVM(this._vmId);
} }
OnClose(ev) { OnClose() {
//console.log(arguments) //console.log(arguments)
// reconnect lol // reconnect lol
/* the right way doesnt work thanks to something /* the right way doesnt work thanks to something
Log(`[${this._vmId}]`, `Connection closed, reconnecting in 5 seconds`); Log(`[${this._vmId}]`, `Connection closed, reconnecting in 5 seconds`);
let self = this; let this = this;
setTimeout(() => { setTimeout(() => {
Log(`[${this._vmId}]`, `Reconnecting now`); Log(`[${this._vmId}]`, `Reconnecting now`);
self.DoConn(); this.DoConn();
}, 1000 * 5) }, 1000 * 5)
*/ */
@ -129,21 +146,21 @@ class HelperBot extends CollabVMClient {
// The bot should probably give up after some attempts // The bot should probably give up after some attempts
} }
Chat(message) { Chat(message: string) {
this.SendGuacamoleMessage("chat", message); this.SendGuacamoleMessage("chat", message);
} }
OnAddUser_Bot(count) { OnAddUser_Bot(count: number) {
this.GeneralCmdLimit.SetUserCount(count); this.GeneralCmdLimit!.SetUserCount(count);
this.RebootLimit.SetUserCount(count); this.RebootLimit!.SetUserCount(count);
} }
OnRemUser_Bot(count) { OnRemUser_Bot(count: number) {
this.GeneralCmdLimit.SetUserCount(count); this.GeneralCmdLimit!.SetUserCount(count);
this.RebootLimit.SetUserCount(count); this.RebootLimit!.SetUserCount(count);
} }
UserCanBypass(username) { UserCanBypass(username: string) {
let existingUser = this.GetUser(username); let existingUser = this.GetUser(username);
// Apparently this can fail somehow..? // Apparently this can fail somehow..?
@ -153,12 +170,12 @@ class HelperBot extends CollabVMClient {
return rank == 2 || rank == 3; return rank == 2 || rank == 3;
} }
SendMonitorCommand(cmd) { SendMonitorCommand(cmd: string) {
this.SendGuacamoleMessage("admin", "5", this.GetVM(), cmd); this.SendGuacamoleMessage("admin", "5", this.GetVM()!, cmd);
} }
ConcatPath(isodir, otherPath) { ConcatPath(isodir: string, otherPath: string) {
let isopath = ISO_DIRECTORIES[isodir]; let isopath = config.ISO_DIRECTORIES[isodir];
if (isopath === undefined) { if (isopath === undefined) {
// imo crashing and being restarted by systemd is better than not knowing why shit was coming out as undefined // imo crashing and being restarted by systemd is better than not knowing why shit was coming out as undefined
// gotta love javascript // gotta love javascript
@ -169,11 +186,11 @@ class HelperBot extends CollabVMClient {
// QEMU Abstractions // QEMU Abstractions
QemuEjectDevice(devname) { QemuEjectDevice(devname: string) {
this.SendMonitorCommand(`eject ${devname}`); this.SendMonitorCommand(`eject ${devname}`);
} }
QemuChangeDevice(devname, source, opts) { QemuChangeDevice(devname: string, source: string, opts: string) {
this.SendMonitorCommand(`change ${devname} "${source}" ${opts}`); this.SendMonitorCommand(`change ${devname} "${source}" ${opts}`);
} }
@ -186,27 +203,27 @@ class HelperBot extends CollabVMClient {
if (this._hasFloppy) this.QemuEjectDevice("vm.floppy"); if (this._hasFloppy) this.QemuEjectDevice("vm.floppy");
} }
QemuChangeCd(source, opts) { QemuChangeCd(source: string, opts: string) {
if (this._ide2) this.QemuChangeDevice("ide2-cd0", source, opts); if (this._ide2) this.QemuChangeDevice("ide2-cd0", source, opts);
else this.QemuChangeDevice("vm.cd", source, opts); else this.QemuChangeDevice("vm.cd", source, opts);
} }
QemuChangeFloppy(source) { QemuChangeFloppy(source: string) {
if (this._hasFloppy) if (this._hasFloppy)
this.QemuChangeDevice("vm.floppy", source, "raw read-only"); this.QemuChangeDevice("vm.floppy", source, "raw read-only");
} }
OnChat(username, message) { OnChat(username: string, message: string) {
//console.log(`${username}> ${message}`); //console.log(`${username}> ${message}`);
if (username == this.GetUsername()) return; if (username == this.GetUsername()) return;
if (message[0] === BOT_PREFIX) { if (message[0] === config.BOT_PREFIX) {
this.HandleCommands(username, message); this.HandleCommands(username, message);
} }
} }
HandleCommands(username, message) { HandleCommands(username: string, message: string) {
{ {
let user = this.GetUser(username); let user = this.GetUser(username);
if (user == null) { if (user == null) {
@ -224,7 +241,7 @@ class HelperBot extends CollabVMClient {
// Little code fragment to make rate limiting // Little code fragment to make rate limiting
// more portable. // more portable.
const DoLimit = (limit) => { const DoLimit = (limit: RateLimit) => {
//console.log(`[AnyOSBot] [${this._vmId}] ${this.GetUserCount()} users online (${this.GetUserCountFull()} actual)`) //console.log(`[AnyOSBot] [${this._vmId}] ${this.GetUserCount()} users online (${this.GetUserCountFull()} actual)`)
//if(this._vmId !== 'vm0b0t') { //if(this._vmId !== 'vm0b0t') {
@ -249,18 +266,18 @@ class HelperBot extends CollabVMClient {
}; };
// generate a help HTML string for the help // generate a help HTML string for the help
const generateHelp = (arr) => { const generateHelp = (arr: HelpCommand[]) => {
let str = "<h4>AnyOSInstallBot Help:</h4><ul>"; let str = "<h4>AnyOSInstallBot Help:</h4><ul>";
for (var cmd of arr) { for (var cmd of arr) {
// remove commands which depend on the floppy on a VM without floppy // remove commands which depend on the floppy on a VM without floppy
if (cmd.usesFloppy && !this._hasFloppy) continue; if (cmd.usesFloppy && !this._hasFloppy) continue;
str += `<li><b>${BOT_PREFIX}${cmd.command}</b> - ${cmd.help}</li>`; str += `<li><b>${config.BOT_PREFIX}${cmd.command}</b> - ${cmd.help}</li>`;
} }
str += "</ul>"; str += "</ul>";
return str; return str;
}; };
const generateList = (title, arr) => { const generateList = (title: string, arr: string[]) => {
let str = `<h4>${title}</h4><ul>`; let str = `<h4>${title}</h4><ul>`;
for (var cmd of arr) { for (var cmd of arr) {
str += `<li>${cmd}</li>`; str += `<li>${cmd}</li>`;
@ -277,7 +294,7 @@ class HelperBot extends CollabVMClient {
switch (command) { switch (command) {
case "help": case "help":
if (!DoLimit(this.GeneralCmdLimit)) return; if (!DoLimit(this.GeneralCmdLimit!)) return;
this.SendGuacamoleMessage( this.SendGuacamoleMessage(
"admin", "admin",
"21", "21",
@ -331,7 +348,7 @@ class HelperBot extends CollabVMClient {
break; break;
case "network": case "network":
if (!DoLimit(this.GeneralCmdLimit)) return; if (!DoLimit(this.GeneralCmdLimit!)) return;
switch (this._vmId) { switch (this._vmId) {
case "vm7": case "vm7":
@ -359,14 +376,14 @@ class HelperBot extends CollabVMClient {
); );
break; break;
default: default:
this.chat("This VM should already have internet."); this.Chat("This VM should already have internet.");
break; break;
} }
break; break;
case "certerror": case "certerror":
if (!DoLimit(this.GeneralCmdLimit)) return; if (!DoLimit(this.GeneralCmdLimit!)) return;
//if(this._vmId == 'vm0b0t') { //if(this._vmId == 'vm0b0t') {
// this.SendGuacamoleMessage("admin", "21", "<h1>fuck off retard why are you trying to get collabnet on vm0</h1>"); // this.SendGuacamoleMessage("admin", "21", "<h1>fuck off retard why are you trying to get collabnet on vm0</h1>");
@ -391,13 +408,13 @@ class HelperBot extends CollabVMClient {
case "httpcd": case "httpcd":
case "httpflp": case "httpflp":
{ {
if (!DoLimit(this.GeneralCmdLimit)) return; if (!DoLimit(this.GeneralCmdLimit!)) return;
let arg = message.slice(message.indexOf(" ") + 1); let arg = message.slice(message.indexOf(" ") + 1);
let ext = arg.slice(arg.lastIndexOf(".") + 1); let ext = arg.slice(arg.lastIndexOf(".") + 1);
if (arg.indexOf("..") !== -1) return; if (arg.indexOf("..") !== -1) return;
for (var ii = 0; ii < BANNED_ISO.length; ii++) { for (var ii = 0; ii < config.BANNED_ISO.length; ii++) {
if (BANNED_ISO[ii].test(arg)) { if (config.BANNED_ISO[ii].test(arg)) {
this.Chat("That ISO is currently blacklisted."); this.Chat("That ISO is currently blacklisted.");
return; return;
} }
@ -541,7 +558,7 @@ class HelperBot extends CollabVMClient {
case "eject": case "eject":
{ {
if (!DoLimit(this.GeneralCmdLimit)) return; if (!DoLimit(this.GeneralCmdLimit!)) return;
let arg = message.slice(message.indexOf(" ") + 1); let arg = message.slice(message.indexOf(" ") + 1);
@ -560,7 +577,7 @@ class HelperBot extends CollabVMClient {
break; break;
case "reboot": case "reboot":
if (!DoLimit(this.RebootLimit)) return; if (!DoLimit(this.RebootLimit!)) return;
// this.Chat("hold on fellas"); // this.Chat("hold on fellas");
// return; // return;
@ -568,7 +585,7 @@ class HelperBot extends CollabVMClient {
break; break;
case "bootset": case "bootset":
if (!DoLimit(this.GeneralCmdLimit)) return; if (!DoLimit(this.GeneralCmdLimit!)) return;
//this.Chat("sorry, severe autism not allowed right now"); //this.Chat("sorry, severe autism not allowed right now");
//return; //return;
@ -591,20 +608,20 @@ class HelperBot extends CollabVMClient {
// this.GeneralCmdLimit = new RateLimit(25 * 1000); // this.GeneralCmdLimit = new RateLimit(25 * 1000);
//else //else
this.GeneralCmdLimit = new RateLimit( this.GeneralCmdLimit = new RateLimit(
kGeneralLimitBaseSeconds * 1000, config.kGeneralLimitBaseSeconds * 1000,
2, 2,
`General commands/${this._vmId}`, `General commands/${this._vmId}`,
); );
//this.EjectLimit = new RateLimit(30 * 1000); //this.EjectLimit = new RateLimit(30 * 1000);
this.RebootLimit = new RateLimit( this.RebootLimit = new RateLimit(
kRebootLimitBaseSeconds * 1000, config.kRebootLimitBaseSeconds * 1000,
3, 3,
`!reboot/${this._vmId}`, `!reboot/${this._vmId}`,
); );
} }
OnGuacamoleMessage(message) { OnGuacamoleMessage(message: string[]) {
if (message[0] == "connect") { if (message[0] == "connect") {
if (message[1] == "0") { if (message[1] == "0") {
Log(`[${this._vmId}]`, `Failed to connect to VM`); Log(`[${this._vmId}]`, `Failed to connect to VM`);
@ -616,7 +633,7 @@ class HelperBot extends CollabVMClient {
Log(`[${this._vmId}]`, `Connected to VM`); Log(`[${this._vmId}]`, `Connected to VM`);
// I'm fucking lazy // I'm fucking lazy
this.SendGuacamoleMessage("login", ADMIN_TOKEN); this.SendGuacamoleMessage("login", config.ADMIN_TOKEN);
this.CreateRateLimits(); this.CreateRateLimits();
} }
@ -636,7 +653,7 @@ class HelperBot extends CollabVMClient {
} }
} }
for (let vm of INSTALLBOT_VMS) { for (let vm of config.INSTALLBOT_VMS) {
// initalize this bot instance // initalize this bot instance
new HelperBot(vm.uri, vm.id, vm.usesIde2, vm.hasFloppy).DoConn(); new HelperBot(vm.uri, vm.id, vm.usesIde2, vm.hasFloppy).DoConn();
} }

108
tsconfig.json Normal file
View file

@ -0,0 +1,108 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "ES2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "ES2022", /* Specify what module code is generated. */
"rootDir": "./src", /* Specify the root folder within your source files. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}