Wikia/app — pull request #795 by Monchoman45 (2013-05-13 22:00:29+00:00)
Title: Chat commands

Following up on https://github.com/Wikia/app/pull/764 (`/me`):

Commands traditionally (a la IRC) are evaluated by the sending client, which accepts responsibility for giving the server a fully qualified request. The intent is to allow clients to implement any commands they want in any format, and to keep the server relatively simple.

For example, per https://github.com/Wikia/app/pull/764#issuecomment-17609122, the server already has a method for a client to request a kick or a ban - a `/kick` command could be implemented easily by the client, accepting the name of the user to kick, forming a `KickCommand` model and sending it on the main socket. The only change the server should make would be to ensure that the requested user is actually in the room, which arguably it should do anyway.

Sender-side command execution has other benefits too - the sender would handle the problem of escapes (`//me` returning `/me` per https://github.com/Wikia/app/commit/7ae60466ba5b733c79c3489e163663af27581316), which simplifies the receiving end (particularly helpful to bots). It also addresses the problem of adding more commands (per https://github.com/Wikia/app/pull/724) and of being able to support more commands (per https://github.com/Wikia/app/commit/7ae60466ba5b733c79c3489e163663af27581316#L0R134) elegantly - the server can support a particular action, and the client can create an interface to that however it so chooses.

Toward that end, this pull request implements such a system as `NodeChatCommands`. It's a singleton (that can't be subclassed, because that would be silly), particularly to keep addition of new commands easy. Commands are added to `NodeChatCommands.commands`, and can be run with `NodeChatCommands.run`. Specifics are outlined in the comment above the definition (https://github.com/Monchoman45/app/commit/23f720036c3f1bea2319245ac28313616427ae1b#L0R954).

`NodeRoomController.sendMessage`'s functionality as a listener is now in `NodeRoomController.inputListener`, and `sendMessage` itself now accepts a string and directly sends it to the server. `inputListener` checks for commands and handles return values and escapes. `sendMessage` does not check for commands.

`/me` was an interesting first choice because it must be interpreted by the receiver (in IRC, `/me` is a [CTCP](http://enwp.org/Client-to-client_protocol) `ACTION`, but that's a different fish entirely). Since receiving `/me message` indicates something completely different now, I created a `MeMessage` model that subclasses `ChatMessage` and sets the property `me` to true. This is honored by `ChatView` and by `NodeChatCommands.commands.me`.

Also, if anyone is interested in doing more, `/away` is fairly popular and should be pretty straightforward to implement.