2022-11-19 22:15:05 +00:00
|
|
|
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);
|
|
|
|
|
2022-11-20 12:48:07 +00:00
|
|
|
const {IPCServer} = require("./transports/ipc.js");
|
|
|
|
const {EventEmitter} = require("events");
|
|
|
|
const {WSServer} = require("./transports/websocket.js");
|
2022-11-19 22:15:05 +00:00
|
|
|
const Bridge = require("./bridge.js");
|
2022-11-20 12:48:07 +00:00
|
|
|
const fetch = require("cross-fetch");
|
2022-11-19 22:15:05 +00:00
|
|
|
const lookupAsset = (name, assets) => {
|
|
|
|
return assets.find((x) => x.name === name)?.id;
|
|
|
|
};
|
2022-11-20 12:48:07 +00:00
|
|
|
class RPCServer extends EventEmitter {
|
2022-11-19 22:15:05 +00:00
|
|
|
constructor() {
|
2022-11-20 12:48:07 +00:00
|
|
|
super();
|
2022-11-19 22:15:05 +00:00
|
|
|
return (async () => {
|
|
|
|
this.onConnection = this.onConnection.bind(this);
|
|
|
|
this.onMessage = this.onMessage.bind(this);
|
|
|
|
|
2022-11-20 12:48:07 +00:00
|
|
|
this.ipc = await new IPCServer(this.onMessage, this.onConnection);
|
|
|
|
this.ws = await new WSServer(this.onMessage, this.onConnection);
|
|
|
|
|
|
|
|
return this;
|
2022-11-19 22:15:05 +00:00
|
|
|
})();
|
|
|
|
}
|
|
|
|
|
|
|
|
onConnection(socket) {
|
|
|
|
socket.send({
|
|
|
|
cmd: "DISPATCH",
|
|
|
|
evt: "READY",
|
2022-11-20 12:48:07 +00:00
|
|
|
|
|
|
|
data: {
|
|
|
|
v: 1
|
|
|
|
}
|
2022-11-19 22:15:05 +00:00
|
|
|
});
|
2022-11-20 12:48:07 +00:00
|
|
|
|
|
|
|
this.emit("connection", socket);
|
2022-11-19 22:15:05 +00:00
|
|
|
}
|
|
|
|
|
2022-11-20 12:48:07 +00:00
|
|
|
async onMessage(socket, {cmd, args, nonce}) {
|
|
|
|
this.emit("message", {socket, cmd, args, nonce});
|
|
|
|
|
2022-11-19 22:15:05 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case "SET_ACTIVITY":
|
|
|
|
if (!socket.application) {
|
2022-11-20 12:48:07 +00:00
|
|
|
// fetch info about application
|
2022-11-19 22:15:05 +00:00
|
|
|
socket.application = await (
|
|
|
|
await fetch(`https://discord.com/api/v9/oauth2/applications/${socket.clientId}/rpc`)
|
|
|
|
).json();
|
|
|
|
socket.application.assets = await (
|
|
|
|
await fetch(`https://discord.com/api/v9/oauth2/applications/${socket.clientId}/assets`)
|
|
|
|
).json();
|
|
|
|
log("fetched app info for", socket.clientId, socket.application);
|
|
|
|
}
|
|
|
|
|
2022-11-20 12:48:07 +00:00
|
|
|
const {activity, pid} = args; // translate given parameters into what discord dispatch expects
|
2022-11-19 22:15:05 +00:00
|
|
|
const {buttons, timestamps, instance} = activity;
|
|
|
|
|
|
|
|
const metadata = {};
|
|
|
|
const extra = {};
|
|
|
|
if (buttons) {
|
2022-11-20 12:48:07 +00:00
|
|
|
// map buttons into expected metadata
|
2022-11-19 22:15:05 +00:00
|
|
|
metadata.button_urls = buttons.map((x) => x.url);
|
|
|
|
extra.buttons = buttons.map((x) => x.label);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (timestamps)
|
|
|
|
for (const x in timestamps) {
|
2022-11-20 12:48:07 +00:00
|
|
|
// translate s -> ms timestamps
|
2022-11-19 22:15:05 +00:00
|
|
|
if (Date.now().toString().length - timestamps[x].toString().length > 2)
|
2022-11-20 12:48:07 +00:00
|
|
|
timestamps[x] = Math.floor(1000 * timestamps[x]);
|
2022-11-19 22:15:05 +00:00
|
|
|
}
|
|
|
|
|
2022-11-20 12:48:07 +00:00
|
|
|
// lookup assets to ids
|
2022-11-19 22:15:05 +00:00
|
|
|
if (activity.assets?.large_image)
|
|
|
|
activity.assets.large_image = lookupAsset(activity.assets.large_image, socket.application.assets);
|
|
|
|
if (activity.assets?.small_image)
|
|
|
|
activity.assets.small_image = lookupAsset(activity.assets.small_image, socket.application.assets);
|
|
|
|
|
2022-11-20 12:48:07 +00:00
|
|
|
this.emit("activity", {
|
2022-11-19 22:15:05 +00:00
|
|
|
activity: {
|
|
|
|
name: socket.application.name,
|
|
|
|
application_id: socket.application.id,
|
|
|
|
type: 0,
|
|
|
|
metadata,
|
|
|
|
flags: instance ? 1 << 0 : 0,
|
|
|
|
...activity,
|
|
|
|
...extra
|
|
|
|
},
|
|
|
|
pid
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
2022-11-20 12:48:07 +00:00
|
|
|
|
|
|
|
case "INVITE_BROWSER":
|
|
|
|
const {code} = args;
|
|
|
|
socket.send({
|
|
|
|
cmd,
|
|
|
|
data: {
|
|
|
|
code
|
|
|
|
},
|
|
|
|
nonce
|
|
|
|
});
|
|
|
|
|
|
|
|
this.emit("invite", code);
|
|
|
|
break;
|
2022-11-19 22:15:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = {RPCServer};
|