#!/usr/bin/python
# Moods client for Ralph Meijer's moods agent.
#
# Most recent version can be found at:
# http://www.ressukka.net/jabber/moods
# 
# Or with subversion client from:
# $HeadURL: http://svn.ressukka.net/jabber/moods/emotion.py $
#
# Written by Sami Haahtinen
#     JID/E-Mail: ressu@ressukka.net
#
# $Id: emotion.py 6 2004-03-09 10:26:28Z ressu $
# Changes:
# 0.6
#	* Update namespace to match JEP-0107
#
# 0.5
#	* More protocol updates
#	* Removed the usage of calendar module which doesn't work like it used
#	  to in python 2.3
#
# 0.4
#	Added readline support, now you have tab completion.
#
# 0.3
#	added support for available moods xml file.
#
# 0.2
#       Updated the protocol
#
# 0.1
#       Initial release

import sys
import jabber
import string
import xmlstream
from xml.dom.minidom import parse, parseString
from urllib2 import urlopen
import posix
import time
import readline

VERSION = 0.5

# I'll move these later on to a common config file.
jabber_host = "example.net"
jabber_user = "username"
jabber_password = "password"
jabber_resource = "set_moods_py"

# Define a name for mood file
mood_file = "moods.xml"

# Per default, don't fetch the moods file.
moods_need_fetch = False

# Default location to fetch a mood file from if it doesn't exist.
default_moods_url = "http://ralphm.net/available_moods"

# Shamelessly rip these off from ralphs script =)
NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
NS_MOOD = 'http://jabber.org/protocol/mood'

node_base = 'ralphm/mood/'
full_node = node_base + jabber_user + '@' + jabber_host

# define completion class.
class Completer:
    def __init__(self):
	self.list = []

    def complete(self, text, state):
	if state == 0:
	    self.matches = self.get_matches(text)
	try:
	    return self.matches[state]
	except IndexError:
	    return None

    def set_choices(self, list):
	self.list = list

    def get_matches(self, text):
	matches = []
	for elt in self.list:
	    if string.find(elt, text) == 0:
		matches.append(elt)
	return matches

completer = Completer()


try:
	# Create emotion list.
	moods_dom = parse(mood_file).getElementsByTagName('moods')[0]
	moods_url = moods_dom.getElementsByTagName('url')[0].firstChild.nodeValue.strip()
except IOError:
	print "No moods file, forcing update"
	moods_url = default_moods_url
	moods_need_fetch = True
else:
	# file exists.. lets see if the current moods file is older than 5 days.
	if time.mktime(time.localtime()) - posix.stat(mood_file)[8] > 604800:
		# Attempt to fetch a new copy of the moods source
		print "Moods file too old, forcing update"
		moods_need_fetch = True

if moods_need_fetch:
	print "Fetching moods file from %s..." % (moods_url)
	newsource = urlopen(moods_url).read()
	file(mood_file, 'w').write(newsource)

	# parse it all again.
	moods_dom = parseString(newsource).getElementsByTagName('moods')[0]

moodlist = []
for i in moods_dom.getElementsByTagName('list')[0].getElementsByTagName('mood'):
  moodlist.append(i.firstChild.nodeValue)

# Generate a pretty list of moods...
moodstring = moodlist[0]
for i in moodlist[1:-1]:
  moodstring = "%s, %s" % (moodstring, i)
if moodlist[0] != moodlist[-1]:
  moodstring = "%s and %s" % (moodstring, moodlist[-1])

# get the emotions
print "Currently supported emotions are: %s" % (moodstring)
completer.set_choices(moodlist)
readline.parse_and_bind("tab: complete")
readline.set_completer(completer.complete)
emotion = raw_input("emotion: ");

reason = raw_input("reason: ");

# Connect to the server
# con = jabber.Client(host=jabber_host,log=sys.stderr)
con = jabber.Client(host=jabber_host)

## Try and connect
try:
    con.connect()
except:
    print "Couldn't connect: %s" % e
    sys.exit(0)
else:
    print "Connected"

## Authenticate
if con.auth(jabber_user,jabber_password,jabber_resource):
    print "Authenticated"
else:
    print "Auth failed", con.lastErr, con.lastErrCode
    sys.exit(1)

# Create the query
pubsub_iq = """
  <iq to='%s' type='set'>
    <pubsub xmlns='%s'>
      <publish node='%s'>
	<item id='current'>
	  <mood xmlns='%s'>
	    <value>%s</value>
	    <text>%s</text>
	  </mood>
	</item>
      </publish>
    </pubsub>
  </iq>
""" % ('pubsub.ik.nu', NS_PUBSUB, full_node, NS_MOOD, emotion, reason);

iq = jabber.Iq(node=xmlstream.NodeBuilder(pubsub_iq).getDom())

# Send the query
resp = con.SendAndWaitForResponse(iq)
if resp:
   print "Sent your new mood";
else:
   print "Failed to set your new mood."

