From ce2a0485ab31a7ae98ccccea2c57cfec9ba761b7 Mon Sep 17 00:00:00 2001 From: MasterAcnolo Date: Sat, 8 Aug 2026 10:51:10 +0200 Subject: [PATCH] fix: discord RPC on Linux, creating symlink between Discord and Freedom Loader at start if needed --- app/discordRPC.js | 72 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/app/discordRPC.js b/app/discordRPC.js index dcfbb4b..c74e3e0 100644 --- a/app/discordRPC.js +++ b/app/discordRPC.js @@ -1,6 +1,8 @@ const config = require('../config'); const RPC = require("discord-rpc"); const { logger } = require("../server/logger"); +const fs = require("fs"); +const path = require("path"); /** * Discord Application Client ID used to authenticate the RPC connection. @@ -20,6 +22,51 @@ const rpc = new RPC.Client({ transport: "ipc" }); */ let intervalId; +/** + * Automagically fixes Discord RPC on Linux for Sandboxed versions (Flatpak & Snap). + * It creates a symlink from the sandbox IPC socket to the standard system location. + * + * @returns {void} + */ +function fixLinuxDiscordRPC() { + // Only execute on Linux + if (process.platform !== "linux") return; + + /** + * Get the user's runtime directory (e.g., /run/user/1000). + * @type {string} + */ + const xdgDir = process.env.XDG_RUNTIME_DIR || `/run/user/${process.getuid()}`; + const standardSocket = path.join(xdgDir, "discord-ipc-0"); + + // If the standard socket already exists (Native Discord), do nothing. + if (fs.existsSync(standardSocket)) return; + + /** + * Paths for known sandboxed Discord IPC sockets. + */ + const flatpakSocket = path.join(xdgDir, "app/com.discordapp.Discord/discord-ipc-0"); + const snapSocket = path.join(xdgDir, "snap.discord/discord-ipc-0"); + + let targetSocket = null; + + if (fs.existsSync(flatpakSocket)) { + targetSocket = flatpakSocket; + } else if (fs.existsSync(snapSocket)) { + targetSocket = snapSocket; + } + + // If a sandboxed socket is found, create the symlink stealthily. + if (targetSocket) { + try { + fs.symlinkSync(targetSocket, standardSocket); + logger.info(`Discord RPC bridge created automatically targeting: ${targetSocket}`); + } catch (err) { + logger.warn(`Failed to create Discord RPC bridge: ${err.message}`); + } + } +} + /** * Initializes Discord Rich Presence (RPC) connection. * @@ -32,6 +79,11 @@ let intervalId; */ function startRPC() { + /** + * Patch that create Simlinks for Linux environment; + */ + fixLinuxDiscordRPC(); + /** * Rich Presence payload describing current application state * shown in Discord user profile. @@ -60,28 +112,30 @@ function startRPC() { * * Responsibilities: * - Clear any running intervals - * - Remove current activity from Discord + * - Remove current activity from Discord if connected * - Destroy RPC transport connection * - Handle cleanup errors safely */ -async function stopRPC(){ +async function stopRPC() { + if (rpc) { try { if (intervalId) clearInterval(intervalId); /** - * Ensures RPC connection exists before attempting cleanup. + * Ensures RPC connection AND the underlying socket exist + * before attempting to clear activity to prevent crash. */ - if (rpc && rpc.transport) { - await rpc.clearActivity() - await rpc.destroy(); - } else{ - logger.error("Not Able to close RPC") + if (rpc.transport && rpc.transport.socket) { + await rpc.clearActivity(); } - + + await rpc.destroy(); + } catch (err) { logger.error("Error while closing the RPC:", err); } } +} module.exports = { startRPC, stopRPC};