#!/usr/bin/env python
# *-* coding: utf-8 -*-

"""
This is a very simple bot to show how automation using msnlib could be done.
It's not quite useful as-is, but provides a good example.

If you play with it, please let me know.
"""


# sys, for getting the parameters
import sys, os

# time, for sleeping
import time

# select to wait for events
import select

# socket, to catch errors
import socket

# thread, for creating the worker thread
import thread

# and, of course, msnlib
import msnlib
import msncb

os.environ["LANG"] = "ko_KR.utf-8"

def null(s):
	"Null function, useful to void debug ones"
	pass

msnlib.debug = null
msncb.debug = null

m = msnlib.msnd()
m.cb = msncb.cb()

def get_grouped_list(md):
	contacts = []
	db = {}
	for gid in md.groups.keys():
		db[gid] = []
	for gid in md.groups.keys():
		for e in md.users.keys():
			if md.users[e].gid == gid:
				db[gid].append(e)
	gids = db.keys()
	gids.sort()
	for gid in gids:
		ul = db[gid]
		ul.sort()
		for email in ul:
			u = m.users[email]
			if u.status == 'FLN':
				continue
			contacts.append(email)
	return contacts

def lookSvn(command, repos, rev):
	result = os.popen("/usr/bin/svnlook %s %s -r %s"%(command, repos, rev))
	log = ""
	for i in result.readlines():
		if i[-1:] == "\n":
			i = i[:-1]
		log += i + "\r\n"
	if log[-4:] == "\r\n\r\n":
		log = log[:-2]
	return log

def getAuthor(repos, rev):
	return lookSvn("author", repos, rev)

def getLog(repos, rev):
	return lookSvn("log", repos, rev)

def getChanged(repos, rev):
	return lookSvn("changed", repos, rev)

def getContacts():
	return get_grouped_list(m)

def sendToAll(log):
	contacts = getContacts()
	for contact in contacts:
		m.sendmsg(contact, log)
		time.sleep(1)
	time.sleep(1)

def appendLog(log, string):
	log += string
	if 1400 <= len(log):
		sendToAll(log[:1500])
		print 'Send with overflow: '+log[:1500]
		log = log[1500:]
	return log

def do_work():
	"""
	Here you do your stuff and send messages using m.sendmsg()
	This is the only place your code lives
	"""
	
	# wait a bit for everything to settle down (sync taking efect
	# basically)
	print 'Wait to login'
	time.sleep(3)
	print 'Making log..'
	
	repos = sys.argv[1]
	rev = sys.argv[2]

	m.encoding="UTF-8"

	log = ""
	log = appendLog(log, "Author: " + getAuthor(repos, rev))
	log = appendLog(log, "Revision: " + rev + "\r\n")
	log = appendLog(log, "----\r\n")
	log = appendLog(log, getChanged(repos, rev))
	log = appendLog(log, "----\r\n")
	log = appendLog(log, getLog(repos, rev))

	print 'Made a log'
	sendToAll(log)

	print 'Send messages: ', log

	# give time to send the messages
	print 'Wait to send'
	time.sleep(10)
	print 'Quit'

	# and then quit
	quit()
	

# you shouldn't need to touch anything past here


# get the login email and password from the parameters
try:
	m.email = "PUT YOUR MSN E-MAIL"
	m.pwd = "PUT YOUR MSN PASSWORD"
except:
	print "Use: msnbot email password"
	sys.exit(1)


m.login()

# this makes the server send you the contact list, and it's recommended that
# you do it because you can get in trouble when getting certain events from
# people that are not on your list; and it's not that expensive anyway
m.sync()

# any non-offline status will do, otherwise we'll get an error from msn when
# sending a message
m.change_status("away")

def quit():
	try:
		m.disconnect()
	except:
		pass
	print "Exit"
	sys.exit(0)

# we start a thread to do the work. it's a thread because we want to share
# everything, and fork cow semantics cause problems here
thread.start_new_thread(do_work, ())


# we loop over the network socket to get events
while 1:
	# we get pollable fds
	t = m.pollable()
	infd = t[0]
	outfd = t[1]

	# we select, waiting for events
	try:
		fds = select.select(infd, outfd, [], 0)
	except:
		quit()
	
	for i in fds[0] + fds[1]:       # see msnlib.msnd.pollable.__doc__
		try:
			m.read(i)
		except ('SocketError', socket.error), err:
			print 'Socket Error'
			if i != m:
				# user closed a connection
				# note that messages can be lost here
				m.close(i)
			else:
				# main socket closed
				quit()

	# sleep a bit so we don't take over the cpu
	time.sleep(0.01)



