Update arrpc to 3.0.0 (#284)

This commit is contained in:
aeongdesu 2022-12-10 18:40:14 +09:00 committed by GitHub
parent af1f2f2e1c
commit e2fc0c6401
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 33122 additions and 13 deletions

View file

@ -71,6 +71,7 @@ Then just use apps with Discord RPC like normal and they _should_ work!
- [ ] Erlpack
- [ ] HTTP Server
- [x] IPC
- [x] Process Scanning
### Commands

View file

@ -1,5 +1,16 @@
# arRPC Changelog
## v3.0.0 [26-11-2022]
- **Added Process Scanning.** Now scans for detectable/verified games and tells Discord the app, allowing process detection whilst maintaining privacy (Discord does not see any/all processes, just the name and app ID).
- **Fixed RPC not fully working with more apps/libraries.** Now responds with a mock/fake arRPC user and the proper config, replies with confirmation, and supports blank activites fully.
- **Fixed a few minor Bridge bugs.** Fixed catchup not working with several apps.
## v2.2.1 [24-11-2022]
- IPC: Fix version given as string not being accepted
- IPC: Fix socket closing
## v2.2.0 [20-11-2022]
- Server: Move all looking up/fetching to client

View file

@ -1,8 +1,8 @@
{
"name": "arrpc",
"version": "2.2.0",
"version": "3.0.0",
"description": "Open Discord RPC server for atypical setups",
"main": "src/index.cjs",
"main": "src/index.js",
"scripts": {
"start": "node src"
},

View file

@ -1,7 +1,7 @@
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")}]`, ...args);
log("arRPC v2.2.0 [ArmCord]");
log("arRPC v3.0.0 [ArmCord]");
const {RPCServer} = require("./server.js");
const {mainWindow} = require("../../../ts-out/window.js");

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,95 @@
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(237, 66, 69, "process")}]`, ...args);
const DetectableDB = require("./detectable.json");
const Natives = require("./native/index.js");
const Native = Natives[process.platform];
const timestamps = {},
names = {},
pids = {};
class ProcessServer {
constructor(handlers) {
if (!Native) return log("unsupported platform:", process.platform);
this.handlers = handlers;
this.scan = this.scan.bind(this);
this.scan();
setInterval(this.scan, 5000);
log("started");
}
async scan() {
const processes = await Native.getProcesses();
const ids = [];
for (const [pid, _path] of processes) {
const path = _path.toLowerCase().replaceAll("\\", "/");
const toCompare = [path.split("/").pop(), path.split("/").slice(-2).join("/")];
for (const p of toCompare.slice()) {
// add more possible tweaked paths for less false negatives
toCompare.push(p.replace("64", "")); // remove 64bit identifiers-ish
toCompare.push(p.replace(".x64", ""));
toCompare.push(p.replace("x64", ""));
}
for (const {executables, id, name} of DetectableDB) {
if (executables?.some((x) => !x.isLauncher && toCompare.some((y) => x.name === y))) {
names[id] = name;
pids[id] = pid;
ids.push(id);
if (!timestamps[id]) {
log("detected game!", name);
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)) {
log("lost game!", names[id]);
delete timestamps[id];
this.handlers.message(
{
socketId: id
},
{
cmd: "SET_ACTIVITY",
args: {
activity: null,
pid: pids[id]
}
}
);
}
}
}
}
module.exports = {ProcessServer};

View file

@ -0,0 +1,2 @@
const win32 = require("./win32.js");
module.exports = {win32};

View file

@ -0,0 +1,21 @@
const {exec} = require("child_process");
module.exports = {
getProcesses: () =>
new Promise((res) =>
exec(`wmic process get ProcessID,ExecutablePath /format:csv`, (e, out) => {
res(
out
.toString()
.split("\r\n")
.slice(2)
.map((x) => {
const parsed = x.trim().split(",").slice(1).reverse();
parsed[0] = parseInt(parsed[0]) || parsed[0]; // pid to int
return parsed;
})
.filter((x) => x[1])
);
})
)
};

View file

@ -1,10 +1,8 @@
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(87, 242, 135, "bridge")}]`, ...args);
const {EventEmitter} = require("events");
const {IPCServer} = require("./transports/ipc.js");
const {WSServer} = require("./transports/websocket.js");
const {ProcessServer} = require("./process/index.js");
let socketId = 0;
class RPCServer extends EventEmitter {
@ -23,6 +21,7 @@ class RPCServer extends EventEmitter {
this.ipc = await new IPCServer(handlers);
this.ws = await new WSServer(handlers);
this.process = await new ProcessServer(handlers);
return this;
})();
@ -34,7 +33,23 @@ class RPCServer extends EventEmitter {
evt: "READY",
data: {
v: 1
v: 1,
// needed otherwise some stuff errors out parsing json strictly
user: {
// mock user data using arRPC app/bot
id: "1045800378228281345",
username: "arRPC",
discriminator: "0000",
avatar: "cfefa4d9839fb4bdf030f91c2a13e95c",
flags: 0,
premium_type: 0
},
config: {
api_endpoint: "//discord.com/api",
cdn_host: "cdn.discordapp.com",
environment: "production"
}
}
});
@ -59,6 +74,14 @@ class RPCServer extends EventEmitter {
switch (cmd) {
case "SET_ACTIVITY":
const {activity, pid} = args; // translate given parameters into what discord dispatch expects
if (!activity)
return this.emit("activity", {
activity: null,
pid,
socketId: socket.socketId.toString()
});
const {buttons, timestamps, instance} = activity;
socket.lastPid = pid ?? socket.lastPid;
@ -91,6 +114,13 @@ class RPCServer extends EventEmitter {
socketId: socket.socketId.toString()
});
socket.send?.({
cmd,
data: null,
evt: null,
nonce
});
break;
case "GUILD_TEMPLATE_BROWSER":
@ -104,7 +134,7 @@ class RPCServer extends EventEmitter {
nonce
});
this.emit(cmd === "INVITE_BROWSER" ? "invite" : "guild_template", code);
this.emit(cmd === "INVITE_BROWSER" ? "invite" : "guild-template", code);
break;
case "DEEP_LINK":

View file

@ -4,7 +4,9 @@ const log = (...args) => console.log(`[${rgb(88, 101, 242, "arRPC")} > ${rgb(254
const {join} = require("path");
const {platform, env} = require("process");
const {unlinkSync} = require("fs");
const {createServer, createConnection} = require("net");
const SOCKET_PATH =
platform === "win32"
? "\\\\?\\pipe\\discord-ipc"
@ -210,10 +212,20 @@ class IPCServer {
socket.once("handshake", (params) => {
log("handshake:", params);
const ver = params.v ?? 1;
const ver = parseInt(params.v ?? 1);
const clientId = params.client_id ?? "";
// encoding is always json for ipc
socket.close = (code = CloseCodes.CLOSE_NORMAL, message = "") => {
socket.end(
encode(Types.CLOSE, {
code,
message
})
);
socket.destroy();
};
if (ver !== 1) {
log("unsupported version requested", ver);

View file

@ -25,7 +25,7 @@ class WSServer {
await new Promise((res) => {
http = createServer();
http.on("error", (e) => {
// log('http error', e);
// log("http error", e);
if (e.code === "EADDRINUSE") {
log(port, "in use!");
@ -35,7 +35,7 @@ class WSServer {
wss = new WebSocketServer({server: http});
wss.on("error", (e) => {
// log('wss error', e);
// log("wss error", e);
});
wss.on("connection", this.onConnection);
@ -92,8 +92,8 @@ class WSServer {
return;
}
/* if (clientId === '') {
log('client id required');
/* if (clientId === "") {
log("client id required");
socket.close();
return;