import child_process from "child_process"; import fs from "fs"; import { Server } from "socket.io"; async function spawnPromise(program, args) { return new Promise((resolve, _reject) => { let output = ""; const process = child_process.spawn(program, args); process.stdout.on("data", (data) => { output += data; }); process.stderr.on("data", (data) => { output += data; }); process.on("close", (code) => { resolve({ output, code }); }); }); } let io = new Server(); async function send_private_data() { let adid = await spawnPromise("bash", ["/conf/get_adid.sh"]) adid = adid.output; let gps_coords = await spawnPromise("bash", ["/conf/get_location.sh"]) gps_coords = gps_coords.output; gps_coords = gps_coords.trim().split(','); io.emit("private_info", {adid, latitude: gps_coords[0], longitude: gps_coords[1]}) } function send_notification(socket, is_ok, context, message) { socket.emit("notification", { is_ok, context, message, }); } let screenshot_in_flight = false; let gps_setting_in_progress = false; //maybe check output of child processes and send errors in some way io.on("connection", (socket) => { socket.onAny((ev, ...args) => { console.log("server got: ", ev, ...args); }); socket.on("screenshot", async () => { if (screenshot_in_flight) return; screenshot_in_flight = true; let screen; try { screen = await fetch("http://localhost:9987/v2/uiDevice/screenshot"); } catch(err) { console.error("Failed to get the screenshot from culebra, the emulator probably died", err); screenshot_in_flight = false; return; } let body = await screen.bytes(); socket.emit("screenshot_data", body); screenshot_in_flight = false; }); socket.on("private_info_req", async () => { await send_private_data(); }) socket.on("reset_adid", async () => { await spawnPromise("bash", ["/conf/reset_adid.sh"]); await send_private_data(); }) socket.on("back", async () => { if (gps_setting_in_progress) { send_notification(socket, false, "Interactions not allowed when setting gps coordinates", ""); send_notification(socket, false, "Back", ""); return ; } await spawnPromise("bash", ["/conf/back.sh"]); }); socket.on("home", async () => { if (gps_setting_in_progress) { send_notification(socket, false, "Interactions not allowed when setting gps coordinates", ""); return ; } await spawnPromise("bash", ["/conf/home.sh"]); }); socket.on("install", async () => { const res = await spawnPromise("bash", ["/conf/install.sh"]); send_notification( socket, res.code === 0, "Installing the application", res.output ); }); // drag handles both drag and click socket.on("motionevent", async (data) => { if (gps_setting_in_progress) { send_notification(socket, false, "Interactions not allowed when setting gps coordinates", ""); return ; } await spawnPromise("bash", [ "/conf/motionevent.sh", data.motionType, data.x + "", data.y + "" ]); }); // drag handles both drag and click socket.on("drag", async (data) => { if (gps_setting_in_progress) { send_notification(socket, false, "Interactions not allowed when setting gps coordinates", ""); return ; } await spawnPromise("bash", [ "/conf/drag.sh", data.startX + "", data.startY + "", data.endX + "", data.endY + "", data.dragTime + "", ]); }); socket.on("key", async (data) => { if (gps_setting_in_progress) { send_notification(socket, false, "Interactions not allowed when setting gps coordinates", ""); return ; } await spawnPromise("bash", [ "/conf/press_key.sh", data.key ]); }); socket.on("setcoord", async (data) => { if (gps_setting_in_progress) { send_notification(socket, false, "Interactions not allowed when setting gps coordinates", ""); return ; } gps_setting_in_progress = true; const res = await spawnPromise("bash", [ "/conf/set_geo_full.sh", data.lon + "", data.lat + "", ]); send_notification( socket, res.code === 0, "Setting the moch location", res.output ); gps_setting_in_progress = false; await send_private_data(); }); }); io.listen(3000); console.log("listening on port 3000");