Article Image
Article Image
read

In my CPSC350 course we learned about SocketIO. I really enjoyed the SocketIO assignment because I always wondered how a chatroom worked. Although, I found the assignment to be one of my more difficult ones to complete, it was not to hard to figure out. Once I figured out how the data is retreived and send between the functions I was easily able to complete the assignment. In the HTML file the Angular JS directive sends information to the Javascript file which then passed the information to the Python file, the information then makes its way back to the Javascript file and would then be outputted to the HTML file. Each socketio function in the Javascript file updates the screen without consistently reloading the site, thus, quickly and efficiently displaying information to the user.

SocketIO Pt1 Rudiment:

SocketIO Pt1 Chatroom

Python File

#server.py

import os
import uuid
import psycopg2
import psycopg2.extras
from flask import Flask, session
from flask.ext.socketio import SocketIO, emit

app = Flask(__name__, static_url_path='')
app.config['SECRET_KEY'] = 'secret!'

socketio = SocketIO(app)

messages = []
users = {}

def connectToDB():
  connectionString = 'dbname=space user=astro password=astro123 host=localhost'
  print connectionString
  try:
    return psycopg2.connect(connectionString)
  except:
    print("Can't connect to database")

@socketio.on('connect', namespace='/iss')
def makeConnection():
    print('connected')
    conn = connectToDB()
    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    
    cur.execute("SELECT username, message FROM messages JOIN users ON messages.userid = users.id")
    msgs = cur.fetchall()
    conn.commit()
    
    session['uuid'] = uuid.uuid1()        
            
    for msg in msgs:
        tmp = {'text':msg['message'], 'name':msg['username']}
        emit('message', tmp)
            
        
@socketio.on('identify', namespace = '/iss')
def on_identify(person):
    print('identify ' + person)
    
@socketio.on('login', namespace='/iss')
def on_login(username, password):
    conn = connectToDB()
    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    print ('login' + username + password)
    
    session['username']=username
    users[session['uuid']]={'username': username}
    
    try:
        query = cur.mogrify("SELECT * FROM users WHERE username = %s AND password = crypt(%s, password) " , (users[session['uuid']]['username'], password))
        cur.execute(query)
        results=cur.fetchall()
        conn.commit()
        print (results)
        
        #Check if there is a result 
        if (cur.rowcount==1):
            print('connected roster')
            print(session['uuid'])
            print(users[session['uuid']]['username'])
            print("ida")
            
            emit('loggedin', users[session['uuid']]['username'])
            
            tmp = {'text':"is now connected", 'name':users[session['uuid']]['username']}
            emit('message', tmp, broadcast=True)
            
        #Incorrect password or not a user
        else:
            print("Invalid username or password!")
            conn.rollback()
        
    except:
        print("Error logging in!")
        conn.rollback()
    
    conn.commit()    

@socketio.on('message', namespace='/iss')
def new_message(message1):
    conn = connectToDB()
    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    
    try:
        print(users)
        print(session['uuid'])
        print("idb")
        query = cur.mogrify("""INSERT INTO messages(message, userid) VALUES(%s, (SELECT id FROM users WHERE username = %s))""", (message1, users[session['uuid']]['username']))
        print(query)
        cur.execute(query)
        conn.commit()
        tmp = {'text':message1, 'name': users[session['uuid']]['username']}
        emit('message', tmp, broadcast=True)
        
    except:
        print("Error messaging!")
        conn.rollback()
    
    conn.commit()
    
@socketio.on('search', namespace='/iss')
def search(term):
    conn = connectToDB()
    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

    try:
        print("hi")
        query = cur.mogrify("SELECT username, message FROM messages JOIN users ON messages.userid = users.id WHERE messages.message LIKE '%%%s%%' OR users.username LIKE '%%%s%%'" % (term, term, ))
        print(query)
        cur.execute(query)
        results = cur.fetchall()
        print(results)
        conn.commit()
        
    except:
        print("error searching")
        conn.rollback()
    
    emit('clear')

    for r in results:
        tmp = {'message1':r['message'], 'user':r['username']}
        emit('found', tmp)

@socketio.on('disconnect', namespace='/chat')
def on_disconnect():
    print 'disconnect'

@app.route('/')
def mainIndex():
    print 'in hello world'
    return app.send_static_file('index.html')
    
@app.route('/js/<path:path>')
def static_proxy_js(path):
    # send_static_file will guess the correct MIME type
    return app.send_static_file(os.path.join('js', path))
    
@app.route('/css/<path:path>')
def static_proxy_css(path):
    # send_static_file will guess the correct MIME type
    return app.send_static_file(os.path.join('css', path))
    
@app.route('/img/<path:path>')
def static_proxy_img(path):
    # send_static_file will guess the correct MIME type
    return app.send_static_file(os.path.join('img', path))

# start the server
if __name__ == '__main__':
        socketio.run(app, host=os.getenv('IP', '0.0.0.0'), port =int(os.getenv('PORT', 8080)), debug=True)

SQL file

#space.sql

DROP DATABASE IF EXISTS space;
CREATE DATABASE space;

DROP ROLE IF EXISTS astro;
CREATE ROLE astro WITH password 'astro123' LOGIN;
\c space

CREATE EXTENSION pgcrypto;

DROP TABLE IF EXISTS users;
CREATE TABLE users (
    id serial NOT NULL,
    username text NOT NULL,
    password text NOT NULL,
    PRIMARY KEY(id)
);

GRANT ALL ON users TO astro;
GRANT ALL ON users_id_seq TO astro;

DROP TABLE IF EXISTS messages;
CREATE TABLE messages(
    id serial NOT NULL,
    message varchar(256) NOT NULL,
    userid int NOT NULL,
    PRIMARY KEY(id),
    
    CONSTRAINT user_id_fk
    FOREIGN KEY (userid)
    REFERENCES users (id)
);

GRANT ALL ON messages TO astro;
GRANT ALL ON messages_id_seq TO astro;
GRANT ALL ON messages_userid_seq TO astro;

INSERT INTO users(username, password) VALUES('chelsea', crypt('chelsea', gen_salt('bf')));
INSERT INTO users(username, password) VALUES('raz', crypt('raz', gen_salt('bf')));
INSERT INTO users(username, password) VALUES('raze', crypt('raze', gen_salt('bf')));

INSERT INTO messages(message, userid) VALUES('Test1', (SELECT id FROM users WHERE username = 'chelsea'));
INSERT INTO messages(message, userid) VALUES('Test2', (SELECT id FROM users WHERE username = 'chelsea'));
INSERT INTO messages(message, userid) VALUES('Test3', (SELECT id FROM users WHERE username = 'raze'));
INSERT INTO messages(message, userid) VALUES('Test4', (SELECT id FROM users WHERE username = 'raz'));

Javascript File

#controller.js

function login(showhide){
    if(showhide == "show"){
        document.getElementById('popupbox').style.visibility="visible";
        document.getElementById('sendbox').style.visibility="hidden";
        document.getElementById('searchbox').style.visibility="hidden";
    }else if(showhide == "hide"){
        document.getElementById('popupbox').style.visibility="hidden"; 
        document.getElementById('sendbox').style.visibility="visible";
        document.getElementById('searchbox').style.visibility="visible";
    }
}

var ISSChatApp = angular.module('ISSChatApp', []);

ISSChatApp.controller('ChatController', function($scope){
    var socket = io.connect('https://' + document.domain + ':' + location.port + '/iss'); 
    
    $scope.messages = [];
    $scope.found = [];
    $scope.name = '';
    $scope.text = '';
    
    socket.on('connect', function(){
        console.log('connected');
    });
    
    $scope.login2 = function login2() {
        console.log("Trying to log in");
        socket.emit('login', $scope.name2, $scope.password);
    };
    
    socket.on('loggedin', function(username){
        console.log('login hidden');
        login('hide');
        $scope.name = username;
        $scope.$apply();
        
    });
    
    $scope.setName = function setName() {
        console.log('setting name');
        $scope.name=$scope.name2;
    };
    
    $scope.send2 = function send2(){
        console.log('Sending message: ', $scope.text);
        socket.emit('message', $scope.text);
        $scope.text = '';
    };
    
    socket.on('message', function(msg){
        console.log('messaging');
        $scope.messages.push(msg);
        $scope.$apply();
        var elem = document.getElementById('msgpane');
        elem.scrollTop = elem.scrollHeight;
    });
    
    $scope.searching = function searching() {
        console.log("Searching for " + $scope.term);
        socket.emit('search', $scope.term);
    };
    
    socket.on('found', function(msg){
        console.log('print results');
        $scope.found.push(msg);
        $scope.$apply();
        var elem = document.getElementById('msgpane2');
        elem.scrollTop = elem.scrollHeight;
    });
    
     socket.on('clear', function(){
        console.log('clear');
        $scope.found = [];
        $scope.$apply();
     });
     
});
Blog Logo

Chelsea Irizarry


Published

Image

Chelsea Irizarry

A CPSC350 blog

Back to Overview