Update - This is an automated commit

mane
Mia Raindrops 3 months ago
parent b48653b164
commit 08c7826c59
Signed by: Mia Raindrops
GPG Key ID: EFBDC68435A574B7

5
.gitignore vendored

@ -2,3 +2,8 @@ token.txt
Luna-darwin-arm64
Luna-linux-arm64
Luna-linux-x64
Luna-win32-x64
Luna-darwin-arm64*
Luna-linux-arm64*
Luna-linux-x64*
Luna-win32-x64*

@ -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.

@ -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 @@
{"file_format_version": "1.0.0", "ICD": {"library_path": ".\\vk_swiftshader.dll", "api_version": "1.0.5"}}

Binary file not shown.

@ -1,4 +1,4 @@
const { app, desktopCapturer } = require('electron');
const { app, desktopCapturer, dialog } = require('electron');
const { platform, hostname } = require('node:os');
const { writeFileSync, existsSync, readFileSync } = require('node:fs');
const axios = require('axios');
@ -15,7 +15,7 @@ process.on('uncaughtException', (e) => {
}
})
let token;
global.token = "";
async function refresh() {
let osInfo = await si.osInfo();
@ -115,11 +115,15 @@ async function refresh() {
}
app.whenReady().then(async () => {
if (!existsSync("./token.txt")) {
console.log("Please create a token.txt file containing a valid Cold Haze administrator token.");
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 {
token = readFileSync("./token.txt").toString().trim();
global.token = readFileSync(data + "/token.txt").toString().trim();
require('./ercp');
global._proxy = require('./proxy');

@ -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 ./

@ -8,7 +8,7 @@ async function main() {
username = (await axios("https://ponies.equestria.horse/api/me", {
method: "get",
headers: {'Cookie': 'PEH2_SESSION_TOKEN=' + fs.readFileSync("./token.txt").toString().trim()}
headers: {'Cookie': 'PEH2_SESSION_TOKEN=' + token}
})).data.id;
console.log(username);

Loading…
Cancel
Save