Search code examples
javascriptbackbone.jsreal-timepusher

pusher client events triggering for user


I am working on a realtime application at the moment, that allows a user to add other others to a "team", I am wanting to notify a user they have been added in realtime. However I can not for the life of me work how to implement this, I think it is the documentation that is confusing me more than anything,

The user must be subscribed to the channel that the event is being triggered on

How can this be possible? Surely by the fact that I am trying to add some one to a group in a realtime, and that group is a unique channel they cannot me subscribed too it?

Here is my attempt, and explanation of the process.

1) A user logins into an app and is subscribed to a unique to them channel "presence-user_{id}" where id is there user id from the database.

2) A user elsewhere wants to add a user to their group, a select that user which runs the following code,

App['presence-' + 'user_' + newUser.get('id')] = App.pusher.subscribe('presence-user_' + newUser.get('id'));
                            App['presence-' + 'user_' + newUser.get('id')].trigger('client-user-added', { project : self.model.get('id') });

newUser is a backbone model detailing the user details of the selected user. What I am trying to do here is subscribe the user who is trying to a user to a group to that users channel.

This should then fire this method listenter,

App['presence-' + 'user_' + App.Session.get('user_id')].bind('client-user-added', this.RT_addProject, this);

This in turn should fire the following the method on the added clients application,

RT_addProject: function(data) {
    console.log(data);
},

however it does not. What is the correct method of triggering client events?

TLDR; I want notify a user in realtime when they are added to a group using pusher.


Solution

  • There key points to presence channels are:

    1. The presence channel name should be shared between the users that you wish to join the group - the act of subscribing to the channel adds them to the channel.
    2. Each user on a channel needs a unique ID that you supply via your server (probably the user session ID) via an auth callback. This uniquely identifies them on the channel.
    3. If the authentication is successful they are subscribed. Upon subscription the client get an initial list of existing users on the channel via the pusher:subscription_succeeded event.
    4. Existing subscribers to the channel are notified of the presence of new users via pusher:member_added events.
    5. As users go offline (close the browser, navigate between pages or unsubscribe via code) all other users on the channel are informed that the user has left the channel via pusher:member_removed events.

    For example. On the client:

    var pusher = new Pusher(APP_KEY);
    var chatChannel = pusher.subscribe('presence-chat');
    
    chatChannel.bind('pusher:subscription_succeeded', function(members) {
      members.each(memberAdded);
    });
    chatChannel.bind('pusher:member_added', memberAdded);
    chatChannel.bind('pusher:member_removed', memberRemoved);
    
    function memberAdded(member) {
      // add to UI etc.
    }
    
    function memberRemoved(member) {
      // remove from UI etc.
    }
    

    The act of subscribing results in the Pusher JS library making an auth POST request to a server endpoint.

    Server pseudo code:

    var channelName = authRequest.postParam['channel-name'];
    var socketId =  authRequest.postParam['socket-id'];
    
    var pusher = new Pusher(YOUR_CREDENTIALS);
    
    if( currentSessionUserAllowedToSubscribeToChannel(channelName)  ) {
      var uniqueUserId = getCurrentSessionUserUniqueId();
      var customUserInfo = getCustomUserInfo();
      var authSignature = pusher.presence_auth(channelName,
                                          uniqueUserId,
                                          customUserInfo);
    
      send200AuthJSONToClient(authSignature);
    }
    else {
      send401ToClient();
    }
    

    What is the correct method of triggering client events?

    Client events can only be triggered on private or presence channels once the subscription has succeeded:

    var pusher = new Pusher(APP_KEY);
    var chatChannel = pusher.subscribe('presence-chat');
    
    chatChannel.bind('pusher:subscription_succeeded', function() {
      var wasTriggered = pusher.trigger('client-event', {some: 'data'});
      console.log(wasTriggered);
    });
    

    TLDR; I want notify a user in realtime when they are added to a group using pusher.

    If userA wants userB to join channelX then you need to signal userB about the existence of channelX so they can subscribe to it.

    userB can only receive events on channels they are subscribed to. So, userA somehow needs to send an event on a channel userB knows about. A common solution to this is to have a per user channel e.g. userA-notifications and userA needs to trigger an event on this channel via the server. Ultimately you need an authority to stop unwanted events from being triggered.

    This answer is relevant to the process described above: https://stackoverflow.com/a/28165893/39904