From f4a30d19aa282662b6cb369a30320ab6b5f20f63 Mon Sep 17 00:00:00 2001 From: Stefan Krulj Date: Fri, 5 Oct 2012 04:55:10 +0200 Subject: [PATCH] initial commit --- brathuhn.py | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++ config.py | 9 ++ get_quote.py | 91 ++++++++++++++++++++ logger.py | 63 ++++++++++++++ main.py | 53 ++++++++++++ quote.py | 98 +++++++++++++++++++++ sortiere.py | 14 +++ 7 files changed, 563 insertions(+) create mode 100644 brathuhn.py create mode 100644 config.py create mode 100755 get_quote.py create mode 100644 logger.py create mode 100755 main.py create mode 100755 quote.py create mode 100755 sortiere.py diff --git a/brathuhn.py b/brathuhn.py new file mode 100644 index 0000000..66f25e3 --- /dev/null +++ b/brathuhn.py @@ -0,0 +1,235 @@ +import xmpp, os, sys, time + +from config import * + +VERSION = "0.2" + +commands = dict() +commands_private = dict() +group_listeners = [] +private_listeners = [] +status_listeners = [] + +users = dict() + +STATUS_JOIN, STATUS_ONLINE, STATUS_OFFLINE, STATUS_RENAME, STATUS_XAWAY, STATUS_AWAY, STATUS_UNKNOWN = range(7) + +def getUsers(): + """Return a dictionary of every user in the group, the values are status codes.""" + return users + +def addCommand(name,help,func): + """Add a groupchat command. + + @param name -- The name of the command, if the command keyword + "!name" is used at the start of a message the given + handler will be called + @param help -- Help string displayed on with the !help command + @param func -- Handler of the form func(msg,args) where msg is the + xmpppy representation of the message sent and args is + a list of arguments""" + commands[name]=(help,func) + +def addPrivateCommand(name,help,func): + """Add a private chat command. + + @param name -- The name of the command, if the command keyword + "!name" is used at the start of a message the given + handler will be called + @param help -- Help string displayed on with the !help command + @param func -- Handler of the form func(msg,args) where msg is the + xmpppy representation of the message sent and args is + a list of arguments""" + commands_private[name]=(help,func) + +def addGroupListener(func): + """Add a groupchat listener. + + @param func -- Handler of the form func(from,msg) where both arguments + are unicode strings""" + group_listeners.append(func) + +def addPrivateListener(func): + """Adds a private chat listener. + + @param func -- Handler of the form func(from,msg) where both arguments + are unicode strings""" + private_listeners.append(func) + +def addStatusListener(func): + """Adds a user status listener. + + @param func -- Handler of the form func(from,msg,status) where first two + arguments are unicode strings and status is one of STATUS_* + constants""" + status_listeners.append(func) + +def sendMsg(to,body,mtype=None): + """Send a message to the server. + + @param to -- Recipient of the message + @param body -- Message body + @param mtype -- Type of the message, (e.g. "groupchat" for group + messages)""" + mymsg = xmpp.protocol.Message(body=body) + mymsg.setTo(to) + if mtype!=None: + mymsg.setType(mtype) + cl.send(mymsg) + +def sendStyledMsg(to,body,mtype=None,style=""): + """Send a CSS-styled message to the server. + + @param to -- Recipient of the message + @param body -- Message body + @param mtype -- Type of the message, (e.g. "groupchat" for group + messages) + @param style -- Inline CSS used to format the message""" + mymsg = xmpp.protocol.Message(body=body) + mymsg.setTo(to) + if mtype!=None: + mymsg.setType(mtype) + c=mymsg.addChild('html', namespace='http://jabber.org/protocol/xhtml-im') + c=c.addChild('body',namespace='http://www.w3.org/1999/xhtml') + c=c.addChild('span',payload=body,attrs={'style':style}) + cl.send(mymsg) + +def sendMonoMsg(to,body,mtype=None): + """Send a mono-spaced styled message to the server (e.g. ASCII art). + + @param to -- Recipient of the message + @param body -- Message body + @param mtype -- Type of the message, (e.g. "groupchat" for group + messages)""" + mymsg = xmpp.protocol.Message(body=body) + mymsg.setTo(to) + mymsg.setType(mtype) + c=mymsg.addChild('html', namespace='http://jabber.org/protocol/xhtml-im') + c=c.addChild('body',namespace='http://www.w3.org/1999/xhtml') + c=c.addChild('span', attrs={'style':'font-family: Courier New, monospace;'}) + c=c.addChild('pre',payload=body,attrs={'style':'background-color: #ffffff;'}) + cl.send(mymsg) + +def __help(msg,args): + sendMsg(ROOM,"Available commands:",'groupchat') + for cmd in commands: + sendMsg(ROOM," !"+cmd+" - "+commands[cmd][0],'groupchat') + sendMsg(ROOM,"Available private chat commands:",'groupchat') + for cmd in commands_private: + sendMsg(ROOM," !"+cmd+" - "+commands_private[cmd][0],'groupchat') + +def __messageCB(conn,msg): + if msg.getType() == "groupchat": + #print unicode(msg.getFrom()) +": "+ unicode(msg.getBody()) +" " +unicode(msg.getChildren()) + body = unicode(msg.getBody()) + mfrom = unicode(msg.getFrom()) + if NAME in body and not room_nick in mfrom: + sendMsg(ROOM,NAME+" --(brathuhn bot framework (v"+VERSION+"), type !help)",'groupchat') + for cmd in commands: + if body.startswith("!"+cmd) and not room_nick in mfrom: + args = body.split() + commands[cmd][1](msg,args) + for listener in group_listeners: + listener( unicode(msg.getFrom()), unicode(msg.getBody())) + + if msg.getType() == "chat": + if msg.getBody() != None: + body = unicode(msg.getBody()) + mfrom = unicode(msg.getFrom()) + for cmd in commands_private: + if body.startswith("!"+cmd) and not room_nick in mfrom: + args = body.split() + commands_private[cmd][1](msg,args) + for listener in private_listeners: + listener( mfrom, body) + raise xmpp.NodeProcessed + +def __presenceCB(conn,msg): + #print "Status",msg.getFrom(), msg.getStatus(), msg.getStatusCode(), msg.getType() + if msg.getType()=='unavailable': + nick=msg.getNick() + if nick==None: + del users[msg.getFrom()] + #Disconnect + if not msg.getFrom() in users: + for listener in status_listeners: + listener(msg.getFrom(),msg,STATUS_OFFLINE) + else: + del users[msg.getFrom()] + #Rename + if not msg.getFrom() in users: + for listener in status_listeners: + listener(msg.getFrom(),msg,STATUS_RENAME) + else: + show = msg.getShow() + if show==None: + if not msg.getFrom() in users: + for listener in status_listeners: + listener(msg.getFrom(),msg,STATUS_JOIN) + + users[msg.getFrom()] = STATUS_ONLINE + #Online + else: + print msg.getFrom(),"is now",show + if not msg.getFrom() in users: + for listener in status_listeners: + listener(msg.getFrom(),msg,STATUS_JOIN) + if show=="away": + users[msg.getFrom()] = STATUS_AWAY + elif show=="xa": + users[msg.getFrom()] = STATUS_XAWAY + else: + users[msg.getFrom()] = STATUS_UNKNOWN + # status change + + status = STATUS_OFFLINE + if msg.getFrom() in users: + status = users[msg.getFrom()] + + for listener in status_listeners: + listener(msg.getFrom(),msg.getStatus(),status) + +jid=xmpp.protocol.JID(node=NAME,domain=SRV,resource='bot') +cl=xmpp.Client(jid.getDomain(),debug=[]) + +def connect_and_join(): + """Connect to the server and join the group chat room from the config.""" + global room_nick + global room_to + #connect to server + con=cl.connect() + if not con: + print 'could not connect!' + sys.exit() + print 'connected' + + cl.RegisterHandler('message',__messageCB) + cl.RegisterHandler('presence',__presenceCB) + + #authenticate + auth=cl.auth(NAME,PWD,resource=jid.getResource()) + if not auth: + print 'could not authenticate!' + sys.exit() + print 'auth' + + + room_to = "%s/%s" % (ROOM, NAME) + room_nick = ROOM+"/"+NAME + msg = xmpp.Presence(to=room_to) + if PWD_ROOM != "": + msg.addChild('x', namespace='http://jabber.org/protocol/muc').addChild('password',payload=PWD_ROOM) + + #add the help command + addCommand("help","Prints this help message",__help) + + #join the room + cl.send(msg) + #set status + cl.send(xmpp.Presence(to=room_to,status=NAME+" --(brathuhn bot framework (v"+VERSION+"), type !help)")) + +def loop(): + """Loop forever and handle the event-queue.""" + while True: + cl.Process(1) + diff --git a/config.py b/config.py new file mode 100644 index 0000000..eb8f9bc --- /dev/null +++ b/config.py @@ -0,0 +1,9 @@ +NAME = "brathuhn" +SRV = "n0g.at" +PWD = "123huhn" + +#ROOM = "gladio@conference.n0g.at" +#PWD_ROOM = "secret" + +ROOM = "debug@conference.n0g.at" +PWD_ROOM = "" diff --git a/get_quote.py b/get_quote.py new file mode 100755 index 0000000..c78737c --- /dev/null +++ b/get_quote.py @@ -0,0 +1,91 @@ +import urllib2, exceptions +from HTMLParser import HTMLParser +from random import randint +import brathuhn + +class WikiQuoteParser(HTMLParser): + FORBIDDEN_H2 = ["External links","Web","Filminfo", "Contents","Inhaltsverzeichnis","Cast", "See also"] + def __init__(self): + HTMLParser.__init__(self) + self.in_ul=0 + self.in_li=0 + self.h2_num=0 + self.in_h2=0 + self.stop_h2=False + self.stop_div=True + self.quote="" + self.quotes=[] + self.div_hist=0 + self.in_div=0 + + def handle_starttag(self, tag, attrs): + if tag=="ul": + self.in_ul+=1 + if tag=="li": + self.in_li+=1 + if tag=="h2": + self.h2_num+=1 + self.in_h2+=1 + self.stop_h2=False + if tag=="div": + self.in_div+=1 + for at in attrs: + if at[0]=="id" and at[1]=="mw-content-text": + self.div_hist=self.in_div + self.stop_div=False + def handle_endtag(self, tag): + if tag=="div": + if self.div_hist==self.in_div: + self.div_hist=0 + self.stop_div=True + self.in_div-=1 + if tag=="h2": + self.in_h2-=1 + if tag=="ul": + self.in_ul-=1 + if tag=="li": + self.in_li-=1 + if self.in_li==0: + if self.quote!="": + self.quotes.append(self.quote) + self.quote="" + def handle_data(self, data): + + if self.in_h2>0: + for i in self.FORBIDDEN_H2: + if data.startswith(i): + self.stop_h2=True + + if self.stop_div or self.stop_h2: + return + + if self.in_li==1 and self.in_ul==1 and self.h2_num>=1: + self.quote+=data.replace("\n","") + + +def quote(msg,args): + if len(args)!=3: + brathuhn.sendMsg(brathuhn.ROOM,"Usage: "+args[0]+" language (two letter code) topic",'groupchat') + else: + try: + url = "http://"+args[1][0:2]+".wikiquote.org/wiki/"+args[2] + req = urllib2.Request(url, headers={'User-Agent' : "Magic Browser"}) + con = urllib2.urlopen( req ) + + data=con.read() + print "data:", args[1][0:2], args[2],url + wqp=WikiQuoteParser() + wqp.feed(data) + #for i in wqp.quotes: + # print "-- ",i + if len(wqp.quotes)==1: + brathuhn.sendMsg(brathuhn.ROOM,wqp.quotes[0],'groupchat') + elif len(wqp.quotes)>1: + brathuhn.sendMsg(brathuhn.ROOM,wqp.quotes[randint(0,len(wqp.quotes)-1)],'groupchat') + else: + brathuhn.sendMsg(brathuhn.ROOM,"No quotes found",'groupchat') + con.close() + except exceptions.Exception as e: + brathuhn.sendMsg(brathuhn.ROOM,"Network Error "+unicode(e),'groupchat') + + diff --git a/logger.py b/logger.py new file mode 100644 index 0000000..a99d9b6 --- /dev/null +++ b/logger.py @@ -0,0 +1,63 @@ +import brathuhn, tempfile + +user_logs = dict() + +def show_log(msg,args): + if len(args)!=1: + brathuhn.sendMsg(msg.getFrom(),"Usage: !"+args[0]) + return + if msg.getFrom() in user_logs: + user_logs[msg.getFrom()].seek(0) + log = user_logs[msg.getFrom()].read() + brathuhn.sendMsg(msg.getFrom(),'\n'+log) + else: + brathuhn.sendMsg(msg.getFrom(),"I'm currently not logging for you") + +def del_log(msg,args): + if len(args)!=1: + brathuhn.sendMsg(msg.getFrom(),"Usage: !"+args[0]) + return + if msg.getFrom() in user_logs: + user_logs[msg.getFrom()].seek(0) + user_logs[msg.getFrom()].truncate(0) + brathuhn.sendMsg(msg.getFrom(),"Done!") + else: + brathuhn.sendMsg(msg.getFrom(),"I'm currently not logging for you") + +def stop_log(msg,args): + if len(args)!=1: + brathuhn.sendMsg(brathuhn.ROOM,"Usage: !"+args[0],'groupchat') + return + brathuhn.sendMsg(brathuhn.ROOM,"/me stopped logging for "+unicode(msg.getFrom()),'groupchat') + if msg.getFrom() in user_logs: + del user_logs[msg.getFrom()] + + +def start_log(msg,args): + if len(args)!=1: + brathuhn.sendMsg(brathuhn.ROOM,"Usage: !"+args[0],'groupchat') + return + brathuhn.sendMsg(brathuhn.ROOM,"/me started logging for "+unicode(msg.getFrom()),'groupchat') + user_logs[msg.getFrom()]=open(tempfile.mkstemp(brathuhn.NAME)[1],"w+") + +def message_logger(mfrom,msg): + for key in user_logs: + user_logs[key].write(mfrom+": "+msg+"\n") + +def status_logger(mfrom,msg,status): + for key in user_logs: + if status==brathuhn.STATUS_JOIN: + user_logs[key].write(unicode(mfrom)+" joined\n") + if status==brathuhn.STATUS_ONLINE: + user_logs[key].write(unicode(mfrom)+" is now online\n") + pass + if status==brathuhn.STATUS_OFFLINE: + user_logs[key].write(unicode(mfrom)+" left\n") + if status==brathuhn.STATUS_RENAME: + user_logs[key].write(unicode(mfrom)+" is now known as "+msg.getName()+"\n") + if status==brathuhn.STATUS_XAWAY: + user_logs[key].write(unicode(mfrom)+" is now extended away\n") + if status==brathuhn.STATUS_AWAY: + user_logs[key].write(unicode(mfrom)+" is now away\n") + if status==brathuhn.STATUS_UNKNOWN: + user_logs[key].write(unicode(mfrom)+" is now ???\n") diff --git a/main.py b/main.py new file mode 100755 index 0000000..5f21d15 --- /dev/null +++ b/main.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import brathuhn +import subprocess +import random + +from get_quote import * +brathuhn.addCommand("quote","Usage: !quote language (two letter code) topic",quote) + + +from logger import * +brathuhn.addPrivateCommand("show_log","Usage: !show_log",show_log) +brathuhn.addPrivateCommand("start_log","Usage: !start_log",start_log) +brathuhn.addPrivateCommand("stop_log","Usage: !stop_log",stop_log) +brathuhn.addPrivateCommand("delete_log","Usage: !delete_log",del_log) +brathuhn.addGroupListener(message_logger) +brathuhn.addStatusListener(status_logger) + + +def cowsay(msg,args): + cowfile="default" + text="" + if( len(args)==2 ): + text=args[1] + elif( len(args)>=3 ): + cowfile=args[1] + for i in range(2,len(args)): + text+=args[i]+" " + else: + brathuhn.sendMsg(brathuhn.ROOM,"Usage: "+args[0]+" [cowfile] text",'groupchat') + return + + try: + txt=subprocess.check_output(["cowsay","-f",cowfile,text]) + for line in txt.split('\n'): + #brathuhn.sendStyledMsg(brathuhn.ROOM,line,'groupchat',) + brathuhn.sendMonoMsg(brathuhn.ROOM,line,'groupchat') + except subprocess.CalledProcessError: + pass +brathuhn.addCommand("cowsay","Usage: !cowsay [cowfile] text",cowsay) + + +def choose(msg,args): + if len(args)==1: + brathuhn.sendMsg(brathuhn.ROOM,"Usage: "+args[0]+" item_1 item_2 ... item_n",'groupchat') + else: + brathuhn.sendMsg(brathuhn.ROOM,args[1+random.randint(0,len(args[1:])-1)],'groupchat') +brathuhn.addCommand("choose","Usage: !choose item_1 item_2 ... item_n",choose) + +brathuhn.connect_and_join() +brathuhn.loop() + diff --git a/quote.py b/quote.py new file mode 100755 index 0000000..4394806 --- /dev/null +++ b/quote.py @@ -0,0 +1,98 @@ +#!/usr/bin/python + +import httplib +from HTMLParser import HTMLParser +from random import randint +import brathuhn + +import sys + +class WikiQuoteParser(HTMLParser): + in_ul=0 + in_li=0 + h2_num=0 + in_h2=0 + stop_h2=False + stop_div=True + quote="" + quotes=[] + div_hist=0 + in_div=0 + forbidden_h2 = ["External links","Web","Filminfo", "Contents","Inhaltsverzeichnis"] + + def handle_starttag(self, tag, attrs): + if tag=="ul": + self.in_ul+=1 + if tag=="li": + self.in_li+=1 + if tag=="h2": + self.h2_num+=1 + self.in_h2+=1 + self.stop_h2=False + if tag=="div": + self.in_div+=1 + for at in attrs: + if at[0]=="id" and at[1]=="mw-content-text": + self.div_hist=self.in_div + self.stop_div=False + def handle_endtag(self, tag): + if tag=="div": + if self.div_hist==self.in_div: + self.div_hist=0 + self.stop_div=True + self.in_div-=1 + if tag=="h2": + self.in_h2-=1 + if tag=="ul": + self.in_ul-=1 + if tag=="li": + self.in_li-=1 + if self.in_li==0: + if self.quote!="": + self.quotes.append(self.quote) + self.quote="" + def handle_data(self, data): + + if self.in_h2>0: + for i in self.forbidden_h2: + if data.startswith(i): + self.stop_h2=True + + if self.stop_div or self.stop_h2: + return + + if self.in_li==1 and self.in_ul==1 and self.h2_num>=1: + self.quote+=data.replace("\n","") + +#http://en.wikiquote.org/wiki/Douglas_Adams +def quote(msg,args): + if len(args)!=3: + print "Usage: "+args[0]+" language (two letter code) topic" + else: + try: + print "start" + conn = httplib.HTTPConnection(args[1][0:2]+".wikiquote.org") + conn.request("GET", "/wiki/"+args[2]) + print conn + + res = conn.getresponse() + if res.status==200: # OK + data=res.read() + print "data:", args[1][0:2], args[2] + wqp=WikiQuoteParser() + wqp.feed(data) + #for i in wqp.quotes: + # print "-- ",i + if len(wqp.quotes)==1: + print wqp.quotes[0] + elif len(wqp.quotes)>1: + print wqp.quotes[randint(0,len(wqp.quotes)-1)] + else: + print "No quotes" + else: + print "Error %d %s" % (res.status, res.reason) + conn.close() + print "end" + except: + print "Unknown Error" + diff --git a/sortiere.py b/sortiere.py new file mode 100755 index 0000000..f39a7f3 --- /dev/null +++ b/sortiere.py @@ -0,0 +1,14 @@ +#!/usr/bin/python + +def sortiere(liste): + if len(liste)==1: + pivot = liste[0] + return [liste[0]] + elif len(liste)==0: + return [] + pivot = liste[0] + return sortiere([x for x in liste[1:] if x<= pivot]) + \ + [pivot] + \ + sortiere([x for x in liste[1:] if x> pivot]) + +print sortiere([2,3,4,1,2,8,9])