discordjs / RPC

A simple RPC client for Discord

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot subscribe to some RPC events, the events do not fire

opened this issue · comments

My application has to detect when the user joins to a voice channel and then detect updates on that voice channel.
The VOICE_CHANNEL_SELECT event is working fine, but VOICE_STATE_CREATE / VOICE_STATE_UPDATE / VOICE_STATE_DELETE events do not fire at all.

The event API just for convenience: https://discord.com/developers/docs/topics/rpc#commands-and-events

const RPC = require('discord-rpc');

const cfg = {
  clientId: 'hidden',
  clientSecret: 'hidden',
  scopes: ['rpc']
}

RPC.register(cfg.clientId);

const client = new RPC.Client({ transport: 'ipc' });

client.on('ready', () => {
  console.log('Logged in as', client.application.name);
  console.log('Authed for user', client.user.username);

  client.subscribe('VOICE_CHANNEL_SELECT', function (channel) {  // This one works fine
    if (channel.channel_id == null) return;

    client.subscribe('VOICE_STATE_CREATE', channel, (voice_status) => {  // This one and the ones below never fire
      console.log(voice_status);
    });

    client.subscribe('VOICE_STATE_UPDATE', channel, (voice_status) => {
      console.log(voice_status);
    });

    client.subscribe('VOICE_STATE_DELETE', channel, (voice_status) => {
      console.log(voice_status);
    });
  }
}

client.login({ clientId: cfg.clientId, clientSecret: cfg.clientSecret, scopes: cfg.scopes, redirectUri: 'https://localhost:8080/authorize'}).catch(console.error);

any thoughts? thanks in advance.

I was just looking at that, and it seems that there is an implementation mistake in client.js, _onRpcMessage(message) https://github.com/discordjs/RPC/blob/master/src/client.js#L194

      const subid = subKey(message.evt, message.args);
      if (!this._subscriptions.has(subid)) {
        return;
      }
      this._subscriptions.get(subid)(message.data);

While rpc events seems to send back args in "data" field, therefore "args" field is always undefined and RPC subscription doesn't work
https://discord.com/developers/docs/topics/rpc#guildstatus-example-guild-status-dispatch-payload

I think changing message.args to message.data would fix it

Hi, thank you for your response!
Your fix seems right to me, however my code still doesn't work, but I think that it might be the same problem you stated here.

With your response, I managed to find a quick temporary fix, but it is not too good.

// client.js line 193
      const subid = message.evt; // Used to be "subKey(message.evt, message.data)";
      if (!this._subscriptions.has(subid)) {
        return;
      }
      this._subscriptions.get(subid)(message.data);
// client.js line 661
subscribe(event, args, callback) {
    if (!callback && typeof args === 'function') {
      callback = args;
      args = undefined;
    }
    return this.request(RPCCommands.SUBSCRIBE, args, event).then(() => {
      const subid = event; // Used to be "subKey(event, args);"
      this._subscriptions.set(subid, callback);
      return {
        unsubscribe: () => this.request(RPCCommands.UNSUBSCRIBE, args, event)
          .then(() => this._subscriptions.delete(subid)),
      };
    });
  }

The problem with this fix is that now there can only be one subscription per event.

Yeah, main issue with VOICE_STATE_CREATE event is that it doesn't send back the args data. Your fix works well but it will also listen to other channels if you subscribe to it. As it seems the API doesn't provide a way (nonce or args) to know what channel it is for.
BUT you should be able to find it yourself by tracking who is in what channel.

Also regarding having multiple listeners on the same event, I would suggest handling an Array of callbacks instead of a single callback per subkey when there are multiple subscription

Find the same problem with event MESSAGE_CREATE.
But if you change message.args to message.data , it doesn't fix it.

The way the key is generate for the Map this._subscriptions in subscribe function doesn't map with the subKey generate in the _onRpcMessage

When subscribe, it create an entry with :
MESSAGE_CREATE{"channel_id":"XXXXX"}

In _onRpcMessage function it check the key with:
MESSAGE_CREATE{"channel_id":"XXXXX","message":{"id":"XXXXX","content":"XXXXX"}}

That way it never found the subscription and never trigger it.

I make an ugly fix :

if(args.channel_id != undefined) {
      return `${event}${args.channel_id}`;  
  } else {
      return `${event}${JSON.stringify(args)}`;
  }

with the change suggest by @Herysia (message.args to message.data)

It seems to fix it for me

commented

Maybe do something like #112 but instead of just using message.data use something like this
in _onRpcMessage

const subid = subKey(message.evt, {
    channel_id: message.data.channel_id,
    user_id: message.data.user_id,
});

Then you can specify just the keys that would be set for args, if they are not in data they will not appear, and this still works for MESSAGE_CREATE as the message data is not included.
^ This doesn't work for VOICE_STATE_CREATE, VOICE_STATE_UPDATE, VOICE_STATE_DELETE though as the message for each of those does not include a channel_id although a channel_id is required to subscribe to each of them.

@devsnek not sure why these issues / PRs were closed -- the issue still exists. I have my personal projects pointing at my github branch as a dep, as this issue is not fixed.

commented

this issue has been resolved as of v4.0.1