"use strict"; /** * Client class that implements the InstantChat protocol using WebSockets. * * Dispatches the following events which can be subscribed/unsubscribed using .on() and .off(): * - initialized: Connection to server has been established and initialized, ready to send messages. * - disconnected: Connection has been closed. * - connectionError: Some connection error occurred. * - receivedMessage: Chat message has been received. Data: object {from: 'username', text: 'text'} */ class Client extends EventDispatcher { constructor(wsUri, chatID, nickname) { super(); this.wsUri = wsUri; this.chatID = chatID; this.nickname = nickname; // Create WebSocket and set internal callbacks console.log("Initialize Client...") this.webSocket = new WebSocket(wsUri); this.webSocket.onopen = this._onSocketOpen.bind(this); this.webSocket.onclose = this._onSocketClose.bind(this); this.webSocket.onerror = this._onSocketError.bind(this); this.webSocket.onmessage = this._onSocketMessage.bind(this); } // Internal WebSocket event handlers _onSocketOpen(evt) { console.log("Connected to " + this.wsUri); this.sendInit(this.chatID, this.nickname); } _onSocketClose(evt) { console.log("Connection closed (code " + evt.code + ")."); this.dispatch("disconnected"); } _onSocketError(evt) { console.error("Connection error: ", evt); this.dispatch("connectionError"); } _onSocketMessage(evt) { console.log("Received: " + evt.data); this._parseMessage(evt.data); } /** * Sends an arbitrary command as JSON. * * commandObj: The command as an object ('action' specifies type of command). */ sendCommand(commandObj) { const commandJson = JSON.stringify(commandObj); console.log("Sending command: " + commandJson); this.webSocket.send(commandJson); } /** * Sends the 'init' command which sets up the session. Also sets the chat ID and nickname. * * chatID: The ID of the chat instance. * nickname: The user's nickname. */ sendInit(chatID, nickname) { this.sendCommand({ action: "init", chat_id: chatID, nickname: nickname, }); } /** * Sends the 'message' command which sends a chat message to the chat. * * msgText: The text of the chat message. */ sendChatMessage(msgText) { this.sendCommand({ action: "message", text: msgText, }); } /** * Parses an incoming JSON message and dispatches specific events. * * msgText: The content of the message as a JSON string. */ _parseMessage(msgString) { try { const msg = JSON.parse(msgString); switch (msg.type) { // Response to 'init' command (doesn't have much content, I guess) case "init": console.log("Got init response: ", msg); this.dispatch("initialized"); break; // Incoming chat message case "message": console.log("Received chat message from '" + msg.from + "', text '" + msg.text + "'"); this.dispatch("receivedMessage", { from: msg.from, text: msg.text, }); break; // TODO Topic change, user join/leave, error, ... default: console.error("Unknown message type '" + msg.type + "'"); } } catch (e) { console.error("Error parsing message JSON: " + e.message); } } }