how to build a custom chatengine plugin

How to Build a Custom ChatEngine Plugin

As developers evaluate products and tools a common phrase that comes up is vendor lock-in and feature-set parity. Developers want tools that give them maximum flexibility with a full feature set. When our CTO Stephen built PubNub, his vision was to create an agnostic product that met developers needs and allowed the developer to choose what protocol, language, and functionality fits their use case.

As more features and products are launched we’ve tried to stick to the same principle with the BLOCKS Catalog and more recently with ChatEngine. ChatEngine allows developers to quickly create fully functional chat applications. Out of the box there is a full feature set for creating a modern chat application.

However, one of the most exciting parts is the plugin framework. A plugin allows developers to add nearly any functionality to ChatEngine. This functionality can be as simple as a typing indicator or searching for online users. Today I’m going to show you how to build your own custom plugin so that any functionality you might need can be added to ChatEngine!

Plugin Anatomy

A plugin is a NodeJS module that exports a mixin-like object that augments ChatEngine objects. This effectively hooks into the events ChatEngine creates and allows the user to do anything before or after an event happens.

The plugin entry must be a file called plugin.js in the root directory. From this file you can require any other file as normal, but the entry must be plugin.js Every plugin must return an object containing the property namespace and middleware or extends. One use case would be to modify ChatEngine objects and add new methods to them. For example, this plugin adds a method called newMethod() to the Chat class.

// newmethod/plugin.js
module.exports = {
    return {
        extends: {
            Chat: {
                construct: (options) => {
                    // this is called when the plugin is attached to the Chat
                    // the Chat object is available through this.parent
                    console.log('I am extending', this.parent, 'with options', options);
                },
                newMethod: () => {
                    // this is a new method that gets attached to Chat as Chat.newMethod()
                    console.log('New Method Fired - this Chat object is available as this.parent');
                }
            }
        }
    }

}

To actually use the plugin you can attach it to a Chat.

// include the plugin via require
newMethodPlugin = require('newmethod/plugin.js');

// create a chat for the plugin to attach to
chat = new ChatEngine.Chat('my-plugin-chat');

// attach the plugin to the chat
// newMethodPlugin.construct() is called and console log is fired
chat.plugin(newMethodPlugin({
    myparam: true
}));

// Console: I am extending ChatEngine.Chat with options {myParam: true}

chat.newMethod();

// Console: New Method Fired - this Chat object is available as this.parent

When the plugin is installed, every instance of ChatEngine.Chat will have a new method called newMethod(). You can call the method like someChat.newMethod().

Middleware

Middleware allows you to transform payloads as they travel through the system. They are executed in the order they are assigned.

The only valid properties of the middleware object are emit and on.

  • emit is executed before the payload is sent over the network to the rest of the connected clients.
  • on is executed when the client receives a payload from another client.
// timer/plugin.js
module.exports = (config) => {

    return {
        middleware: {
            emit:
                message: (payload, next) => {
                    payload.sentTime = new Date();
                    next(err, payload);
                }
            },
            on:
                message: (payload, next) -> {
                    payload.receiveTime = new Date();
                    next(err, payload);
                }
            }
        }
    };

}

The sub-properties under emit and on are the events that will trigger the transformation. For example, the plugin above will be executed when a message event is sent from the client.

// include the plugin via require
timerPlugin = require('timer/plugin.js');

chat.plugin(timerPlugin());

// emit a message
someChat.emit('message', {text: “This triggers the emit method before it's published over the wire.”});

// timerPlugin.middleware.emit.message() is executed
// payload.sentTime is added to the payload

// when message is received
// timerPlugin.middleware.ont.message() is executed
someChat.on('message', (payload) => {

    // payload has been modified by the on() method before this was called
    // payload.receiveTime has been added by the plugin
    console.log(payload.receiveTime);

});

With just a few small bits of code we can add extensive amount of functionality to ChatEngine. A full list of the currently documented plugins is in the docs with more coming all the time.

Hopefully, you can find the plugin already for your use case and if not use the above steps to add the functionality! We are always listening to feedback on Github and can’t wait to see what plugins you build.

Use Cases:

Try PubNub Today