In this tutorial we’re going to create a “live” chat client. For this, we’re going to use:

  • WebSocket connections to avoid frequent / long polling.
  • Publish / subscribe for communication, publishing either from the browser or using a script to transform / translate the messages first.

This means that we’re going to have two chat clients (two WebSocket connections), one will have its messages pushed to it as-is, while the second will see its messages translated into French before being pushed. Those clients will either listen to the “chat” or to the “chat-translated” channel.

Chat Channel
Send
Translate Channel
Translate

For this, each chat client will need to connect to scriptr.io using WebSockets to get the needed responsiveness for a chat client:

var client = new WebSocket("wss://api.scriptr.io/");

and will then need to specify which channels it will push to and which it will receive from. So, in this tutorial, we have the following clients:

  • client1 which will have its messages sent as-is, and will publish on channel “chat” while it will be subscribing to messages on the channel “chat-translated”.
  • client2 will not publish to a channel, instead, it will push the messages to a scriptr.io script which will be responsible for translating the (English) messages it receives to French. The script will then publish the translated message to the channel “chat-translated”. This client will be subscribed to channel “chat” in order to get whatever client1 sends

Note: the translation service is provided by the Microsoft API (http://api.microsofttranslator.com).

Step by step:

  • Create the needed channels in scriptr.io by going to Settings -> Channels:
    channels

    Note that in this example, we made the channels public, allowing anyone to publish and subscribe since the tokens are publicly available anyway (readable in js code).
  • Create the two clients:
    client1 = new WebSocket("wss://api.scriptr.io/token");
    client2 = new WebSocket("wss://api.scriptr.io/token");
    
  • Subscribe each client to a specific channel (client1 will be listening to messages broadcasted on channel “chat-translated” while client2 will be listening to messages broadcasted on channel “chat”:
    client1.onopen = function (event) {
    	client1.send(JSON.stringify({
    		"method":"Subscribe",
    		"params":{
    			"channel":"chat-translated"//this client will only receive translated chats
    		}
    	}), client1);
    }
    client2.onopen = function (event) {
    	client2.send(JSON.stringify({
    		"method":"Subscribe",
    		"params":{
    			"channel":"chat"//this client will receive chats as-is
    		}
    	}), client2);
    }
    
  • Push messages from client1 to channel “chat”:
    var chatMessageObject = {
    	"method":"Publish", //using the publish method, the "message" will just be pushed to anyone listening to "chat"
    	"id": "publish",//will be returned as part of the generated id, in order to identify the response
    	"params":{
    		"channel":"chat",
    		"message":"hello",
    	}
    }
    client1.send(JSON.stringify(chatMessageObject));
    
  • Push messages from client2 to script “translate”:
    var chatMessageObject = {
    	"method":"translate", //the "translate" method is a user script that translates messages from English to French.
    	"id": "publish", //will be returned as part of the generated id, in order to identify the response
    	"params":{
    		"message": "hello"
    	}
    }
    client2.send(JSON.stringify(chatMessageObject));
    
  • Save the “translate” script under your account, which will get the message and translate it using the Microsoft translate API:
    var url = "http://api.microsofttranslator.com/v2/Ajax.svc/Translate";
    var token = "Bearer " + require("getTranslateToken.js").getToken();//getTranslateToken is another script that is responsible of refreshing the microsoft API token
    var http = require("http");
    var response = http.request({
      "url": url,
      "params":{
      	"text": text,
      	"from": "en",
      	"to": "fr"
      },
      "headers":{
      	"Authorization": token           
      }
    })
    
  • And then publish it, translated, on the channel “chat-translated”:
    var messaging = require("pubsub");
    messaging.publish("chat-translated", response.body, false);
    

Note that in the previous example the id “publish” is passed for each request. This is done in order to identify the messages received in response to a “publish” request. Each message sent over WebSockets will belong to a “session” identified by an “id”, returned by scriptr.io as a result of a successful WebSocket handshake (available in the “onopen” event). Each subsequent message (publish, script execution, …) will return a new “id” which will look like “sessionId-messageId”.
Users who care about identifying a message as a response to their own request will need to provide a message “id” along with the request. This id will be used to generate the response-id as “sessionId-userProvidedMessageId”. If the user is not interested in mapping requests to responses, he can omit the request-id, and each message he receives will be in the form “sessionId-randomId”.

Resources used for this tutorial:

[toggle title_open=”HTML” title_closed=”HTML” hide=”yes” border=”yes” style=”default” excerpt_length=”0″ read_more_text=”Read More” read_less_text=”Read Less” include_excerpt_html=”no”]HTML that produces the two chat windows[/toggle][toggle title_open=”FrontEnd JS” title_closed=”FrontEnd JS” hide=”yes” border=”yes” style=”default” excerpt_length=”0″ read_more_text=”Read More” read_less_text=”Read Less” include_excerpt_html=”no”]Client Code[/toggle][toggle title_open=”Scriptr.io scripts” title_closed=”Scriptr.io scripts” hide=”yes” border=”yes” style=”default” excerpt_length=”0″ read_more_text=”Read More” read_less_text=”Read Less” include_excerpt_html=”no”]Main translate scriptr.io API
Translate lib
[/toggle]