Powerful Chat System – Lesson 2
Today we continue a series of articles on the creation of powerful chat system. Our second lesson will contain next elements: smart chat (ajax, with spam filtering – protection from the frequent messages). I have decided to make registration for next lesson. Hope that it is ok for you.
Today I have included next elements: chat processor, plus – slight corrections in our previous sources. All project is well structured: system classes is in ‘classes’ folder, stylesheets in ‘css’ folder, template files in ‘templates’ folder, and – new folder ‘js’ for javascript files.
Live Demo
download in package
Now – download the source files and lets start coding !
Step 1. SQL
This table has got minor changes. I have changed type of field ‘when’.
CREATE TABLE `cs_messages` ( `id` int(11) unsigned NOT NULL auto_increment, `sender` int(11) unsigned NOT NULL, `recipient` int(11) unsigned NOT NULL default '0', `message` VARCHAR(255) NOT NULL, `when` int(11) NOT NULL default '0', `room` int(5) unsigned NOT NULL default '0', `type` tinyint(1) unsigned NOT NULL default '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Step 2. HTML
This is main (index) page html markup:
templates/main_page.html
<!DOCTYPE html> <html lang="en" > <head> <title>Powerful Chat System - Lesson 2</title> <link href="css/main.css" rel="stylesheet" type="text/css" /> <script src="http://code.jquery.com/jquery-latest.min.js"></script> </head> <body> <header> <h2>Powerful Chat System - Lesson 2</h2> <a href="https://script-tutorials.com/powerful-chat-system-lesson-2/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a> </header> <div class="container"> {form} </div> <div class="container"> <h2>Main Chat Block</h2> <div class="chat_messages"> {chat} </div> {input} </div> </body> </html>
As you can see – I have changed our second container (which contains our ajax chat).
templates/login_form.html and templates/logout_form.html
These files haven’t changed since last time. Next one new template – chat form:
templates/chat.html
<form class="chat_submit_form"> <div><input type="text" name="message" /><input type="submit" value="Submit" name="Submit" /></div> <div> <h3 class="error">Some error occurs during sending message</h3> <h3 class="success">Message successfully sent</h3> <h3 class="protect">Please wait 5 secs before adding next message</h3> </div> </form> <script src="js/chat.js"></script>
Step 3. CSS
This file contains updated styles of our chat
css/main.css
/* page layout */ *{ margin:0; padding:0; } body { background-color:#eee; color:#fff; font:14px/1.3 Arial,sans-serif; } header { background-color:#212121; box-shadow: 0 -1px 2px #111111; display:block; height:70px; position:relative; width:100%; z-index:100; } header h2{ font-size:22px; font-weight:normal; left:50%; margin-left:-400px; padding:22px 0; position:absolute; width:540px; } header a.stuts,a.stuts:visited{ border:none; text-decoration:none; color:#fcfcfc; font-size:14px; left:50%; line-height:31px; margin:23px 0 0 110px; position:absolute; top:0; } header .stuts span { font-size:22px; font-weight:bold; margin-left:5px; } /* main styles */ .container { background-color: #222; color: #bbb; margin: 20px auto; overflow: hidden; padding: 20px; position: relative; width: 800px; } .container h2 { color: #fff; margin-bottom: 10px; } .column { float: left; width: 48%; } .column:first-child { margin-right: 4%; } .column > * { color: #ddd; margin-bottom: 10px; } .column h3 { color: #fff; } .login_form input,.login_form label { display: block; margin-bottom: 10px; } input[type=text], input[type=password], input[type=submit] { -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } input[type=text], input[type=password] { font-size: 16px; height: 30px; margin-right: 10px; width: 200px; } input[type=submit]{ cursor: pointer; font-size: 16px; font-weight: bold; height: 35px; padding: 5px; } /* chat block */ .chat_messages { border: 1px solid #888; box-shadow: 0 0 5px #AAA; color: #000; padding: 10px; } .chat_messages h2 { color: #fff; } .chat_messages .message { background-color: #fff; margin: 5px; padding: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } .chat_messages .message span { color: #444; font-size: 10px; margin-left: 10px; } .chat_submit_form { margin: 10px 0px; } .chat_submit_form div { float: left; width: 49%; } .chat_submit_form .error, .chat_submit_form .success, .chat_submit_form .protect { display: none; } .chat_submit_form .error { color: #f55; } .chat_submit_form .success { color: #5f5; } .chat_submit_form .protect { color: #55f; }
Step 4. JS
I have created first JS for our chat. At beginning – it contain one function for regular obtaining messages, and handler of form submitting.
js/chat.js
$(function() { getMessages = function() { $.getJSON('index.php?action=get_last_messages', function(data){ if (data.messages) { $('.chat_messages').html(data.messages); } // get recent chat messages in loop setTimeout(function(){ getMessages(); }, 5000); }); } getMessages(); $('.chat_submit_form').submit(function() { $.post('index.php', { message: $('.chat_submit_form input[name=message]').val() }, function(data){ if (data.result == 1) { $('.chat_submit_form .success').fadeIn('slow', function () { $(this).delay(1000).fadeOut('slow'); }); } else if (data.result == 2) { $('.chat_submit_form .protect').fadeIn('slow', function () { $(this).delay(1000).fadeOut('slow'); }); } else { $('.chat_submit_form .error').fadeIn('slow', function () { $(this).delay(1000).fadeOut('slow'); }); } } ); return false; }); });
Step 5. PHP
Now, lets review php sources:
index.php
<?php // set error reporting level if (version_compare(phpversion(), '5.3.0', '>=') == 1) error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED); else error_reporting(E_ALL & ~E_NOTICE); require_once('classes/Services_JSON.php'); require_once('classes/CMySQL.php'); // including service class to work with database require_once('classes/CLogin.php'); // including service class to work with login processing // login system init and generation code $sLoginForm = $GLOBALS['CLogin']->getLoginBox(); $sChat = '<h2>You do not have rights to use chat</h2>'; $sInput = ''; if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active' && $_SESSION['member_role']) { require_once('classes/CChat.php'); // including service class to work with chat // get last messages $sChat = $GLOBALS['MainChat']->getMessages(); if ($_GET['action'] == 'get_last_messages') { // regular updating of messages in chat $oJson = new Services_JSON(); header('Content-type: application/json'); echo $oJson->encode(array('messages' => $sChat)); exit; } // get input form $sInput = $GLOBALS['MainChat']->getInputForm(); if ($_POST['message']) { // POST-ing of message $iRes = $GLOBALS['MainChat']->acceptMessage(); $oJson = new Services_JSON(); header('Content-type: application/json'); echo $oJson->encode(array('result' => $iRes)); exit; } } // draw common page echo strtr(file_get_contents('templates/main_page.html'), array('{form}' => $sLoginForm, '{chat}' => $sChat, '{input}' => $sInput));
As you can see – I have added chat functionality today.
classes/CLogin.php
<?php class CLogin { // constructor function CLogin() { session_start(); } // get login box function function getLoginBox() { if (isset($_GET['logout'])) { // logout processing if (isset($_SESSION['member_name']) && isset($_SESSION['member_pass'])) $this->performLogout(); } if ($_POST && $_POST['username'] && $_POST['password']) { // login processing if ($this->checkLogin($_POST['username'], $_POST['password'], false)) { // successful login $this->performLogin($_POST['username'], $_POST['password']); header( "Location:{$_SERVER['REQUEST_URI']}" ); exit; } else { // wrong login return file_get_contents('templates/login_form.html') . '<h2>Username or Password is incorrect</h2>'; } } else { // in case if we already logged (on refresh page): if (isset($_SESSION['member_name']) && $_SESSION['member_name'] && $_SESSION['member_pass']) { $aReplaces = array( '{name}' => $_SESSION['member_name'], '{status}' => $_SESSION['member_status'], '{role}' => $_SESSION['member_role'], ); return strtr(file_get_contents('templates/logout_form.html'), $aReplaces); } // otherwise - draw login form return file_get_contents('templates/login_form.html'); } } // perform login function performLogin($sName, $sPass) { $this->performLogout(); // make variables safe $sName = $GLOBALS['MySQL']->escape($sName); $aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `cs_profiles` WHERE `name`='{$sName}'"); // $sPassEn = $aProfile['password']; $iPid = $aProfile['id']; $sSalt = $aProfile['salt']; $sStatus = $aProfile['status']; $sRole = $aProfile['role']; $sPass = sha1(md5($sPass) . $sSalt); $_SESSION['member_id'] = $iPid; $_SESSION['member_name'] = $sName; $_SESSION['member_pass'] = $sPass; $_SESSION['member_status'] = $sStatus; $_SESSION['member_role'] = $sRole; } // perform logout function performLogout() { unset($_SESSION['member_id']); unset($_SESSION['member_name']); unset($_SESSION['member_pass']); unset($_SESSION['member_status']); unset($_SESSION['member_role']); } // check login function checkLogin($sName, $sPass, $isHash = true) { // make variables safe $sName = $GLOBALS['MySQL']->escape($sName); $sPass = $GLOBALS['MySQL']->escape($sPass); $aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `cs_profiles` WHERE `name`='{$sName}'"); $sPassEn = $aProfile['password']; if ($sName && $sPass && $sPassEn) { if (! $isHash) { $sSalt = $aProfile['salt']; $sPass = sha1(md5($sPass) . $sSalt); } return ($sPass == $sPassEn); } return false; } } $GLOBALS['CLogin'] = new CLogin();
This class is updated too. I have decided to add ‘member_id’ in sessions too. It will useful afterward.
classes/CMySQL.php
This is database service class. Available in package. Pay attention – database settings of our project is in this file.
classes/Services_JSON.php
This is JSON service class. Available in package.
classes/CChat.php
<?php class CChat { // constructor function CChat() {} // add to DB message function acceptMessage() { $sName = $GLOBALS['MySQL']->escape($_SESSION['member_name']); $iPid = (int)$_SESSION['member_id']; $sMessage = $GLOBALS['MySQL']->escape($_POST['message']); if ($iPid && $sName != '' && $sMessage != '') { $sSQL = " SELECT `id` FROM `cs_messages` WHERE `sender` = '{$iPid}' AND UNIX_TIMESTAMP( ) - `when` < 5 LIMIT 1 "; $iLastId = $GLOBALS['MySQL']->getOne($sSQL); if ($iLastId) return 2; // as protection from very often messages $bRes = $GLOBALS['MySQL']->res("INSERT INTO `cs_messages` SET `sender` = '{$iPid}', `message` = '{$sMessage}', `when` = UNIX_TIMESTAMP()"); return ($bRes) ? 1 : 3; } } // return input text form function getInputForm() { return file_get_contents('templates/chat.html'); } // get last 10 messages function getMessages() { $sSQL = " SELECT `a` . * , `cs_profiles`.`name` , UNIX_TIMESTAMP( ) - `a`.`when` AS 'diff' FROM `cs_messages` AS `a` INNER JOIN `cs_profiles` ON `cs_profiles`.`id` = `a`.`sender` ORDER BY `a`.`id` DESC LIMIT 10 "; $aMessages = $GLOBALS['MySQL']->getAll($sSQL); asort($aMessages); // create list of messages $sMessages = ''; foreach ($aMessages as $i => $aMessage) { $sExStyles = $sExJS = ''; $iDiff = (int)$aMessage['diff']; if ($iDiff < 7) { // less than 7 seconds $sExStyles = 'style="display:none;"'; $sExJS = "<script> $('#message_{$aMessage['id']}').fadeIn('slow'); </script>"; } $sWhen = date("H:i:s", $aMessage['when']); $sMessages .= '<div class="message" id="message_'.$aMessage['id'].'" '.$sExStyles.'><b>' . $aMessage['name'] . ':</b> ' . $aMessage['message'] . '<span>(' . $sWhen . ')</span></div>' . $sExJS; } return $sMessages; } } $GLOBALS['MainChat'] = new CChat();
This is our new class for chat processor. For now – it contain only 3 functions: acceptMessage, getInputForm and getMessages.
Live Demo
download in archive
Conclusion
I will hope that our new series of articles of chat system creation will be useful and interesting for you. If you want to share your ideas, or you noticed any weakness – don’t hesitate to contact us. Good luck and welcome back!
I think you can use the native JSON function json_encode() for the PHP source code. It’s much faster than Service_JSON.
Hi Licson,
Yes, thanks for your note, I know it, I just need to install it (json) at current host.
hello admin did you have your update in video conferencing using HTML5?thanks in advance hoping for a reply….
Hello Ramil,
No, I didn’t, I didn’t implement a video chat feature as a part of our PowerfulChat, I might add it in the future
ok thanks admin…i might search for that part…ehehe…by the way shall i download the function json_encode() for the php??instead of your servcices_json().???thanks in advance admin
Hello ramil again,
Yes, sure, you can use default ‘json_encode’ function in the same way as we use Services_JSON::encode()
hey hii..!!…i want a bettr instant messaging source code .i mean not a chat room type…can i do ny changes in your scripts to get what i want …i need your help..thanx…
Hi Prabhat,
IM is always the part of this script
hey admin,what is your username and password
Hello Abhishek,
Admin login is the following: username = admin, password = password