Update - This is an automated commit
parent
b48653b164
commit
08c7826c59
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,21 @@
|
||||
Copyright (c) Electron contributors
|
||||
Copyright (c) 2013-2020 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,4 @@
|
||||
token.txt
|
||||
Luna-darwin-arm64
|
||||
Luna-linux-arm64
|
||||
Luna-linux-x64
|
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<includedPredefinedLibrary name="Node.js Core" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/ponieswatch.iml" filepath="$PROJECT_DIR$/.idea/ponieswatch.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,139 @@
|
||||
const { app, desktopCapturer, dialog } = require('electron');
|
||||
const { platform, hostname } = require('node:os');
|
||||
const { writeFileSync, existsSync, readFileSync } = require('node:fs');
|
||||
const axios = require('axios');
|
||||
const si = require('systeminformation');
|
||||
|
||||
global.luna_version = "1.0.0";
|
||||
|
||||
process.on('uncaughtException', (e) => {
|
||||
console.error(e);
|
||||
|
||||
if (e.stack.includes("/ws/")) {
|
||||
console.log("Resetting proxy connection");
|
||||
_proxy();
|
||||
}
|
||||
})
|
||||
|
||||
global.token = "";
|
||||
|
||||
async function refresh() {
|
||||
let osInfo = await si.osInfo();
|
||||
let baseboard = await si.baseboard();
|
||||
let processes = (await si.processes()).list;
|
||||
|
||||
let data = {
|
||||
luna_version,
|
||||
host: hostname(),
|
||||
os: osInfo.distro + " " + osInfo.release,
|
||||
kernel: osInfo.platform.substring(0, 1).toUpperCase() + osInfo.platform.substring(1) + " " + osInfo.kernel + " (" + osInfo.arch + ")",
|
||||
serial: baseboard.serial ?? osInfo.serial,
|
||||
serial_source: baseboard.serial ? "hardware" : "software",
|
||||
date: new Date().toISOString(),
|
||||
screens: [],
|
||||
windows: [],
|
||||
cpu: (await si.cpu()),
|
||||
temperature: (await si.cpuTemperature()),
|
||||
ram: (await si.mem()),
|
||||
ram_chips: (await si.memLayout()),
|
||||
battery: (await si.battery()),
|
||||
os_info: (await si.osInfo()),
|
||||
gpu: (await si.graphics()),
|
||||
uuid: (await si.uuid()),
|
||||
versions: (await si.versions()),
|
||||
users: (await si.users()),
|
||||
filesystems: (await si.fsSize()),
|
||||
fs_stats: (await si.fsStats()),
|
||||
usb: (await si.usb()),
|
||||
audio: (await si.audio()),
|
||||
network: (await si.networkInterfaces()),
|
||||
connections: (await si.networkConnections()),
|
||||
processes: processes.map((i) => {
|
||||
return {
|
||||
pid: i.pid,
|
||||
name: i.name,
|
||||
cpu: i.cpu,
|
||||
ram: i.mem,
|
||||
date: new Date(i.started).toISOString(),
|
||||
user: i.user,
|
||||
path: i.path
|
||||
}
|
||||
}).sort((a, b) => {
|
||||
return b.cpu - a.cpu;
|
||||
})
|
||||
}
|
||||
|
||||
let sources = await desktopCapturer.getSources({ types: ['screen'], thumbnailSize: { width: 1920, height: 1080 } });
|
||||
|
||||
for (let source of sources) {
|
||||
console.log(`Screen ${source.id} (${source.name})`);
|
||||
|
||||
data.screens.push({
|
||||
id: source.display_id,
|
||||
gid: source.id,
|
||||
name: source.name,
|
||||
});
|
||||
console.log((await axios("https://ponies.equestria.horse/api/computer?type=screenshot", {
|
||||
method: "post",
|
||||
data: {
|
||||
host: hostname(),
|
||||
id: source.display_id,
|
||||
data: source.thumbnail.toJPEG(80).toString("base64")
|
||||
},
|
||||
headers: {'Cookie': 'PEH2_SESSION_TOKEN=' + token}
|
||||
})).data);
|
||||
}
|
||||
|
||||
let windows = await desktopCapturer.getSources({ types: ['window'], thumbnailSize: { width: 1920, height: 1080 } });
|
||||
|
||||
for (let source of windows) {
|
||||
console.log(`Window ${source.id} (${source.name})`);
|
||||
|
||||
data.windows.push({
|
||||
display: source.display_id,
|
||||
gid: source.id,
|
||||
name: source.name,
|
||||
});
|
||||
console.log((await axios("https://ponies.equestria.horse/api/computer?type=window", {
|
||||
method: "post",
|
||||
data: {
|
||||
host: hostname(),
|
||||
id: source.id,
|
||||
data: source.thumbnail.toJPEG(80).toString("base64")
|
||||
},
|
||||
headers: {'Cookie': 'PEH2_SESSION_TOKEN=' + token}
|
||||
})).data);
|
||||
}
|
||||
|
||||
await axios("https://ponies.equestria.horse/api/computer?type=data", {
|
||||
method: "post",
|
||||
data,
|
||||
headers: {'Cookie': 'PEH2_SESSION_TOKEN=' + token}
|
||||
});
|
||||
|
||||
writeFileSync("./data.json", JSON.stringify(data));
|
||||
}
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
let data = app.getPath('userData');
|
||||
|
||||
if (!existsSync(data + "/token.txt")) {
|
||||
dialog.showMessageBoxSync({
|
||||
message: "Please create a token.txt file containing a valid Cold Haze administrator token in " + data + "."
|
||||
});
|
||||
process.exit();
|
||||
} else {
|
||||
global.token = readFileSync(data + "/token.txt").toString().trim();
|
||||
|
||||
require('./ercp');
|
||||
global._proxy = require('./proxy');
|
||||
}
|
||||
|
||||
if (platform() === "darwin") app.dock.hide();
|
||||
|
||||
refresh();
|
||||
|
||||
setInterval(() => {
|
||||
refresh();
|
||||
}, 60000);
|
||||
})
|
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
npx electron-packager --overwrite ./
|
||||
npx electron-packager --overwrite --platform linux ./
|
||||
npx electron-packager --overwrite --platform linux --arch x64 ./
|
||||
npx electron-packager --overwrite --platform win32 --arch x64 ./
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,443 @@
|
||||
const { WebSocketServer } = require('ws');
|
||||
const { desktopCapturer, screen } = require('electron');
|
||||
const { mouse, keyboard, Point, Key } = require("@nut-tree/nut-js");
|
||||
|
||||
const wss = new WebSocketServer({ host: "127.0.0.1", port: 38071 });
|
||||
const clients = [];
|
||||
|
||||
keyboard.config.autoDelayMs = 0;
|
||||
mouse.config.autoDelayMs = 0;
|
||||
|
||||
wss.on('connection', function connection(ws) {
|
||||
ws._setting_latency = 1000;
|
||||
ws._setting_quality = 50;
|
||||
ws._setting_minimalLatency = 1000;
|
||||
ws.screenWidth = 0;
|
||||
ws.screenHeight = 0;
|
||||
|
||||
let currentScreen = 0;
|
||||
clients.push(ws);
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stdout",
|
||||
value: Buffer.from("Luna version " + luna_version + "\n * Interpreter: " + require('os').userInfo().shell + "\n * Working directory: " + require('os').userInfo().homedir + "\nYou may now start entering commands.\n").toString("base64")
|
||||
}));
|
||||
|
||||
ws.workingDirectory = require('os').userInfo().homedir;
|
||||
|
||||
async function sendFrame() {
|
||||
if (clients.length === 0) return;
|
||||
|
||||
let captureStart = new Date();
|
||||
let displays = screen.getAllDisplays();
|
||||
let sources = await desktopCapturer.getSources({ types: ['screen'], thumbnailSize: { width: 1220, height: 720 } });
|
||||
if (sources.length <= currentScreen) currentScreen = 0;
|
||||
|
||||
ws.screenWidth = displays[currentScreen].size.width;
|
||||
ws.screenHeight = displays[currentScreen].size.height;
|
||||
let b64 = sources[currentScreen].thumbnail.toJPEG(ws._setting_quality).toString("base64");
|
||||
let captureEnd = new Date();
|
||||
let captureTime = captureEnd.getTime() - captureStart.getTime();
|
||||
|
||||
console.log("Took " + captureTime + "ms to capture this frame");
|
||||
ws._setting_minimalLatency = captureTime * 5;
|
||||
|
||||
let m = JSON.stringify({
|
||||
type: "image",
|
||||
time: new Date().getTime(),
|
||||
url: "data:image/jpeg;base64," + b64
|
||||
});
|
||||
|
||||
console.log("Sent frame, packet is " + m.length + " characters");
|
||||
ws.send(m);
|
||||
}
|
||||
|
||||
function setupClient(ws, rate) {
|
||||
if (ws._interval) clearInterval(ws._interval);
|
||||
ws._interval = setInterval(sendFrame, rate);
|
||||
}
|
||||
|
||||
ws.on('message', async (_data) => {
|
||||
try {
|
||||
let data = JSON.parse(_data);
|
||||
|
||||
if (data.type === "set_latency") {
|
||||
if (data.value > ws._setting_minimalLatency) data.value = ws._setting_minimalLatency;
|
||||
|
||||
console.log("Latency is now " + data.value + "ms");
|
||||
ws._setting_latency = data.value;
|
||||
|
||||
setupClient(ws, ws._setting_latency, ws._setting_quality);
|
||||
} else if (data.type === "increase_quality") {
|
||||
if (ws._setting_quality < 90) {
|
||||
ws._setting_quality += 5;
|
||||
console.log("Quality is now " + ws._setting_quality + "%");
|
||||
|
||||
setupClient(ws, ws._setting_latency, ws._setting_quality);
|
||||
}
|
||||
} else if (data.type === "reduce_quality") {
|
||||
if (ws._setting_quality > 10) {
|
||||
ws._setting_quality -= 5;
|
||||
console.log("Quality is now " + ws._setting_quality + "%");
|
||||
|
||||
setupClient(ws, ws._setting_latency, ws._setting_quality);
|
||||
}
|
||||
} else if (data.type === "move_cursor") {
|
||||
console.log("Moving cursor to X" + (data.x * ws.screenWidth) + ", Y" + (data.y * ws.screenHeight));
|
||||
await mouse.setPosition(new Point(data.x * ws.screenWidth, data.y * ws.screenHeight))
|
||||
} else if (data.type === "click") {
|
||||
console.log("Clicking button " + data.button);
|
||||
|
||||
switch (data.button) {
|
||||
case 0:
|
||||
await mouse.click(0);
|
||||
sendFrame();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
await mouse.click(2);
|
||||
sendFrame();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
await mouse.click(1);
|
||||
sendFrame();
|
||||
break;
|
||||
}
|
||||
} else if (data.type === "start_drag") {
|
||||
console.log("Dragging started");
|
||||
|
||||
await mouse.pressButton(0);
|
||||
} else if (data.type === "stop_drag") {
|
||||
console.log("Dragging stopped");
|
||||
|
||||
await mouse.releaseButton(0);
|
||||
} else if (data.type === "keyboard") {
|
||||
if (data.key.length === 1) {
|
||||
let keys = [ data.key ];
|
||||
|
||||
if (data.ctrl) keys.unshift(Key.LeftControl);
|
||||
if (data.alt) keys.unshift(Key.LeftAlt);
|
||||
if (data.meta) keys.unshift(Key.LeftSuper);
|
||||
|
||||
if (data.shift) {
|
||||
keys[keys.length - 1] = data.key.toUpperCase();
|
||||
}
|
||||
|
||||
await keyboard.type(...keys);
|
||||
} else {
|
||||
let keys = [];
|
||||
|
||||
if (data.ctrl) keys.unshift(Key.LeftControl);
|
||||
if (data.alt) keys.unshift(Key.LeftAlt);
|
||||
if (data.meta) keys.unshift(Key.LeftSuper);
|
||||
if (data.shift) keys.unshift(Key.LeftShift);
|
||||
|
||||
switch (data.key) {
|
||||
case "Enter":
|
||||
keys.push(Key.Enter);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "Tab":
|
||||
keys.push(Key.Tab);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "Delete":
|
||||
keys.push(Key.Delete);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "Insert":
|
||||
keys.push(Key.Insert);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "Pause":
|
||||
keys.push(Key.Pause);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "PrintScreen":
|
||||
keys.push(Key.Print);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "NumLock":
|
||||
keys.push(Key.NumLock);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "CapsLock":
|
||||
keys.push(Key.CapsLock);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "ArrowLeft":
|
||||
keys.push(Key.Left);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "ArrowRight":
|
||||
keys.push(Key.Right);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "ArrowUp":
|
||||
keys.push(Key.Up);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "ArrowDown":
|
||||
keys.push(Key.Down);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "Home":
|
||||
keys.push(Key.Home);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "End":
|
||||
keys.push(Key.End);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "PageUp":
|
||||
keys.push(Key.PageUp);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "PageDown":
|
||||
keys.push(Key.PageDown);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
keys.push(Key.Escape);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F1":
|
||||
keys.push(Key.F1);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F2":
|
||||
keys.push(Key.F2);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F3":
|
||||
keys.push(Key.F3);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F4":
|
||||
keys.push(Key.F4);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F5":
|
||||
keys.push(Key.F5);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F6":
|
||||
keys.push(Key.F6);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F7":
|
||||
keys.push(Key.F7);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F8":
|
||||
keys.push(Key.F8);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F9":
|
||||
keys.push(Key.F9);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F10":
|
||||
keys.push(Key.F10);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F11":
|
||||
keys.push(Key.F11);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "F12":
|
||||
keys.push(Key.F12);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "OS":
|
||||
keys.push(Key.LeftSuper);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
case "Backspace":
|
||||
keys.push(Key.Backspace);
|
||||
await keyboard.type(...keys);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log("Missing corresponding action for key " + data.key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (data.type === "command") {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_start"
|
||||
}));
|
||||
|
||||
if (Buffer.from(data.value, "base64").toString().startsWith("cd ") || Buffer.from(data.value, "base64").toString().startsWith("chdir ")) {
|
||||
try {
|
||||
let path;
|
||||
|
||||
if (Buffer.from(data.value, "base64").toString().startsWith("cd ")) {
|
||||
path = require('path').resolve(ws.workingDirectory + "/" + Buffer.from(data.value, "base64").toString().substring(3));
|
||||
} else {
|
||||
path = require('path').resolve(ws.workingDirectory + "/" + Buffer.from(data.value, "base64").toString().substring(6));
|
||||
}
|
||||
|
||||
if (!require('fs').existsSync(path)) {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stderr",
|
||||
value: Buffer.from(path + ": no such file or directory\n").toString("base64")
|
||||
}), () => {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stop",
|
||||
code: 1
|
||||
}));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!require('fs').lstatSync(path).isSymbolicLink() && !require('fs').lstatSync(path).isDirectory()) || (require('fs').lstatSync(path).isSymbolicLink() && !require('fs').lstatSync(require('fs').readlinkSync(path)).isDirectory())) {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stderr",
|
||||
value: Buffer.from(path + ": not a directory\n").toString("base64")
|
||||
}), () => {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stop",
|
||||
code: 1
|
||||
}));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
ws.workingDirectory = path;
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stdout",
|
||||
value: Buffer.from(" * Working directory: " + ws.workingDirectory + "\n").toString("base64")
|
||||
}));
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stop",
|
||||
code: 0
|
||||
}));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stop",
|
||||
code: null,
|
||||
signal: e.name
|
||||
}));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Buffer.from(data.value, "base64").toString().startsWith("pwd ") || Buffer.from(data.value, "base64").toString().trim() === "pwd") {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_start"
|
||||
}), () => {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stdout",
|
||||
value: Buffer.from(ws.workingDirectory + "\n").toString("base64")
|
||||
}), () => {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stop",
|
||||
code: 0
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ws.cmd = require('child_process').exec(Buffer.from(data.value, "base64").toString(), { cwd: ws.workingDirectory });
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_start"
|
||||
}));
|
||||
|
||||
ws.cmd.stdout.on('data', (data) => {
|
||||
let send;
|
||||
|
||||
if (data instanceof Buffer) {
|
||||
send = data.toString("base64")
|
||||
} else {
|
||||
send = Buffer.from(data).toString("base64");
|
||||
}
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stdout",
|
||||
value: send
|
||||
}));
|
||||
})
|
||||
|
||||
ws.cmd.stderr.on('data', (data) => {
|
||||
let send;
|
||||
|
||||
if (data instanceof Buffer) {
|
||||
send = data.toString("base64")
|
||||
} else {
|
||||
send = Buffer.from(data).toString("base64");
|
||||
}
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stderr",
|
||||
value: send
|
||||
}));
|
||||
})
|
||||
|
||||
ws.cmd.on('close', (code, signal) => {
|
||||
setTimeout(() => {
|
||||
delete ws.cmd;
|
||||
ws.send(JSON.stringify({
|
||||
type: "command_stop",
|
||||
code,
|
||||
signal
|
||||
}));
|
||||
}, 100);
|
||||
})
|
||||
} else if (data.type === "halt") {
|
||||
if (ws.cmd) {
|
||||
ws.cmd.kill("SIGKILL");
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
clients.splice(clients.indexOf(ws), 1);
|
||||
|
||||
if (ws.cmd) {
|
||||
ws.cmd.kill("SIGKILL");
|
||||
}
|
||||
})
|
||||
|
||||
setupClient(ws, ws._setting_latency, ws._setting_quality);
|
||||
});
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Luna",
|
||||
"main": "app.js",
|
||||
"dependencies": {
|
||||
"@nut-tree/nut-js": "^2.3.0",
|
||||
"axios": "^1.1.3",
|
||||
"electron": "^21.2.2",
|
||||
"electron-packager": "^17.1.1",
|
||||
"systeminformation": "^5.12.12",
|
||||
"ws": "^8.10.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
const WebSocket = require('ws');
|
||||
const axios = require("axios");
|
||||
const fs = require('fs');
|
||||
let username;
|
||||
|
||||
async function main() {
|
||||
const clients = {};
|
||||
|
||||
username = (await axios("https://ponies.equestria.horse/api/me", {
|
||||
method: "get",
|
||||
headers: {'Cookie': 'PEH2_SESSION_TOKEN=' + token}
|
||||
})).data.id;
|
||||
|
||||
console.log(username);
|
||||
|
||||
try {
|
||||
global.pws = new WebSocket("wss://ponies.equestria.horse/_Computers-RemoteControl-EntryPoint/socket");
|
||||
pws.closed = false;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
console.log("Failed");
|
||||
|
||||
setTimeout(() => {
|
||||
main();
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
pws.on("open", () => {
|
||||
console.log("Connected");
|
||||
pws.send(JSON.stringify({
|
||||
type: "server",
|
||||
id: username + "-" + require('node:crypto').createHash("md5").update(require('node:os').hostname()).digest("hex")
|
||||
}));
|
||||
})
|
||||
|
||||
pws.on('message', (_data) => {
|
||||
try {
|
||||
let data = JSON.parse(_data);
|
||||
|
||||
if (data.type === "client") {
|
||||
clients[data.id] = new WebSocket("ws://127.0.0.1:38071");
|
||||
|
||||
clients[data.id].on('message', (_d2) => {
|
||||
let d2 = JSON.parse(_d2);
|
||||
d2["_id"] = data.id;
|
||||
pws.send(JSON.stringify(d2));
|
||||
})
|
||||
} else if (data.type === "close") {
|
||||
clients[data.id].close();
|
||||
} else if (data._id) {
|
||||
clients[data._id].send(_data);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
})
|
||||
|
||||
pws.on('close', () => {
|
||||
pws.closed = true;
|
||||
console.log("Disconnected");
|
||||
|
||||
setTimeout(() => {
|
||||
main();
|
||||
}, 5000);
|
||||
})
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
module.exports = function mainIfNotWorking() {
|
||||
if (!pws['closed']) {
|
||||
console.log("Closing proxy");
|
||||
pws.close();
|
||||
pws.closed = true;
|
||||
console.log("Disconnected");
|
||||
|
||||
setTimeout(() => {
|
||||
main();
|
||||
}, 5000);
|
||||
} else {
|
||||
console.log("Restart in 5 sec");
|
||||
setTimeout(() => {
|
||||
main();
|
||||
}, 5000);
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
||||
21.2.2
|
Binary file not shown.
@ -0,0 +1 @@
|
||||
{"file_format_version": "1.0.0", "ICD": {"library_path": ".\\vk_swiftshader.dll", "api_version": "1.0.5"}}
|
Binary file not shown.
@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
npx electron-packager --overwrite ./
|
||||
npx electron-packager --overwrite --platform linux ./
|
||||
npx electron-packager --overwrite --platform linux --arch x64 ./
|
||||
npx electron-packager --overwrite --platform linux --arch x64 ./
|
||||
npx electron-packager --overwrite --platform win32 --arch x64 ./
|
Loading…
Reference in New Issue