diff --git a/src/bridge.js b/src/bridge.js index 86794dd..2d865f5 100644 --- a/src/bridge.js +++ b/src/bridge.js @@ -19,7 +19,7 @@ const bridge = Bun.serve({ return Response.redirect("https://github.com/wont-stream/bunRPC", 301); }, websocket: { - message() { }, + message() {}, open(ws) { clients.add(ws); @@ -34,4 +34,4 @@ const bridge = Bun.serve({ }, }); -console.log(`[bunRPC] [Bridge] listening on ws://localhost:${bridge.port}`); \ No newline at end of file +console.log(`[bunRPC] [Bridge] listening on ws://localhost:${bridge.port}`); diff --git a/src/process/index.js b/src/process/index.js index 2cb1b60..159f08d 100644 --- a/src/process/index.js +++ b/src/process/index.js @@ -1,4 +1,4 @@ -import * as Natives from './native/index.js'; +import * as Natives from "./native/index.js"; const Native = Natives[process.platform]; const timestamps = {}; @@ -6,100 +6,116 @@ const names = {}; const pids = {}; export default class { - constructor(handlers) { - if (!Native) return; - - this.handlers = handlers; - - this.scan = this.scan.bind(this); - - this.getDB(); - - this.scan(); - setInterval(this.scan, 10000); // every 10 seconds instead of 5 - - console.log("[bunRPC] [Process] Scanner started"); - } - - async getDB() { - if (this.DetectableDB) return this.DetectableDB; - - const data = await fetch("https://discord.com/api/v9/applications/detectable") - - this.DetectableDB = await data.json(); - - return this.DetectableDB; - } - - async scan() { - const processes = await Native.getProcesses(); - const ids = []; - - const DetectableDB = await this.getDB(); - - for (const [pid, _path, args] of processes) { - const path = _path.toLowerCase().replaceAll('\\', '/'); - const toCompare = []; - const splitPath = path.split('/'); - for (let i = 1; i < splitPath.length; i++) { - toCompare.push(splitPath.slice(-i).join('/')); - } - - for (const p of toCompare.slice()) { - toCompare.push(p.replace('64', '')); - toCompare.push(p.replace('.x64', '')); - toCompare.push(p.replace('x64', '')); - toCompare.push(p.replace('_64', '')); - } - - for (const { executables, id, name } of DetectableDB) { - if (executables?.some(x => { - if (x.is_launcher) return false; - if (x.name[0] === '>' ? x.name.substring(1) !== toCompare[0] : !toCompare.some(y => x.name === y)) return false; - if (args && x.arguments) return args.join(" ").indexOf(x.arguments) > -1; - return true; - })) { - names[id] = name; - pids[id] = pid; - - ids.push(id); - if (!timestamps[id]) { - timestamps[id] = Date.now(); - } - - this.handlers.message({ - socketId: id - }, { - cmd: 'SET_ACTIVITY', - args: { - activity: { - application_id: id, - name, - timestamps: { - start: timestamps[id] - } - }, - pid - } - }); - } - } - } - - for (const id in timestamps) { - if (!ids.includes(id)) { - delete timestamps[id]; - - this.handlers.message({ - socketId: id - }, { - cmd: 'SET_ACTIVITY', - args: { - activity: null, - pid: pids[id] - } - }); - } - } - } -} \ No newline at end of file + constructor(handlers) { + if (!Native) return; + + this.handlers = handlers; + + this.scan = this.scan.bind(this); + + this.getDB(); + + this.scan(); + setInterval(this.scan, 10000); // every 10 seconds instead of 5 + + console.log("[bunRPC] [Process] Scanner started"); + } + + async getDB() { + if (this.DetectableDB) return this.DetectableDB; + + const data = await fetch( + "https://discord.com/api/v9/applications/detectable", + ); + + this.DetectableDB = await data.json(); + + return this.DetectableDB; + } + + async scan() { + const processes = await Native.getProcesses(); + const ids = []; + + const DetectableDB = await this.getDB(); + + for (const [pid, _path, args] of processes) { + const path = _path.toLowerCase().replaceAll("\\", "/"); + const toCompare = []; + const splitPath = path.split("/"); + for (let i = 1; i < splitPath.length; i++) { + toCompare.push(splitPath.slice(-i).join("/")); + } + + for (const p of toCompare.slice()) { + toCompare.push(p.replace("64", "")); + toCompare.push(p.replace(".x64", "")); + toCompare.push(p.replace("x64", "")); + toCompare.push(p.replace("_64", "")); + } + + for (const { executables, id, name } of DetectableDB) { + if ( + executables?.some((x) => { + if (x.is_launcher) return false; + if ( + x.name[0] === ">" + ? x.name.substring(1) !== toCompare[0] + : !toCompare.some((y) => x.name === y) + ) + return false; + if (args && x.arguments) + return args.join(" ").indexOf(x.arguments) > -1; + return true; + }) + ) { + names[id] = name; + pids[id] = pid; + + ids.push(id); + if (!timestamps[id]) { + timestamps[id] = Date.now(); + } + + this.handlers.message( + { + socketId: id, + }, + { + cmd: "SET_ACTIVITY", + args: { + activity: { + application_id: id, + name, + timestamps: { + start: timestamps[id], + }, + }, + pid, + }, + }, + ); + } + } + } + + for (const id in timestamps) { + if (!ids.includes(id)) { + delete timestamps[id]; + + this.handlers.message( + { + socketId: id, + }, + { + cmd: "SET_ACTIVITY", + args: { + activity: null, + pid: pids[id], + }, + }, + ); + } + } + } +} diff --git a/src/process/native/darwin/index.js b/src/process/native/darwin/index.js index 58c457c..837dc67 100644 --- a/src/process/native/darwin/index.js +++ b/src/process/native/darwin/index.js @@ -1,21 +1,21 @@ -import { exec } from 'node:child_process'; +import { exec } from "node:child_process"; export const getProcesses = () => { - return new Promise((resolve, reject) => { - exec("ps -axo pid,comm", (error, stdout) => { - if (error) { - return reject(error); // Handle errors - } + return new Promise((resolve, reject) => { + exec("ps -axo pid,comm", (error, stdout) => { + if (error) { + return reject(error); // Handle errors + } - const processes = stdout - .toString() - .split('\n') // Split by new lines - .slice(1) // Skip the header line - .map(line => line.trim().split(/\s+/, 2)) // Split into PID and command - .filter(parts => parts.length === 2) // Ensure both PID and command exist - .map(([pid, command]) => [Number(pid), command]); + const processes = stdout + .toString() + .split("\n") // Split by new lines + .slice(1) // Skip the header line + .map((line) => line.trim().split(/\s+/, 2)) // Split into PID and command + .filter((parts) => parts.length === 2) // Ensure both PID and command exist + .map(([pid, command]) => [Number(pid), command]); - resolve(processes); - }); - }); + resolve(processes); + }); + }); }; diff --git a/src/process/native/index.js b/src/process/native/index.js index 0ea8b0a..ff05ff4 100644 --- a/src/process/native/index.js +++ b/src/process/native/index.js @@ -1,3 +1,3 @@ -export * as darwin from './darwin/index.js'; -export * as linux from './linux/index.js'; -export * as win32 from './win32/index.js'; \ No newline at end of file +export * as darwin from "./darwin/index.js"; +export * as linux from "./linux/index.js"; +export * as win32 from "./win32/index.js"; diff --git a/src/process/native/linux/index.js b/src/process/native/linux/index.js index cff0777..02544dd 100644 --- a/src/process/native/linux/index.js +++ b/src/process/native/linux/index.js @@ -1,21 +1,21 @@ import { readdir } from "node:fs/promises"; -import { file } from "bun" +import { file } from "bun"; export const getProcesses = async () => { - const directories = await readdir("/proc"); + const directories = await readdir("/proc"); - const processPromises = directories - .filter(pid => +pid > 0) // Filter valid PIDs upfront - .map(async (pid) => { - try { - const cmdline = await file(`/proc/${pid}/cmdline`).text(); - const [command, ...args] = cmdline.split("\0"); // Destructure for clarity - return [+pid, command, args]; - } catch { - return null; // Return null on failure - } - }); + const processPromises = directories + .filter((pid) => +pid > 0) // Filter valid PIDs upfront + .map(async (pid) => { + try { + const cmdline = await file(`/proc/${pid}/cmdline`).text(); + const [command, ...args] = cmdline.split("\0"); // Destructure for clarity + return [+pid, command, args]; + } catch { + return null; // Return null on failure + } + }); - const processes = await Promise.all(processPromises); - return processes.filter(Boolean); // Filter out null entries + const processes = await Promise.all(processPromises); + return processes.filter(Boolean); // Filter out null entries }; diff --git a/src/process/native/win32/index.js b/src/process/native/win32/index.js index 37bc481..52cf3e2 100644 --- a/src/process/native/win32/index.js +++ b/src/process/native/win32/index.js @@ -1,18 +1,23 @@ -import { exec } from 'node:child_process'; +import { exec } from "node:child_process"; export const getProcesses = () => { - return new Promise((resolve) => { - exec("wmic process get ProcessID,ExecutablePath /format:csv", (error, output) => { + return new Promise((resolve) => { + exec( + "wmic process get ProcessID,ExecutablePath /format:csv", + (error, output) => { + const processes = output + .toString() + .split("\r\n") // Split by new lines + .slice(2) // Remove headers + .map((line) => line.trim().split(",").reverse()) // Split, reverse, and trim + .filter((parsed) => parsed[1]) // Filter out invalid paths + .map(([executablePath, processId]) => [ + Number(processId) || processId, + executablePath, + ]); // Parse IDs - const processes = output - .toString() - .split('\r\n') // Split by new lines - .slice(2) // Remove headers - .map(line => line.trim().split(',').reverse()) // Split, reverse, and trim - .filter(parsed => parsed[1]) // Filter out invalid paths - .map(([executablePath, processId]) => [Number(processId) || processId, executablePath]); // Parse IDs - - resolve(processes); - }); - }); + resolve(processes); + }, + ); + }); }; diff --git a/src/server.js b/src/server.js index 50c4d41..145b80c 100644 --- a/src/server.js +++ b/src/server.js @@ -3,7 +3,7 @@ import { EventEmitter } from "node:events"; import ipc from "./transports/ipc.js"; import ws from "./transports/ws.js"; -import process from "./process/index.js" +import process from "./process/index.js"; let socketId = 0; @@ -168,9 +168,9 @@ export default class extends EventEmitter { data: isValid ? { code } : { - code: isInvite ? 4011 : 4017, - message: `Invalid ${isInvite ? "invite" : "guild template"} id: ${code}`, - }, + code: isInvite ? 4011 : 4017, + message: `Invalid ${isInvite ? "invite" : "guild template"} id: ${code}`, + }, evt: isValid ? null : "ERROR", nonce, }); diff --git a/src/transports/ipc.js b/src/transports/ipc.js index a9c22b0..69f64a2 100644 --- a/src/transports/ipc.js +++ b/src/transports/ipc.js @@ -7,9 +7,13 @@ const SOCKET_PATH = process.platform === "win32" ? "\\\\?\\pipe\\discord-ipc" : join( - process.env.XDG_RUNTIME_DIR || process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp", - "discord-ipc", - ); + process.env.XDG_RUNTIME_DIR || + process.env.TMPDIR || + process.env.TMP || + process.env.TEMP || + "/tmp", + "discord-ipc", + ); const Types = { HANDSHAKE: 0, @@ -115,7 +119,7 @@ const socketIsAvailable = async (socket) => { try { socket.end(); socket.destroy(); - } catch { } + } catch {} }; const possibleOutcomes = Promise.race([ @@ -147,7 +151,7 @@ const getAvailableSocket = async (tries = 0) => { if (process.platform !== "win32") try { unlinkSync(path); - } catch { } + } catch {} return path; } diff --git a/src/transports/ws.js b/src/transports/ws.js index 9a8985b..9d72f85 100644 --- a/src/transports/ws.js +++ b/src/transports/ws.js @@ -9,12 +9,12 @@ const checkIfOpen = async (port) => { ws.onopen = () => { ws.close(); resolve(true); - } + }; ws.onerror = () => { resolve(false); - } - }) + }; + }); }; const getPort = async () => { @@ -82,7 +82,9 @@ export default class { }, }); - console.log(`[bunRPC] [Transport] [WS] listening on ws://localhost:${ws.port}`); + console.log( + `[bunRPC] [Transport] [WS] listening on ws://localhost:${ws.port}`, + ); }); } }