JsChat Blog

JsChat is chat system based on JSON.

Code: github

Web Site: jschat.org

Twitter Auth, Mongo Logging and Tabs

JsChat now has Twitter Auth, logging with mongodb, and the web interface has tabs for switching between rooms.  Twitter auth and mongodb give JsChat persistence.

People can sign in with Twitter, join a set of rooms, then sign in from another computer without appearing to log off JsChat.  The user stays online until they’ve been idle for 7 days or they click Quit.

To get these features, install the following gems:

  • mongo
  • mongo_ext
  • twitter_oauth

Then set up an app on Twitter and add your keys to the config file.  The config file can be in /etc/jschat/config.json, and should look like this:

{
  "port": 6789,
  "ip": "0.0.0.0",
  "logger": logger,
  "max_message_length": 500,
  "tmp_files": "/tmp/file/path",
  "db_name": "jschat",
  "db_host": "localhost",
  "db_port": 27017,
  "db_username": "",
  "db_password": "",
  "twitter" { "key": "xxx", "secret": "xxx" }
}

All of the options are optional, so leave any out that you don’t need.  For example, the one we use on the JsChat server looks like this:

{ 
  "twitter": { "key": "xxx", "secret": "xxx" },
  "db_host": "swan.mongohq.com",
  "db_port": "27080",
  "db_username": "user",
  "db_password": "pass
}

Protocol Changes

The JsChat Protocol has been changed to include a time parameter in all messages.  That means the display style messages no longer contain the time, it’s at the top level instead:

{ 'display' => 'message', 'message' => { ... }, 'time' => 'Tue Mar 30 15:17:02 UTC 2010' }

Gem Released

I’ve bundled JsChat into a gem so you can install it with:

gem install jschat

This makes it possible to run JsChat from the command line:

  • jschat-server - runs the server
  • jschat-web - runs a web app
  • jschat-client - runs the console client

I’ve also added config files.  They’re in JSON format, and you need to double quote the keys.  The default locations are (client) ~/.jschat/config.json and (server) /etc/jschat/config.json.

Stateless Protocol: Complete

JsChat now has a stateless protocol.  This means you can register a cookie with the server that will persist a client connection across socket sessions.

The protocol works like this:

  1. Connect to a server and send a JSON string with protocol set to stateless
  2. The server will send back a cookie
  3. On every subsequent request, provide the cookie

Here’s a code example: stateless_example.rb

One of the reasons for doing this is it cuts down the web app’s complexity.  The old web app embedded an EventMachine module which maintained connections for each user with the server.

This actually duplicates functionality that is already in the JsChat server, and goes against the grain of the way I intended JsChat to function.  The original approach made it difficult to run multiple web app processes (for example, with Passenger).

JsChat is meant to be a very simple protocol that’s easy to implement.  The EventMachine session management approach was just a hack I did, reusing code from the console client.

The old web app was 440 lines of code, and it’s now 264.

Stateless Protocol

I’m working on making the JsChat protocol stateless.  This means that the web client’s complexity will be greatly reduced in the future.

I’m going to make the stateless mode optional, so clients can connect using sockets or single requests.

Clojure Bot

Here’s an example of a bot written with Clojure: Clojure JsChat Bot.  It might not be 100% idiomatic Clojure, but it shows that talking JsChat is simple in Clojure.

Clojure comes bundled with JSON libraries for creating and parsing JSON.  The parser returns a PersistentArrayMap: ((parsed-json "message") "message") accesses the message body element of a JsChat message.

JavaScript Bots

I’ve made an example of a JavaScript bot for JsChat.  You can run it using Rhino, and it uses Java’s sockets for connections:

$ rlwrap java -jar js.jar
Rhino 1.7 release 2 2009 03 22
js> load('bot.js')

Notice how simple the code for interpreting the protocol is.  I’ve used the same strategy as the JsChat client and server code, whereby methods are executed based on the hashes returned from the server: JsChat.Responses.Display[json.display]

Kev and his Emotes

Kev originally wanted us to build JsChat about 3 years ago.  We haven’t quite implemented his idea yet (which was about monetizing IRC-style chat), but he’s had a lot of ideas and feature suggestions for JsChat so far.  One that he was particularly concerned about was emoticons, so I included them on a rainy Sunday afternoon.

I just updated the web app with a command so you can list all of them.  Next time you’re in the web app, type /emotes and you’ll get a list of available emoticons.

Passenger/Rack Support

I’ve just checked in Passenger and Rack support with a config.ru sample into the JsChat repo.  It should now be easy to get JsChat working with Passenger if you use it on your servers.

I also made message submissions display in realtime in the web app’s chat transcript.  This means there’s instant feedback when a message is posted.

JsChat: Polling

People are repeatedly joining #jschat talking about the merits of polling.  Please read this before you do that, or you’re likely to get ignored:

  • Yes, I know about server-sent events and flash hacks that provide sockets
  • No, we’re not going to use Juggernaut
  • JsChat will gradually support native server-sent events (some browsers provide this already)
  • I used polling because it works on more devices and is cleaner
  • The web interface is only a small part of the system
  • Stop to consider the thought that’s been put into other aspects of the web interface