Skip to content
This repository has been archived by the owner on Oct 23, 2019. It is now read-only.

mccutchen/watercooler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

README


Introduction
------------------------------------------------------------------------

Watercooler is a web application that provides realtime group chat,
built with Python and the Django web programming framework.  This
document aims to be a high-level overview of its structure and
functionality (it will no doubt be long-winded and cover the wrong
details).

Watercooler has only been tested in Firefox on OS X and Windows and
Safari on OS X.  It has been designed to be completely functional
(though much less useful) with JavaScript disabled (ie, posts can
still be made, etc., but there would be no live updating of chat
pages).

Testing Watercooler by yourself requires using at least two separate
browsers, so that you can log in as two separate users to make posts
to the same conversation.  I've done this with Firefox and Safari as
well as just Firefox under two separate profiles.


Basic Structure
------------------------------------------------------------------------

Watercooler is a Django project, which means the source code follows
the same basic patterns as other Django projects.  At a basic level,
Django projects are defined by the following elements:

 * settings.py, which defines the settings for the project

 * models.py, which defines the data models used by the project in
   terms of Django's object-relational mapper (ORM)

 * urls.py, which defines the URL structure of the project, mapping
   URLs to view functions

 * views.py, which contains the view functions to which URLs are
   mapped by urls.py

Additionally, most Django projects, Watercooler included, will also
have the following:

 * a templates directory, which contains the templates used by the
   view functions to generate output

 * admin.py, which sets up Django's built-in administrative interface
   for a project's particular data models (as defined in models.py)

 * a media directory, which contains the static media (ie, CSS,
   JavaScript, images, etc.) used by the project.  These are generally
   not served by Django itself, but are instead served by another web
   server better suited for that task (eg, Apache, nginx, etc.).

A note about the concepts of projects vs. applications in Django: When
you read about Django, you will see that, generally speaking, a single
Django "project" is composed of one or more Django "applications"
(which can be shared between projects, ideally).  Watercooler, because
of its simplicity, is a single project and application (in the Django
sense) in one.


Django contrib apps used
------------------------------------------------------------------------

Watercooler takes advantage of some of Django's bundled contrib apps
to easily extend its functionality.  It uses the following apps:

 * django.contrib.admin, which provides a nice administrative
   interface to your data.

 * django.contrib.auth, which provides an authentication system for
   managing users (including logging them in and out and allowing them
   to register).

These apps in turn use the django.contrib.contenttypes and
django.contrib.sessions apps.


Settings
------------------------------------------------------------------------

Django projects usually keep their settings in a module called
'settings.py'.  For Watercooler, I have broken the settings up by
hostname to make deployment to different hosts (eg, my local dev
server and the remote production server) easiser.

So, in the Watercooler source code, there is a settings directory
which serves as a Python module.  The common settings shared by all
instances of Watercooler are contained in settings/__init__.py.
Host-specific settings are kept in Python files named for the hostname
to which they apply.  For example, dev server is named 'butter', so
the settings that apply to Watercooler on that server are in
settings/butter.py.


Chat pages
------------------------------------------------------------------------

The most complicated part of Watercooler is the functionality of the
individual chat pages.  Here is a basic explanation of how they work.

Chats are identified by their "slug" in URLs.  The slug is
automatically generated based on the name given to the chat when it is
created.  Each Chat is composed of zero or more Posts.  Posts are
associated with a particular User, were created at a particular date
and time, and have their content saved as plain text.

When a particular Chat's page is loaded, all of its Posts are stuffed
into a table with two columns: username and post content.  Initially,
the post content is plain text.

On page load, the following steps are taken:

 * MediaHandler (defined in media/js/mediahandler.js) is
   initialized

 * PostHandler (media/js/posthandler.js) is initialized

 * LayoutHandler (media/js/layouthandler.js) is initialized

Then, the PostHandler begins polling the server every two seconds to
get any new Posts made by other users and to get an updated list of
active and inactive Users for this particular Chat.


MediaHandler
------------------------------------------------------------------------

The MediaHandler object is responsible for transforming each Post's
plain text content into embedded multimedia objects when appropriate.
Each Post's content is run through the MediaHandler.handle method,
which simply looks for URLs.  If a URL is found, one of the following
steps is taken:

 * Image URLs (ie, those pointing to JPEG, GIF or PNG files) are
   transformed into inline image elements.

 * YouTube URLs are transformed into embedded YouTube videos.

 * MP3 URLs are transformed into embedded media players.

 * Any other URLs are transformed into hyperlink elements.

On initialization, MediaHandler iterates over each post currently on
the page and processes its content as described above.  Then, when any
new posts are added to the page (by the current user or other users),
those posts are also processed.


PostHandler
------------------------------------------------------------------------

When the PostHandler is initialized, it iterates through each Post on
the page and adds its timestamp (which is given in the Post's <tr>'s
class attribute) to a list of known timestamps.  It then sets up an
event listener on the post form that intercepts form submissions and
instead adds the post via an Ajax request to the server.  Finally, it
begins polling the server for updates every two seconds.

On every poll request, the PostHandler sends the latest timestamp that
it knows about and receives from the server a list of Posts made since
that timestamp and a list of active and inactive users.  It adds any
posts to the page (after having their content processed by the
MediaHandler) and passes the list of users to the UserHandler, which
updates the list of users in the sidebar.


LayoutHandler
------------------------------------------------------------------------

The LayoutHandler tries to fit the layout of the page to the size of
the user's browser window when the page is loaded.  This ensures that
the footer and post form are always at the bottom of the page,
available without scrolling.

This is, however, a brittle approach that breaks when the window is
resized (and probably suffers from other problems).


Flaws
------------------------------------------------------------------------

There are some flaws in Watercooler as it is currently constituted.
Some are simply features which have not been implemented, others are
problems for which a good solution has not yet been found.  Here are
those that I can think of off right now:

 * Private chats.  All chats created through the public web interface
   are public.  In a finished product, there would be private,
   password-protected chats that could be shared with a specific group
   of people (via automated email, presumably).  I felt this was out
   of the scope of the project.

 * Post dates and times.  At the moment, there is no date or time
   information displayed with the posts on chat pages, even though
   that data is readily available.  I should figure out a good way to
   make that info available when desired.

 * Chat archiving.  A chat page currently displays every post made in
   that chat.  This would get unweildy with large or long-lasting
   chats, so an interface for archiving chats should be implemented.

 * Chats with duplicate names.  Right now, if you try to create a chat
   with the same name as one that already exists, you are silently
   redirected to the existing chat's page.  Ideally, a new chat with
   an adjusted slug would be created instead.

 * The dynamic layout of chat pages (done by LayoutHandler) is brittle
   and flaky.  A better solution (preferably all CSS) would be nice.


Wrapping Up
------------------------------------------------------------------------

I'll add to this document as things occur to me.  Please let me know
if you have any questions or comments.  I'll be glad to answer them to
the best of my ability.


Will McCutchen
mccutchen@gmail.com

About

Web-based realtime multiuser chat (final project for CS 329E)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published