Page MenuHomeSealhub

No OneTemporary

diff --git a/android/code/index.mjs b/android/code/index.mjs
index 11531b5..3fc1ba3 100644
--- a/android/code/index.mjs
+++ b/android/code/index.mjs
@@ -1,60 +1,64 @@
import { WebSocketServer } from "ws";
import child_process from "child_process";
import fs from "fs";
-import { send_notification } from "./notifications.mjs"
+import { send_notification } from "./notifications.mjs";
async function spawnPromise(program, args) {
return new Promise((resolve, reject) => {
let output = "";
const process = child_process.spawn(program, args);
- process.stdout.on('data', (data) => {
+ process.stdout.on("data", (data) => {
output += data;
});
- process.stderr.on('data', (data) => {
+ process.stderr.on("data", (data) => {
output += data;
});
process.on("close", (code) => {
- resolve({output, code});
+ resolve({ output, code });
});
});
}
const wss = new WebSocketServer({ port: 3000 });
//maybe check output of child processes and send errors in some way
wss.on("connection", (ws) => {
ws.on("message", async (dataBuf) => {
let data = dataBuf.toString();
if (data === "screenshot") {
await spawnPromise("bash", ["/conf/screenshot.sh"]);
ws.send(fs.readFileSync("/screenshot.png"));
} else if (data.includes("touch")) {
const dataSplit = data.split(" ");
await spawnPromise("bash", [
"/conf/touch.sh",
dataSplit[1],
dataSplit[2],
]);
} else if (data === "back") {
await spawnPromise("bash", ["/conf/back.sh"]);
} else if (data === "home") {
await spawnPromise("bash", ["/conf/home.sh"]);
} else if (data === "install") {
const res = await spawnPromise("bash", ["/conf/install.sh"]);
- send_notification(res.code === 0, "Installing the application", res.output);
+ send_notification(
+ res.code === 0,
+ "Installing the application",
+ res.output
+ );
} else if (data.includes("drag")) {
const dataSplit = data.split(" ");
await spawnPromise("bash", [
"/conf/drag.sh",
dataSplit[1],
dataSplit[2],
dataSplit[3],
dataSplit[4],
]);
}
});
ws.on("close", (_) => {
ws.close();
});
});
diff --git a/android/code/notifications.mjs b/android/code/notifications.mjs
index 200d5b2..01ce9a1 100644
--- a/android/code/notifications.mjs
+++ b/android/code/notifications.mjs
@@ -1,36 +1,41 @@
import { WebSocket } from "ws";
import { WebSocketServer } from "ws";
const notification_proxy = new WebSocketServer({ port: 3001 });
let notification_subs = [];
-notification_proxy.on('connection', (ws) => {
+notification_proxy.on("connection", (ws) => {
notification_subs.push(ws);
});
-export function send_notification(is_ok, context, message)
-{
+export function send_notification(is_ok, context, message) {
let updated_subs = [];
if (notification_subs.length === 0) {
console.log("WARNING: Got a notification, but nobody is subscribed");
}
for (const sub of notification_subs) {
if (sub.readyState == WebSocket.CONNECTING) {
- console.log("WARNING: Unable to forward a notification to client that is still connecting");
+ console.log(
+ "WARNING: Unable to forward a notification to client that is still connecting"
+ );
updated_subs.push(sub);
} else {
try {
- sub.send(JSON.stringify({
- is_ok,
- context,
- message
- }));
+ sub.send(
+ JSON.stringify({
+ is_ok,
+ context,
+ message,
+ })
+ );
updated_subs.push(sub);
} catch {
sub.close();
- console.log("WARNING: Fail to send a notification, closing the connection");
+ console.log(
+ "WARNING: Fail to send a notification, closing the connection"
+ );
}
}
}
}
diff --git a/http_server/code/index.mjs b/http_server/code/index.mjs
index 1e5dc42..26c6d4a 100644
--- a/http_server/code/index.mjs
+++ b/http_server/code/index.mjs
@@ -1,113 +1,112 @@
import express from "express";
import { readFile } from "node:fs/promises";
import {
guardedScreenshot,
android_websocket,
waitFullBoot,
} from "./screenshot.mjs";
-import { execSync } from 'node:child_process';
+import { execSync } from "node:child_process";
-import fileUpload from 'express-fileupload';
+import fileUpload from "express-fileupload";
const device_size_x = 320;
const device_size_y = 640;
const app = express();
app.use(express.urlencoded({ extended: false }));
-app.use(express.static('/code/dist'))
+app.use(express.static("/code/dist"));
console.log("Waiting for full boot...");
await waitFullBoot();
console.log("Boot detected! activating endpoints");
//GET
app.get("/favicon.ico", function (req, res) {
res.sendFile("/code/favicon.ico");
});
app.get("/htmx.js", function (req, res) {
res.sendFile("/code/node_modules/htmx.org/dist/htmx.min.js");
});
app.get("/trafficLog", async function (req, res) {
res.sendFile("/log/trafficLog");
});
app.get("/screen", async function (req, res) {
await guardedScreenshot();
res.sendFile("/code/screenshot.png");
});
app.get("/", async function (req, res) {
let fileData = (await readFile("/code/index.html")).toString();
fileData = fileData.replace(
"___screenshotDelayMs___",
process.env.screenshotDelayMs
);
res.setHeader("Content-Type", "text/html");
res.setHeader("Content-Disposition", "inline");
res.send(fileData);
});
//POST
app.post("/back", function (req, res) {
android_websocket.send(`back`);
res.sendStatus(200);
});
// default options
app.use(fileUpload());
-app.post('/upload_apk', async function (req, res) {
+app.post("/upload_apk", async function (req, res) {
if (!req.files || Object.keys(req.files).length === 0) {
- return res.status(400).send('No files were uploaded.');
+ return res.status(400).send("No files were uploaded.");
}
execSync("rm -rf /shared_buffer/*");
if (Array.isArray(req.files.app)) {
for (const [idx, file] of req.files.app.entries()) {
- let uploadPath = '/shared_buffer/app' + idx + '.apk';
+ let uploadPath = "/shared_buffer/app" + idx + ".apk";
await file.mv(uploadPath);
}
} else {
- let uploadPath = '/shared_buffer/app' + 0 + '.apk';
+ let uploadPath = "/shared_buffer/app" + 0 + ".apk";
await req.files.app.mv(uploadPath);
}
android_websocket.send(`install`);
- res.send('Files uploaded!');
-})
+ res.send("Files uploaded!");
+});
app.post("/home", function (req, res) {
android_websocket.send(`home`);
res.sendStatus(200);
});
app.post("/touch", function (req, res) {
const x = parseInt(req.body.x);
const y = parseInt(req.body.y);
if (isNaN(x) || isNaN(y) || x > device_size_x || y > device_size_y) {
res.send(
`the query params must be x <= ${device_size_x}, y <= ${device_size_y}\n`
);
} else {
android_websocket.send(`touch ${x} ${y}`);
res.sendStatus(200);
}
});
app.post("/drag", function (req, res) {
const body = req.body;
const startX = Number(body.startX);
const startY = Number(body.startY);
const endX = Number(body.endX);
const endY = Number(body.endY);
android_websocket.send(`drag ${startX} ${startY} ${endX} ${endY}`);
res.sendStatus(200);
});
app.listen(8080, () => console.log("Listening in port 8080"));
-
diff --git a/http_server/code/screenshot.mjs b/http_server/code/screenshot.mjs
index 199d7ae..4caac92 100644
--- a/http_server/code/screenshot.mjs
+++ b/http_server/code/screenshot.mjs
@@ -1,69 +1,68 @@
import fs from "fs";
import { sleep } from "./utils.mjs";
import { WebSocket } from "ws";
export const android_websocket = new WebSocket("ws://android:3000");
let doneWrite = 0;
let screenshotPromise = null;
async function screenshot() {
const time_start = Date.now();
let retries = 0;
while (android_websocket.readyState != WebSocket.OPEN) {
await sleep(15);
retries++;
- if (retries > 50)
- {
+ if (retries > 50) {
console.error("Screenshot ws timeout");
doneWrite = 0;
screenshotPromise = null;
- return ;
+ return;
}
}
android_websocket.send("screenshot");
while (!doneWrite) {
await sleep(15);
if (Date.now() - time_start > 2000) {
console.error("Screenshot timed out after 2s");
break; // timeout
}
}
doneWrite = 0;
screenshotPromise = null;
}
export async function guardedScreenshot() {
if (!screenshotPromise) {
screenshotPromise = screenshot();
} else {
console.log("ongoing screenshot promise not taking a new one");
}
return screenshotPromise;
}
export async function waitFullBoot() {
var start = performance.now();
var counter = 0;
//will timeout after 10 min
while (performance.now() - start < 600 * 1000) {
var before = performance.now();
await screenshot();
var after = performance.now();
if (after - before < process.env.screenshotDelayMs) counter++;
else counter = 0;
if (counter === 10) return;
}
throw new Error("wait for screenshot time to be less than 0.5s timed out");
}
android_websocket.on("message", (dataBuf) => {
let fd;
fd = fs.openSync("/code/screenshot.png", "w");
fs.writeSync(fd, dataBuf);
fs.close(fd);
doneWrite = 1;
});
diff --git a/http_server/code/src/notifications.jsx b/http_server/code/src/notifications.jsx
index 9ba6110..741523f 100644
--- a/http_server/code/src/notifications.jsx
+++ b/http_server/code/src/notifications.jsx
@@ -1,69 +1,68 @@
import { render, Component } from "preact";
-import { useState } from "preact/hooks";
function rand_num() {
return Math.floor(Math.random() * Number.MAX_VALUE);
}
class Notifications extends Component {
constructor() {
super();
this.state = { notifications: [] };
}
- remove_notification (id) {
+ remove_notification(id) {
const newNotifications = this.state.notifications.filter(
(notification) => notification.id !== id
);
this.setState({ notifications: newNotifications });
- };
+ }
componentDidMount() {
// This should also be dynamic
this.connection = new WebSocket("ws://127.0.0.1:3001");
this.connection.onmessage = (msg) => {
let new_id = rand_num();
this.setState({
notifications: [
{ id: new_id, notification: JSON.parse(msg.data) },
...this.state.notifications,
],
});
// a 10 sec timeout
setTimeout(() => {
- this.remove_notification(new_id)
- }, 10000)
+ this.remove_notification(new_id);
+ }, 10000);
};
}
render() {
console.log("Render", this.state.notifications);
return this.state.notifications.map(({ id, notification }) => (
<div
onClick={() => this.remove_notification(id)}
style={`
background-color: ${notification.is_ok ? "#66ff99" : "#ff5c33"};
border-radius: 5px;
border-width: 2px;
border-style: solid;
border-color: ${notification.is_ok ? "#369648" : "#a23915"};
padding: 5px;
margin-top: 2px;
margin-bottom: 2px;
`}
>
<div>
<b>{notification.context}</b>
</div>
<div>
{notification.message.split("\n").map((line) => (
<p>{line}</p>
))}
</div>
</div>
));
}
}
render(<Notifications />, document.getElementById("notifications"));

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 8, 12:14 (11 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1034567
Default Alt Text
(10 KB)

Event Timeline