/****************************************************************************** * * Copyright 2014 Paphus Solutions Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package com.paphus.sdk; import com.paphus.sdk.config.ChannelConfig; import com.paphus.sdk.config.UserConfig; import de.tavendo.autobahn.WebSocketConnection; import de.tavendo.autobahn.WebSocketConnectionHandler; /** * Connection class for a Live Chat, or chatroom connection. * A live chat connection is different than an SDKConnection as it is asynchronous, * and uses web sockets for communication. */ public class LiveChatConnection { protected boolean debug = false; protected ChannelConfig channel; protected UserConfig user; protected Credentials credentials; protected WebSocketConnection socket; protected LiveChatListener listener; protected boolean keepAlive = false; protected Thread keepAliveThread; /** * Create a new connection with the application credentials and the listener. * The listener will be notified asynchronously of messages and events. */ public LiveChatConnection(Credentials credentials, LiveChatListener listener) { this.credentials = credentials; this.listener = listener; } /** * Connection to the live chat server channel. * Validate the user credentials. * This call is asynchronous, any error or success with be sent as a separate message to the listener. */ public void connect(ChannelConfig channel, UserConfig user) { this.channel = channel; this.user = user; try { this.socket = new WebSocketConnection(); this.socket.connect("ws://" + this.credentials.host + this.credentials.app + "/live/chat", new WebSocketConnectionHandler() { @Override public void onOpen() { if (LiveChatConnection.this.user == null) { LiveChatConnection.this.socket.sendTextMessage("connect " + LiveChatConnection.this.channel.id + " " + LiveChatConnection.this.credentials.applicationId); } else { LiveChatConnection.this.socket.sendTextMessage( "connect " + LiveChatConnection.this.channel.id + " " + LiveChatConnection.this.user.user + " " + LiveChatConnection.this.user.token + " " + LiveChatConnection.this.credentials.applicationId); } } @Override public void onTextMessage(String text) { String user = ""; String message = text; int index = text.indexOf(':'); if (index != -1) { user = text.substring(0, index); message = text.substring(index + 2, text.length()); } if (user.equals("Online-xml")) { return; } if (user.equals("Online")) { LiveChatConnection.this.listener.updateUsers(message); return; } if (LiveChatConnection.this.keepAlive && user.equals("Info") && text.contains("pong")) { return; } if (user.equals("Info")) { LiveChatConnection.this.listener.info(text); return; } if (user.equals("Error")) { LiveChatConnection.this.listener.error(text); return; } LiveChatConnection.this.listener.message(text); } @Override public void onClose(int code, String reason) { LiveChatConnection.this.listener.message("Info: Closed"); LiveChatConnection.this.listener.closed(); } }); } catch (Exception exception) { throw new SDKException(exception); } } /** * Sent a text message to the channel. * This call is asynchronous, any error or success with be sent as a separate message to the listener. * Note, the listener will receive its own messages. */ public void sendMessage(String message) { checkSocket(); this.socket.sendTextMessage(message); } /** * Accept a private request. * This is also used by an operator to accept the top of the waiting queue. * This can also be used by a user to chat with the channel bot. * This call is asynchronous, any error or success with be sent as a separate message to the listener. */ public void accept() { checkSocket(); this.socket.sendTextMessage("accept"); } /** * Test the connection. * A pong message will be returned, this message will not be broadcast to the channel. * This call is asynchronous, any error or success with be sent as a separate message to the listener. */ public void ping() { checkSocket(); this.socket.sendTextMessage("ping"); } /** * Exit from the current private channel. * This call is asynchronous, any error or success with be sent as a separate message to the listener. */ public void exit() { checkSocket(); this.socket.sendTextMessage("exit"); } /** * Request a private chat session with a user. * This call is asynchronous, any error or success with be sent as a separate message to the listener. */ public void pvt(String user) { checkSocket(); this.socket.sendTextMessage("pvt: " + user); } /** * Boot a user from the channel. * You must be a channel administrator to boot a user. * This call is asynchronous, any error or success with be sent as a separate message to the listener. */ public void boot(String user) { checkSocket(); this.socket.sendTextMessage("boot: " + user); } /** * Send a private message to a user. * This call is asynchronous, any error or success with be sent as a separate message to the listener. */ public void whisper(String user, String message) { checkSocket(); this.socket.sendTextMessage("whisper:" + user + ": " + message); } /** * Disconnect from the channel. */ public void disconnect() { this.keepAlive = false; if (this.keepAliveThread != null) { this.keepAliveThread.interrupt(); } if (this.socket != null) { this.socket.disconnect(); } } protected void runKeepAlive() { this.keepAliveThread = new Thread() { public void run() { while (keepAlive) { sendMessage("ping"); try { Thread.sleep(600000); } catch (InterruptedException exception) { return; } } } }; this.keepAliveThread.start(); } public boolean isDebug() { return debug; } /** * Enable debugging messages (logged to System.out). */ public void setDebug(boolean debug) { this.debug = debug; } /** * Return the current channel. */ public ChannelConfig getChannel() { return channel; } protected void setChannel(ChannelConfig channel) { this.channel = channel; } /** * Return the current user. */ public UserConfig getUser() { return user; } protected void setUser(UserConfig user) { this.user = user; } /** * Return the current application credentials. */ public Credentials getCredentials() { return credentials; } protected void setCredentials(Credentials credentials) { this.credentials = credentials; } public LiveChatListener getListener() { return listener; } public void setListener(LiveChatListener listener) { this.listener = listener; } /** * Return if the connection will be kept alive, and not allowed to timeout due to inactivity. */ public boolean isKeepAlive() { return keepAlive; } /** * Set if the connection should be kept alive, and not allowed to timeout due to inactivity. */ public void setKeepAlive(boolean keepAlive) { this.keepAlive = keepAlive; if (this.keepAlive) { runKeepAlive(); } else if (this.keepAliveThread != null) { this.keepAliveThread.interrupt(); this.keepAliveThread = null; } } protected void checkSocket() { if (this.socket == null) { throw new SDKException("Not connected"); } } }