MISC: Remove API server (#2084)

This commit is contained in:
catloversg
2025-04-12 03:35:34 +07:00
committed by GitHub
parent 0aaa28054a
commit 571cc8f886
7 changed files with 2 additions and 342 deletions

View File

@@ -1,199 +0,0 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const http = require("http");
const crypto = require("crypto");
const log = require("electron-log");
const Store = require("electron-store");
const store = new Store();
let server;
let window;
async function initialize(win) {
window = win;
server = http.createServer(async function (req, res) {
let body = "";
res.setHeader("Content-Type", "application/json");
req.on("data", (chunk) => {
body += chunk.toString(); // convert Buffer to string
});
req.on("end", async () => {
const providedToken = req.headers?.authorization?.replace("Bearer ", "") ?? "";
const isValid = providedToken === getAuthenticationToken();
if (isValid) {
log.debug("Valid authentication token");
} else {
log.log("Invalid authentication token");
res.writeHead(401);
res.end(
JSON.stringify({
success: false,
msg: "Invalid authentication token",
}),
);
return;
}
let data;
try {
data = JSON.parse(body);
} catch (error) {
log.warn(`Invalid body data`);
res.writeHead(400);
res.end(
JSON.stringify({
success: false,
msg: "Invalid body data",
}),
);
return;
}
let result;
switch (req.method) {
// Request files
case "GET":
result = await window.webContents.executeJavaScript(`document.getFiles()`);
break;
// Create or update files
// Support POST for VScode implementation
case "POST":
case "PUT":
if (!data) {
log.warn(`Invalid script update request - No data`);
res.writeHead(400);
res.end(
JSON.stringify({
success: false,
msg: "Invalid script update request - No data",
}),
);
return;
}
result = await window.webContents.executeJavaScript(`document.saveFile("${data.filename}", "${data.code}")`);
break;
// Delete files
case "DELETE":
result = await window.webContents.executeJavaScript(`document.deleteFile("${data.filename}")`);
break;
}
if (!result.res) {
//We've encountered an error
res.writeHead(400);
log.warn(`Api Server Error`, result.msg);
}
res.end(
JSON.stringify({
success: result.res,
msg: result.msg,
data: result.data,
}),
);
});
});
const autostart = store.get("autostart", false);
if (autostart) {
try {
await enable();
} catch (error) {
return Promise.reject(error);
}
}
return Promise.resolve();
}
function enable() {
if (isListening()) {
log.warn("API server already listening");
return Promise.resolve();
}
const port = store.get("port", 9990);
const host = store.get("host", "127.0.0.1");
log.log(`Starting http server on port ${port} - listening on ${host}`);
// https://stackoverflow.com/a/62289870
let startFinished = false;
return new Promise((resolve, reject) => {
server.listen(port, host, () => {
if (!startFinished) {
startFinished = true;
resolve();
}
});
server.once("error", (err) => {
if (!startFinished) {
startFinished = true;
console.log("There was an error starting the server in the error listener:", err);
reject(err);
}
});
});
}
function disable() {
if (!isListening()) {
log.warn("API server not listening");
return Promise.resolve();
}
log.log("Stopping http server");
return server.close();
}
function toggleServer() {
if (isListening()) {
return disable();
} else {
return enable();
}
}
function isListening() {
return server?.listening ?? false;
}
function toggleAutostart() {
const newValue = !isAutostart();
store.set("autostart", newValue);
log.log(`New autostart value is '${newValue}'`);
}
function isAutostart() {
return store.get("autostart");
}
function getAuthenticationToken() {
const token = store.get("token");
if (token) return token;
const newToken = generateToken();
store.set("token", newToken);
return newToken;
}
function generateToken() {
const buffer = crypto.randomBytes(48);
return buffer.toString("base64");
}
module.exports = {
initialize,
enable,
disable,
toggleServer,
toggleAutostart,
isAutostart,
getAuthenticationToken,
isListening,
};

View File

@@ -1,10 +1,8 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { app, shell, BrowserWindow } = require("electron");
const log = require("electron-log");
const utils = require("./utils");
const achievements = require("./achievements");
const menu = require("./menu");
const api = require("./api-server");
const path = require("path");
const { windowTracker } = require("./windowTracker");
@@ -64,13 +62,6 @@ async function createWindow(killall) {
achievements.enableAchievementsInterval(window);
utils.attachUnresponsiveAppHandler(window);
try {
await api.initialize(window);
} catch (error) {
log.error(error);
utils.showErrorBox("Error starting http server", error);
}
menu.refreshMenu(window);
setStopProcessHandler(app, window);

View File

@@ -20,7 +20,6 @@ app.on("window-all-closed", () => {
});
const greenworks = require("./greenworks");
const api = require("./api-server");
const gameWindow = require("./gameWindow");
const achievements = require("./achievements");
const utils = require("./utils");
@@ -61,9 +60,6 @@ function setStopProcessHandler(app, window) {
// First we clear the achievement timer
achievements.disableAchievementsInterval(window);
// Shutdown the http server
api.disable();
// Trigger debounced saves right now before closing
try {
await saveToDisk.flush();

View File

@@ -1,8 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { app, Menu, clipboard, dialog, shell } = require("electron");
const { app, Menu, dialog, shell } = require("electron");
const log = require("electron-log");
const Store = require("electron-store");
const api = require("./api-server");
const utils = require("./utils");
const storage = require("./storage");
const store = new Store();
@@ -233,83 +232,6 @@ function getMenu(window) {
},
],
},
{
label: "API Server",
submenu: [
{
label: api.isListening() ? "Disable Server" : "Enable Server",
click: async () => {
let success = false;
try {
await api.toggleServer();
success = true;
} catch (error) {
log.error(error);
utils.showErrorBox("Error Toggling Server", error);
}
if (success && api.isListening()) {
utils.writeToast(window, "Started API Server", "success");
} else if (success && !api.isListening()) {
utils.writeToast(window, "Stopped API Server", "success");
} else {
utils.writeToast(window, "Error Toggling Server", "error");
}
refreshMenu(window);
},
},
{
label: api.isAutostart() ? "Disable Autostart" : "Enable Autostart",
click: async () => {
api.toggleAutostart();
if (api.isAutostart()) {
utils.writeToast(window, "Enabled API Server Autostart", "success");
} else {
utils.writeToast(window, "Disabled API Server Autostart", "success");
}
refreshMenu(window);
},
},
{
label: "Copy Auth Token",
click: async () => {
const token = api.getAuthenticationToken();
log.log("Wrote authentication token to clipboard");
clipboard.writeText(token);
utils.writeToast(window, "Copied Authentication Token to Clipboard", "info");
},
},
{
type: "separator",
},
{
label: "Information",
click: () => {
dialog
.showMessageBox({
type: "warning",
title: "Bitburner > API Server Information",
message: "The API Server is used to write script files to your in-game home.",
detail:
`WARNING: This feature is deprecated. It may be removed in future versions.\n\n` +
`You should use external tools that support our Remote API feature. For details, please check the "Remote API" page in the in-game documentation. You can also check the "external-editors" channel in our Discord server for more information and support.\n\n` +
"--------------------------------------------------------------------------------\n\n" +
"There is an official Visual Studio Code extension that makes use of the API Server feature.\n\n" +
"It allows you to write your script file in an external IDE and have them pushed over to the game automatically.\n" +
"If you want more information, head over to: https://github.com/bitburner-official/bitburner-vscode.",
buttons: ["Dismiss", "Open Extension Link (GitHub)"],
defaultId: 0,
cancelId: 0,
noLink: true,
})
.then(({ response }) => {
if (response === 1) {
shell.openExternal("https://github.com/bitburner-official/bitburner-vscode");
}
});
},
},
],
},
{
label: "Zoom",
submenu: [

View File

@@ -1,11 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { app, ipcMain } = require("electron");
const zlib = require("zlib");
const path = require("path");
const fs = require("fs/promises");
const { promisify } = require("util");
const gzip = promisify(zlib.gzip);
const gunzip = promisify(zlib.gunzip);
const greenworks = require("./greenworks");
const log = require("electron-log");

View File

@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { dialog, shell } = require("electron");
const { dialog } = require("electron");
const log = require("electron-log");
const Store = require("electron-store");

View File

@@ -5,13 +5,10 @@ import { Terminal } from "./Terminal";
import { SnackbarEvents } from "./ui/React/Snackbar";
import { ToastVariant } from "@enums";
import { IReturnStatus, SaveData } from "./types";
import { GetServer } from "./Server/AllServers";
import { ImportPlayerData, ElectronGameData, saveObject } from "./SaveObject";
import { exportScripts } from "./Terminal/commands/download";
import { CONSTANTS } from "./Constants";
import { commitHash } from "./utils/helpers/commitHash";
import { resolveFilePath } from "./Paths/FilePath";
import { hasScriptExtension } from "./Paths/ScriptFilePath";
import { handleGetSaveDataInfoError } from "./utils/ErrorHandler";
interface IReturnWebStatus extends IReturnStatus {
@@ -49,55 +46,12 @@ export function initElectron(): void {
if (userAgent.includes(" electron/")) {
// Electron-specific code
document.achievements = [];
initWebserver();
initAppNotifier();
initSaveFunctions();
initElectronBridge();
}
}
function initWebserver(): void {
document.getFiles = function (): IReturnWebStatus {
const home = GetServer("home");
if (home === null) return { res: false, msg: "Home server does not exist." };
return {
res: true,
data: {
files: [...home.scripts.values()].map((script) => ({
filename: script.filename,
code: script.code,
ramUsage: script.ramUsage,
})),
},
};
};
document.deleteFile = function (filename: string): IReturnWebStatus {
const path = resolveFilePath(filename);
if (!path) return { res: false, msg: "Invalid file path." };
const home = GetServer("home");
if (!home) return { res: false, msg: "Home server does not exist." };
return home.removeFile(path);
};
document.saveFile = function (filename: string, code: string): IReturnWebStatus {
const path = resolveFilePath(filename);
if (!path) return { res: false, msg: "Invalid file path." };
if (!hasScriptExtension(path)) return { res: false, msg: "Invalid file extension: must be a script" };
code = decodeURIComponent(escape(atob(code)));
const home = GetServer("home");
if (!home) return { res: false, msg: "Home server does not exist." };
const { overwritten } = home.writeToScriptFile(path, code);
const script = home.scripts.get(path);
if (!script) return { res: false, msg: "Somehow failed to get script after writing it. This is a bug." };
const ramUsage = script.getRamUsage(home.scripts);
return { res: true, data: { overwritten, ramUsage } };
};
}
// Expose certain alert functions to allow the wrapper to sends message to the game
function initAppNotifier(): void {
const funcs = {