Catbox Console Client in Python

created by Senso
(recipe) by Senso (1.2 d) (print)   (I like it!) 1 C! Tue Mar 18 2008 at 16:42:31

C.C.C.P.

CCCP is a console chatterbox client written in Python, allowing you to chat with your fellow noders without opening a web browser. It is platform-independent and should run without any problem on Windows, Linux and OSX.

You will need to install the Python interpreter, which is available for free here: http://www.python.org/download/

Install it, copy/paste the following code into a text file and save it with a .PY extension (ex. catbox.py). You can run the script by double-clicking on it or using the following command, in xterm, command.com or whatever:
C:> python catbox.py

Configuration
There is one optional parameter (PROXY) that you will have to change if you are behind a proxy - put its URL and port. It currently does not support HTTPS proxies or any kind of authentication. I may add that later.

Usage
Type your message, press enter to send it. Press enter on an empty line to refresh the chat. To quit, press CTRL-C or type "/quit" like in IRC.

History
v1.0 - Initial buggy release.
v1.1 - Various bugfixes. Removed the plaintext password from the code.
v1.2 - Now supports sending HTML entities and decoding most of those too.
v1.3 - Password prompt now uses getpass().
v1.4 - Will exit if the wrong username/password is entered.
v1.5 - Current. Fixed the posting bug many of you experienced. /msg me if there's any issue.




#!/usr/bin/env python
# Version 1.5

import urllib, urllib2, cookielib
import time, re, getpass
from xml.dom.minidom import parseString
from htmlentitydefs import name2codepoint, codepoint2name

PROXY = ""

cj = cookielib.CookieJar()

class Connection:
  def proxySet(self):
    if PROXY == "":
      self.opener = urllib2.build_opener(urllib2.HTTPHandler, 
        urllib2.HTTPCookieProcessor(cj))
    else: 
      self.opener = urllib2.build_opener(
      urllib2.ProxyHandler({"http" : PROXY}), 
          urllib2.HTTPHandler, urllib2.HTTPCookieProcessor(cj))

    urllib2.install_opener(self.opener)
    return self.opener
    
  def login(self, usr, passwd):
    self.opener = self.proxySet()
    
    self.data = {'node_id':124, 'op':'login', 'user':usr, 'passwd':passwd, 
        'expires':'+10y', 'login':'Login', '.cgifields':'expires'}

    self.r = self.opener.open("http://everything2.com/index.pl", urllib.urlencode(self.data))
  
    return self.r
  
  def post(self, msg):
    self.proxySet()
    
    self.url = 'http://everything2.com/index.pl?node_id=1873513&mode=message&%s' % (urllib.urlencode({'msgtext':msg}),)
    
    self.r = urllib2.urlopen(self.url)
    
  def grabBox(self):
    self.proxySet()
    
    # Will switch to the Universal ticker but it seems this one gets more messages.
    self.url = urllib2.urlopen("http://everything2.com/index.pl?node=chatterbox+xml+ticker")
    self.xml = self.url.read()
    
    self.xml = re.sub('(<a).+?(\' >)', '[', self.xml)  # Removes hyperlinks
    self.xml = re.sub('<\/a>', ']', self.xml)      # Removes link end tag 
    
    self.lister = []
    
    self.dom1 = parseString(self.xml)
    for i in self.dom1.documentElement.getElementsByTagName("message"):
      self.author = i.getAttribute("author").encode('latin-1')
      self.time = i.getAttribute("time")
      self.time = time.mktime(time.strptime(self.time, "%Y-%m-%d %H:%M:%S"))
      self.message = i.firstChild.data[1:].encode('latin-1')
      
      self.lister.append((self.author, self.message, self.time))    

    self.dom1.unlink()
    
    return self.lister

class Chat:
  def __init__(self): pass
  
  def htmlentitydecode(self, s):
      return re.sub('&(%s);' % '|'.join(name2codepoint), 
              lambda m: unichr(name2codepoint[m.group(1)]), s)
  
  def show(self, chatter):
    self.chatter = chatter
    self.now = time.mktime(time.localtime()) - 420.0
    
    for i in self.chatter:
      if i[2] >= self.now: print "<%s> %s\n" % (i[0], self.htmlentitydecode(i[1]))
    
if __name__ == '__main__':
  try:
    usr = raw_input("Username: ")
    passwd = getpass.getpass()
		
    welp = Connection()
    login = welp.login(usr, passwd)
    resp = login.info()
    if resp['Set-Cookie'].find("userpass=") == -1:
      print "Wrong username or password."
    else:
      ch = Chat()
  		
      while 1:
        chat = welp.grabBox()
        ch.show(chat)
        hurr = raw_input("> ")
        if hurr == "/quit": break
        elif hurr != '': welp.post(hurr)
			
  except KeyboardInterrupt: print "\nExiting..."
Y'know, if you log in, you can write something here, or contact authors directly on the site. Create a New User if you don't already have an account.