Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- app.js
- $(document).ready(function() {
- /*
- Assigning element IDs to variables
- */
- var sendButton = $('#snd');
- var msg = $('#msg');
- var messages = $('#messages_list');
- var my_status = $('#my_status');
- var typing = $('#typing');
- var options = $('#attachment_options');
- var chat_window = $('#chat_window');
- /*
- Prepare notification sound for playing
- */
- var notify_sound = new Howl({
- src: ['./assets/sounds/notify2.mp3'],
- volume: 1.0 //set to full volume
- });
- /*
- Disabling Send button on page load
- */
- disable_button();
- /*
- Setting up variables required for making the connection
- */
- var conn = new WebSocket('ws://192.168.0.100:3000'); //Change the ws address to your address
- var active = 0; //Variable to hold the current connection status
- var remoteAddress;
- /*
- Opening the connection to the socket
- */
- conn.onopen = function(e) {
- my_status.addClass('i_am_online'); //Sets the user icon to green
- active = 1; //Sets to 1 to denote connection is open
- conn.send(JSON.stringify({
- action: 'getReady' //Fetching the remote address and messages of the current user
- }));
- };
- /*
- Handling messages received
- */
- conn.onmessage = function(e) {
- var obj = JSON.parse(e.data);
- var type = obj.type;
- var userAddress = obj.ip;
- var unreadableTimeStamp = parseInt(obj.times);
- /**
- * Preparing Human readable timestamp
- */
- var time = moment(unreadableTimeStamp).calendar(null, {
- sameDay: '[Today at] HH:mm',
- nextDay: '[Tomorrow]',
- nextWeek: 'dddd',
- lastDay: '[Yesterday at] HH:mm',
- lastWeek: '[Last] dddd',
- sameElse: 'DD/MM/YYYY'
- });
- /*
- Handling server responses
- */
- if(type == "getUserAddress") {
- remoteAddress = userAddress;
- }
- //else
- //if(type == "fetch_count") {
- // msg_fetched_count = obj.count;
- //}
- else
- if(type == "userJoin") {
- messages.append('<li class="user_connect"><p class="message">'+ obj.ip +' '+ obj.message +'</p></li>');
- }
- else
- if(type == "userLeft") {
- messages.append('<li class="user_disconnect"><p class="message">'+ obj.ip +' '+ obj.message +'</p></li>');
- }
- else
- if(type == "typingOn") {
- typing.html(obj.ip + obj.message).fadeIn('fast');
- }
- else
- if(type == "typingOff") {
- typing.html('').fadeOut('fast');
- }
- else
- if(type == "user"){
- if(userAddress == remoteAddress) {
- typing.html('').fadeOut('fast');
- messages.append('<li class="self" id="'+obj.id+'"><p class="message">'+ obj.message + '</p><p class="time">' + time +'</p></li><p class="username_self">' + userAddress + '</p>');
- }
- else {
- typing.html('').fadeOut('fast');
- messages.append('<li class="other" id="'+obj.id+'"><p class="message">' + obj.message + '</p><p class="time">' + time + '</p></li><p class="username_other">' + userAddress + '</p>');
- if(obj.play != "no") {
- notify_sound.play(); //Play sound for arriving messages only
- }
- }
- }
- //Scroll the window to top automatically on new message
- chat_window.animate({scrollTop: chat_window.get(0).scrollHeight}, 1000);
- };
- /*
- Closing connection to socket
- */
- conn.onclose = function(e) {
- my_status.removeClass('i_am_online');
- active = 0;
- };
- /**
- * The following part manages the basic chat interface.
- * It handles primarily the DOM
- */
- /*
- Toggle the attachment container view
- */
- $('#attachment').click(function (e) {
- options.slideToggle("slow");
- $(this).toggleClass("option-active");
- e.stopPropagation();
- });
- options.click(function (e) {
- e.stopPropagation();//Prevent closing of container on click within it
- });
- $('body').click(function (e) {//Close container if click/tap on body is received
- options.slideUp();
- $('#attachment').removeClass("option-active");
- });
- /*
- Emergency Exit Procedure
- */
- $('#exit').click(function() {
- window.location.replace('http://www.google.com');
- });
- var isTyping = false;
- var timeout = undefined;
- function timeoutFunction() {
- isTyping = false;
- conn.send(JSON.stringify({
- action: 'typing-ended'
- }));
- }
- /*
- Preventing blank input and handling {user} is typing functionality6
- */
- msg.on('keyup', function(e) {
- if ('' != msg.val()) {
- enable_button(); //Enable send button if message content is not empty
- if(isTyping == false) {
- isTyping = true;
- conn.send(JSON.stringify({
- action: 'typing-started'
- }));
- timeout = setTimeout(timeoutFunction, 2000);
- }
- else {
- clearTimeout(timeout);
- timeout = setTimeout(timeoutFunction, 2000);
- }
- }
- else{
- disable_button();
- }
- });
- /*
- Handling message sending
- */
- sendButton.click(function() {
- if (!sendButton.hasClass('active')) {
- return;
- }
- var thread = msg.val();
- //console.log(thread);
- if(active == 1) {
- conn.send(JSON.stringify({
- action: 'sending',
- msg: thread
- }));
- // empty message text area
- msg.val('');
- disable_button();
- }
- else {
- alert('There seems to be a problem with your connection!\nCheck your internet connection and reload the page.');
- }
- });
- /*
- Load previous messages
- */
- chat_window.scroll(function() {
- var offset;
- var pos = chat_window.scrollTop();
- if (pos == 0){
- offset = messages.find('.self,.other').eq(0).attr("id");
- $('#load_previous').css('display', 'block');
- conn.send(JSON.stringify({
- action: 'load_older',
- start: offset
- }));
- }
- });
- /*
- Enable button function
- */
- function enable_button() {
- sendButton.css('cursor', 'pointer').addClass('active');
- }
- /*
- Disable button function
- */
- function disable_button() {
- sendButton.css('cursor', 'default').removeClass('active');
- }
- });
- chat.php
- <?php
- namespace MyApp;
- use Ratchet\MessageComponentInterface;
- use Ratchet\ConnectionInterface;
- use Emojione\Client;
- use Emojione\Ruleset;
- use \PDO;
- use \PDOException;
- class Chat implements MessageComponentInterface {
- protected $clients;
- /**
- * @var \Emojione\Client
- */
- private $emojioneClient;
- private $dbh;
- public function __construct() {
- $this->clients = new \SplObjectStorage;
- /**
- * Following for setting up conversion and display of native and ascii emojis
- */
- $this->emojioneClient = new Client(new Ruleset());
- $this->emojioneClient->imageType = 'png';
- $this->emojioneClient->imagePathPNG = './assets/png/';
- $this->emojioneClient->ascii = true;
- // Open connection to Database
- $this->connect();
- }
- public function onOpen(ConnectionInterface $conn) {
- // first, you are sending to all existing users message of 'new'
- foreach ($this->clients as $client) {
- $client->send(json_encode(array('ip' => $conn->remoteAddress, 'message' => 'online', 'type' => 'userJoin', 'times' => round(microtime(true) * 1000))));
- }
- // then,
- // Store the new connection to send messages to later
- $this->clients->attach($conn);
- my_log("New connection! ({$conn->remoteAddress})");
- }
- public function onMessage(ConnectionInterface $from, $msg) {
- $data = $this->parseMessage($msg);
- $numRecv = count($this->clients) - 1;
- my_log(sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
- , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's'));
- if($data->action === "getReady") {
- foreach ($this->clients as $client) {
- if($from === $client) {
- $client->send(json_encode(array('ip' => $from->remoteAddress, 'type' => 'getUserAddress', 'times' => round(microtime(true) * 1000))));
- // Fetch messages here
- $encoded_JSON_Array = $this->fetchMessages();
- $decoded_JSON_Array = json_decode($encoded_JSON_Array, true);
- foreach ($decoded_JSON_Array as $row) {
- $client->send(json_encode(array('id' => $row['id'], 'ip' => $row['ip'], 'message' => $this->parseEmojiToImage($row['message']), 'type' => $row['type'], 'times' => $row['times'], 'play' => 'no')));
- }
- }
- }
- }
- else
- if($data->action === "load_older") {
- foreach ($this->clients as $client) {
- if ($from === $client) {
- $offset = $data->start;
- $encoded_JSON_Array = $this->fetchMessages($offset);
- $decoded_JSON_Array = json_decode($encoded_JSON_Array, true);
- foreach ($decoded_JSON_Array as $row) {
- $client->send(json_encode(array('id' => $row['id'], 'ip' => $row['ip'], 'message' => $this->parseEmojiToImage($row['message']), 'type' => $row['type'], 'times' => $row['times'], 'play' => 'no')));
- }
- }
- }
- }
- else
- if($data->action === "typing-started") {
- foreach ($this->clients as $client) {
- if($from !== $client){
- $client->send(json_encode(array('ip' => $from->remoteAddress, 'message' => ' is typing...', 'type' => 'typingOn', 'times' => round(microtime(true) * 1000))));
- }
- }
- }
- else
- if($data->action === "typing-ended") {
- foreach ($this->clients as $client) {
- if($from !== $client){
- $client->send(json_encode(array('ip' => $from->remoteAddress, 'message' => ' stoped typing...', 'type' => 'typingOff', 'times' => round(microtime(true) * 1000))));
- }
- }
- }
- else
- if($data->action === "sending") {
- $thread = $this->parseEmojiToStr($data->msg);
- foreach ($this->clients as $client) {
- $client->send(json_encode(array('ip' => $from->remoteAddress, 'message' => $this->parseEmojiToImage($thread), 'type' => 'user', 'times' => round(microtime(true) * 1000))));
- }
- // here you must save messages to the database
- my_log("Saving message to database: $thread");
- $this->insertData($from->remoteAddress, $thread, '', round(microtime(true) * 1000));
- }
- }
- public function onClose(ConnectionInterface $conn) {
- // The connection is closed, remove it, as we can no longer send it messages
- $this->clients->detach($conn);
- //send to others clients message about disconnected user
- foreach ($this->clients as $client) {
- $client->send(json_encode(array('ip' => $conn->remoteAddress, 'message' => 'offline', 'type' => 'userLeft', 'times' => round(microtime(true) * 1000))));
- }
- my_log("Connection {$conn->remoteAddress} has disconnected");
- }
- public function onError(ConnectionInterface $conn, \Exception $e) {
- my_log("An error has occurred: {$e->getMessage()}");
- $conn->close();
- }
- /* CUSTOM FUNCTIONS */
- public function parseMessage($msg) {
- return json_decode($msg);
- }
- public function parseEmojiToStr($str) {
- return $this->emojioneClient->toShort($str);
- }
- public function parseEmojiToImage($str) {
- return $this->emojioneClient->shortnameToImage($str);
- }
- public function connect() {
- $hostname = 'localhost';
- $dbname = 'cryptoIM';
- $username = 'root';
- $password = '';
- try {
- $this->dbh = new PDO("mysql:host=$hostname; dbname=$dbname", $username, $password);
- $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- }
- catch(PDOException $e) {
- echo('ERROR: ' . $e->getMessage());
- }
- }
- public function insertData($username, $messagetxt, $attachmentURI, $unixtime) {
- $query = $this->dbh->prepare("INSERT INTO inbox(users, message, attachmentURI, timestamps) VALUES (:username, :messagetxt, :attachmentURI, :unixtime)");
- $query->execute(array(
- ":username" => $username,
- ":messagetxt" => $messagetxt,
- ":attachmentURI" => $attachmentURI,
- ":unixtime" => $unixtime
- ));
- }
- public function fetchMessages($index = NULL) {
- $message_list = array();
- $query = '';
- // Fetching only last 10 messages
- if($index != NULL) {
- $query = $this->dbh->prepare("SELECT * FROM (SELECT * FROM inbox ORDER BY id DESC LIMIT $index, 10) tmp ORDER BY id ASC");
- $query->execute();
- }
- else {
- $query = $this->dbh->prepare("SELECT * FROM (SELECT * FROM inbox ORDER BY id DESC LIMIT 10) tmp ORDER BY id ASC");
- $query->execute();
- }
- while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
- $message_list[] = array('id' => $row['id'], 'ip' => $row['users'], 'message' => $row['message'], 'type' => 'user', 'times' => $row['timestamps']);
- }
- return json_encode($message_list);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement