Skip to content

feat(DiscordRPC): add support for targeting specific Discord instances (PTB/Canary)#223

Open
zeedif wants to merge 3 commits intoInrixia:masterfrom
zeedif:feat/discordrpc-multi-instance
Open

feat(DiscordRPC): add support for targeting specific Discord instances (PTB/Canary)#223
zeedif wants to merge 3 commits intoInrixia:masterfrom
zeedif:feat/discordrpc-multi-instance

Conversation

@zeedif
Copy link

@zeedif zeedif commented Feb 27, 2026

This PR adds support for targeting a specific Discord instance for the Rich Presence.

I personally use two Discord instances at the same time (Stable and PTB) for different accounts, and I wanted to be able to choose which account gets the Tidal Rich Presence. Previously, it would just default to whatever client was opened first.

Changes made

  • Dynamic Pipe Detection: The native side now scans the OS temp/pipe directories to find exactly which Discord IPC sockets (discord-ipc-x) are currently open.
  • Smart UI: If only one Discord client is running, the plugin connects automatically and no extra settings are shown. If two or more instances are detected, a new dropdown setting appears, allowing the user to seamlessly switch the RPC between instances (e.g., Pipe 0, Pipe 1).
  • Graceful Fallback: If the currently selected pipe gets closed, the plugin will automatically fallback to the lowest available pipe.
  • Error Handling: Wrapped the connection logic in try/catch blocks to prevent the client from throwing annoying CONNECTION_TIMEOUT UI errors when a pipe drops or fails to respond.

- Added dynamic scanning of active Discord IPC pipes (`getAvailablePipes`).
- Automatically connects to the available pipe if only one is found.
- Added a dropdown in settings to select the preferred instance (e.g., Stable vs PTB) when multiple clients are open. The setting remains hidden if only one instance is active.
- Improved connection error handling to prevent UI timeout alerts.
Copy link
Owner

@Inrixia Inrixia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a awesome pr!
Few changes and fixes and I'll be happy to merge 💜

- Extracted pipe detection logic into its own file (`getAvailablePipes.native.ts`).
- Updated file system operations to use `node:fs/promises`.
- Implemented `os.tmpdir()` for OS-agnostic temp directory resolution.
- Optimized pipe ID collection using a `Set`.
- Wrapped `getClient` with `asyncDebounce` to efficiently handle concurrent connection attempts.
- Removed silent `try/catch` in `setActivity` to ensure errors properly propagate up.
@zeedif
Copy link
Author

zeedif commented Feb 27, 2026

Thanks for the feedback! I've just pushed a new commit applying all your suggestions. Let me know if everything looks good now.

Copy link
Owner

@Inrixia Inrixia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, just a few other things around error handling and avoiding client spawn loops and itl be foot to merge.

if (rpcClient) await rpcClient.destroy();
rpcClient = new Client({ clientId: "1130698654987067493" });
await rpcClient.connect();
if (rpcClient) await rpcClient.destroy().catch(() => {});
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the catch here as well.

const client = await getClient();
if (!client.user) return;
rpcClient = new Client(clientOptions);
currentPipeId = targetPipe;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be set after .connect is called

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only this left and then happy to merge, thanks for fixing these things 💜

- Removed silent `.catch(() => {})` on `destroy()` calls to properly throw errors.
- Removed `try/catch` wrapper around `connect()` to let connection errors propagate up naturally.
- Removed redundant `rpcClient = null` assignments.
- Simplified user validation in `setActivity` using optional chaining (`client?.user`).
- Refactored `cleanupRPC` to correctly bubble up potential errors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants