Giter VIP home page Giter VIP logo

python-chat-example's Introduction

10 Minute Chat in Python

A small example application using the flowthings.io platform

Installation

This application was built using Python 2.x and Bottle.

Within the project directory:

virtualenv env
. env/bin/activate
cp settings-template.py settings.py
## Update the settings.py file with your Flow account details
pip install -r requirements.txt
python 10minutechat.py

Browse to localhost:8100 (or whatever you set your host / port to).

Overview

The application demonstrates the following:

  • A Flow to which we will send new chat messages
  • A Flow from which we will receive chat messages
  • A Track between the above Flows, which also contains the content-filtering logic
  • A restricted Token object, which will be used for all participants of the chat room.

Code Walkthrough

The main code is within these files:

  • 10minutechat.py
  • views/room.tpl

The Python Client

The demo uses the flowthings.io Python Client, the Bottle web framework, and JavaScript.

We begin by setting up the Python library:

	user = ## your username
	master_token = ## your token

	creds = Token(user, master_token)
	api = API(creds, host="api.flowthings.io", secure=True)

We could put all of our chat rooms in our root Path, but to keep everything contained and organized we shall create a root path:

	app_path = "/%s/10minutechat" % (user)
	api.flow.create({'path': app_path})

This Flow won't itself hold any data. You can think of it as creating a directory on a Unix filesystem.

Creating the Send / Receive Flows

Each time a user requests a new Chat Room, we'll first pick a new random path, and create the Flows we need under the path:

	# Room Base Path
	random_path = ## create random string
    room_path = "%s/%s/" % (app_path, random_path
    api.flow.create({'path': room_path})

    # Create Flows
    send_flow_path = create_flow("%s/send" % room_path)
    receive_flow_path = create_flow("%s/receive" % room_path)

	api.flow.create({'path': send_flow_path, 'capacity': 0})
	api.flow.create({'path': receive_flow_path, 'capacity': 0})

We have a choice here regarding the capacity of these Flows. A Flow's capacity determines how many Drops will be persisted on the platform before old Drops are deleted. A capacity of 0 will prevent any Drops from being persisted, but they will still move through the system like any other Drop.

Creating the Track and Filtering Logic

We need to create a Track between the send and receive Flows, and attach our content filtering JavaScript.

	js_func = """function (input){
	    var acceptableWords = ['Loosely-Coupled Architecture', 'JSON'];

	    var text = input.elems.message.value;
	    var forbiddenWords = new RegExp('Enterprise Java Beans|XML','ig');

	    function randomAcceptableWord(){
		    var index = Math.floor(Math.random()*(acceptableWords.length)+0);
		    return acceptableWords[index];
	    }

	    text = text.replace(forbiddenWords, randomAcceptableWord());

	    input.elems.message.value = text
	    return input;
	  }"""

    api.track.create({'source': send_flow_path, 'destination': receive_flow_path,
                             'js': js_func})

The JavaScript snippet is executed whenever a chat message is sent. For each chat message, we scan the content for a list of "forbidden" words. When we detect one, we replace the word with a randomly-selected "authorized" word, before returning it. This "sanitized" Drop is delivered to the receive Flow for everyone to view.

Creating the Limited-access Token

We can use a Token to grant limited access to the chatroom, with a 10 minute expiry. We can't have users consuming messages that haven't been sanitized of course, so we grant write-only access to the send Flow. We also don't want users bypassing the content-filter, so we grant read-only access to the receive Flow.

Finally, we set an expiry time of 10 minutes in the future.

	token-object = api.token.create({
        "paths" : {
            send_path: {'dropRead': False, 'dropWrite':  True},
            receive_path: {'dropRead': True, 'dropWrite': False}
        },
        "duration" : 600000})

The client returns an object representing a Token. This string is what the chat users will use to authenticate. This way, we've sandboxed our users. We generate a URL for people to use, which includes the new token string:

	token-string = token-object["tokenString"]
	url = "http://%s:%s/room/join?room=%s" % (host, port, token_string)

WebSockets

On the JavaScript side, after page-load we set up a Web Sockets connection, using the Token String previously generated. Once authenticated, we can subscribe to all messages from the Receive Flow:

	request = $.ajax({
		        url: "https://{{ws_host}}/session",
		        beforeSend: function (req){
		    		req.setRequestHeader("X-Auth-Token", "{{token_string}}");
		    		req.setRequestHeader("X-Auth-Account", "{{flow_user}}");
		    		req.withCredentials = true
				},
		        type: "post",
		        dataType: 'json',
		        success: function(data){

		        	var sessionId = data["body"]["id"]
		        	var url = "ws://{{ws_host}}/session/" + sessionId + "/ws";

		        	connection = new WebSocket(url);

		        	connection.onopen = function () {
					  connection.send(subscribe());
					};
					connection.onerror = function (error) {
					  console.log('WebSocket Error ' + error);
					};
					connection.onmessage = function (e) {
					  var message = JSON.parse(e.data)
					  if (message.value){
					  	  console.log("Received: " + JSON.stringify(message.value))
						  var user = message.value.elems.user.value;
						  var content = message.value.elems.message.value;
						  addMessage(user,content)
					  }
					};
		        }
		    });

We can use the same connection to send chat messages:

	$("#chatForm").submit(function(event){

	    var username = $("#username").val()
	    var content = $("#content").val()

	    if (content != ''){
	    	var message = dropMessage(username, content)
		    connection.send(message);
		    $("#content").val('')
	    }

	    event.preventDefault();
	});

python-chat-example's People

Contributors

mattmorten avatar

Watchers

James Cloos avatar Ozgur avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.