diff options
Diffstat (limited to 'src/xmpppy-0.5.0rc1/doc')
-rw-r--r-- | src/xmpppy-0.5.0rc1/doc/advanced.html | 116 | ||||
-rw-r--r-- | src/xmpppy-0.5.0rc1/doc/basic.html | 111 | ||||
-rwxr-xr-x | src/xmpppy-0.5.0rc1/doc/examples/README.py | 71 | ||||
-rwxr-xr-x | src/xmpppy-0.5.0rc1/doc/examples/bot.py | 94 | ||||
-rw-r--r-- | src/xmpppy-0.5.0rc1/doc/examples/commandsbot.py | 289 | ||||
-rwxr-xr-x | src/xmpppy-0.5.0rc1/doc/examples/logger.py | 75 | ||||
-rwxr-xr-x | src/xmpppy-0.5.0rc1/doc/examples/xsend.py | 44 | ||||
-rw-r--r-- | src/xmpppy-0.5.0rc1/doc/examples/xtalk.py | 83 | ||||
-rw-r--r-- | src/xmpppy-0.5.0rc1/doc/index.html | 166 | ||||
-rw-r--r-- | src/xmpppy-0.5.0rc1/doc/xmpppy.css | 70 | ||||
-rw-r--r-- | src/xmpppy-0.5.0rc1/doc/xmpppy_title.png | bin | 0 -> 1213 bytes |
11 files changed, 1119 insertions, 0 deletions
diff --git a/src/xmpppy-0.5.0rc1/doc/advanced.html b/src/xmpppy-0.5.0rc1/doc/advanced.html new file mode 100644 index 00000000..4766eff0 --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/advanced.html @@ -0,0 +1,116 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<!-- $Id: advanced.html,v 1.2 2004/12/26 08:12:41 snakeru Exp $ --> +<html xml:lang="ru-RU" lang="ru-RU" xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta content="text/html; charset=koi8-r" http-equiv="content-type" /> + <title>Xmpppy usage - advanced.</title> + </head> +<!-- +Historical notes +Intro +simplexml +Dispatcher +--> + <body> + <h1>Introduction</h1> + <p>To write a programs using XMPP technology you must understand the basic + principles of it. Xmpppy uses it's own implementation of XML handling + procedures - so you should get used to it. Though it is simple enough I hope.</p> + <dl> + <dn>Node class</dn> + <dt> + <dl> + <dn>prototype</dn> + <dt>Node.__init__(name='', attrs={}, payload=[], parent=None, node=None)</dt> + <dn>Note that 'name' argument really consists of namespace and node name, space separated. Example:</dn> + <dt>node=Node('jabber:client message', attrs={'to':'target@jid.com'},payload=[Node('body',payload=['Hello target!'])])<br /> + or<br /> + node=Node('jabber:client message')<br /> + node['to']='target@jid.com'<br /> + node.NT.body='Hello target!' + </dt> + </dl> + NT stands for 'New Tag' and explicitly adds new child to the current node. + Also the T can be used. That means "find Tag" but if tag exists it acts just like NT otherwise. + </dt> + + <dn>Protocol class</dn> + <dt> + Uses similar syntax. We will use 'node' attribute now: + <dl> + <dn>prototype</dn> + <dt>Protocol.__init__(name=None, to=None, typ=None, frm=None, attrs={}, payload=[], timestamp=None, xmlns='jabber:client', node=None)</dt> + <dn>example</dn> + <dt>p=Protocol(node=node)<br /> + or<br /> + proto=Protocol('message',to='target@jid.com',payload=[Node('body',payload=['Hello target!'])])<br /> + or<br /> + proto=Protocol('message',to='target@jid.com')<br /> + proto.NT.body='Hello target!' + </dt> + </dl> + </dt> + + <dn>Message class</dn> + <dt> + Similar syntax: + <dl> + <dn>prototype</dn> + <dt>Message.__init__(to=None, body=None, typ=None, subject=None, attrs={}, frm=None, payload=[], timestamp=None, xmlns='jabber:client', node=None)</dt> + <dn>example</dn> + <dt>m=Message(node=proto)<br /> + or<br /> + m=Message('target@jid.com','Hello target!')<br /> + </dt> + </dl> + </dt> + + <dn>Iq class</dn> + <dt> + Similar syntax: + <dl> + <dn>prototype</dn> + <dt>Iq.__init__(typ=None, queryNS=None, attrs={}, to=None, frm=None, payload=[], xmlns='jabber:client', node=None)</dt> + <dn>example</dn> + <dt>iq=Iq('set',NS_AUTH,payload=[Node('username',payload=['user']),Node('password',payload=['secret'])])<br /> + or<br /> + iq=Iq('set',NS_AUTH)<br /> + iq.T.query.NT.username='user'<br /> + iq.T.query.NT.password='secret'<br /> + or<br /> + iq=Iq('set',NS_AUTH)<br /> + iq.T.query.T.username='user'<br /> + iq.T.query.T.password='secret'<br /> + As I already noted - 'T' acts just like 'NT' if tag doesn't exists. + </dt> + </dl> + </dt> + + <dn>Presence class</dn> + <dt> + Similar syntax: + <dl> + <dn>prototype</dn> + <dt>Presence.__init__(to=None, typ=None, priority=None, show=None, status=None, attrs={}, frm=None, timestamp=None, payload=[], xmlns='jabber:client', node=None)</dt> + <dn>example</dn> + <dt>pres=Presence(priority=5, show='xa',status="I'm away from my computer")<br /> + or<br /> + pres=Presence()<br /> + pres.setPriority(5) + pres.setShow('xa') + pres.setStatus("I'm away from my computer") + pres.setTimestamp() + or<br /> + pres=Presence()<br /> + pres.T.priority=5 + pres.T.show='xa' + pres.T.status="I'm away from my computer" + pres.setTimestamp() + </dt> + </dl> + </dt> + + </dl> + </body> +</html> diff --git a/src/xmpppy-0.5.0rc1/doc/basic.html b/src/xmpppy-0.5.0rc1/doc/basic.html new file mode 100644 index 00000000..86259d90 --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/basic.html @@ -0,0 +1,111 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xml:lang="ru-RU" lang="ru-RU" xmlns="http://www.w3.org/1999/xhtml"> +<!-- $Id: basic.html,v 1.5 2004/12/26 08:12:42 snakeru Exp $ --> + <head> + <meta content="text/html; charset=koi8-r" http-equiv="content-type" /> + <title>Xmpppy usage - basics.</title> + </head> + <body> +<!-- +basic +Объясняется принципы простейшего скриптования. Фактически уровень README.py. +advanced +Вольное изложение предмета +expert +описание API каждого модуля +--> +<h1>Preface.</h1> +<p>English is not my native language. If you see any bugs in this text, please, let me know.</p> +<h1>Basic</h1> +<h2>Introduction.</h2> +<p>This documents topic is for people who want to quickly try xmpppy for a simple task, like +writing a command-line script for sending a single message.</p> +<h2>Writing a simple script</h2> +<p>This example demonstrates a simple script that sends message to one +recipient. +Example:</p> +<pre> +xsend test@jabber.org Hello there! +</pre> +<p>You don't have a similar tool in your toolkit? Using the xmpppy +library it can be created easily. +<br />What? Already have one? Hmm. Maybe you want to simplify things a bit, or just curious how +to do it one more way? Anyway - let's start now! +<br /> +First - we declare ourself as a python script and importing needed modules:</p> +<pre> +#!/usr/bin/python +import sys,os,xmpp +</pre> +<p>After it we have to check if we have enough arguments on the command-line:</p> +<pre> +if len(sys.argv) < 2: + print "Syntax: xsend JID text" + sys.exit(0) +</pre> +<p>After it we must decode arguments. Omitting all checks to simplify our script:</p> +<pre> +tojid=sys.argv[1] +text=' '.join(sys.argv[2:]) +</pre> +<p>One more non-jabber step: We have to to get our Jabber ID and login +details. Presuming that all info +stored in ~/.xsend file:</p> +<pre> +jidparams={} +if os.access(os.environ['HOME']+'/.xsend',os.R_OK): + for ln in open(os.environ['HOME']+'/.xsend').readlines(): + key,val=ln.strip().split('=',1) + jidparams[key.lower()]=val +for mandatory in ['jid','password']: + if mandatory not in jidparams.keys(): + open(os.environ['HOME']+'/.xsend','w').write('#JID=romeo@montague.net\n#PASSWORD=juliet\n') + print 'Please ensure the ~/.xsend file has valid JID for sending messages.' + sys.exit(0) +</pre> +<p>Phew! The most complex (non-jabber ;) ) part is finished. From now on we have to:</p> +<ul> + <li>connect to jabber server</li> + <li>authenticate ourselves</li> + <li>submit a message</li> +</ul> +<p>Let's start: +<br /> +0. To connect we must have a client instance. Calculating our server name and +creating Client class instance for it:</p> +<pre> +jid=xmpp.protocol.JID(jidparams['jid']) +cl=xmpp.Client(jid.getDomain(),debug=[]) +</pre> +<p>1. Connect and authenticate with credentials from the config file.</p> +<pre> +cl.connect() +cl.auth(jid.getNode(),jidparams['password']) +</pre> +<p>2. We can go online now (by sending the inital presence) but will not do that, as it is not nessessary for sending a message. +So we send a message now!</p> +<pre> +#cl.sendInitialPresence() +cl.send(xmpp.protocol.Message(tojid,text)) +</pre> +<p>We're done! The session must now be closed but since we have not registered +disconnect handler we will just leave it to python and TCP/IP layer. +All jabber servers that I know handle <span style="font-style: italic;">such</span> +disconnects correctly. +<br /> +You can download this script <a href="examples/xsend.py">here</a>.</p> +<h3>What now?</h3> +<p>If you were impressed of how the things were done with xmpppy, you may be interested in +more thorough examination of xmpppy library. The "advanced" and "expert" +parts of this document are here to help you. +<br /> +"<a href="advanced.html">Advanced</a>" (isn't writed yet) part is much like another tutorial and +describing common principles of XMPP usage via xmpppy prism. It describes ideas that are the foundation of XML handling with the +simplexml library, the essence of dispatcher's work and how messages are processed, and +some guidelines to write more complex programs and uses of the library. +<br /> +"<a href="apidocs/">Expert</a>" part is full library API description documentation. +This is epydoc generated output - all info is taken from the xmpppy code so you can re-generate it at any time. +</p> +</body> +</html> diff --git a/src/xmpppy-0.5.0rc1/doc/examples/README.py b/src/xmpppy-0.5.0rc1/doc/examples/README.py new file mode 100755 index 00000000..ae01dc62 --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/examples/README.py @@ -0,0 +1,71 @@ +#!/usr/bin/python +# -*- coding: koi8-r -*- +from xmpp import * + +def presenceHandler(conn,presence_node): + """ Handler for playing a sound when particular contact became online """ + targetJID='node@domain.org' + if presence_node.getFrom().bareMatch(targetJID): + # play a sound + pass +def iqHandler(conn,iq_node): + """ Handler for processing some "get" query from custom namespace""" + reply=iq_node.buildReply('result') + # ... put some content into reply node + conn.send(reply) + raise NodeProcessed # This stanza is fully processed +def messageHandler(conn,mess_node): pass + +if 1: + """ + Example 1: + Connecting to specified IP address. + Connecting to port 5223 - TLS is pre-started. + Using direct connect. + """ + # Born a client + cl=Client('ejabberd.somedomain.org') + # ...connect it to SSL port directly + if not cl.connect(server=('1.2.3.4',5223)): + raise IOError('Can not connect to server.') +else: + """ + Example 2: + Connecting to server via proxy. + Assuming that servername resolves to jabber server IP. + TLS will be started automatically if available. + """ + # Born a client + cl=Client('jabberd2.somedomain.org') + # ...connect via proxy + if not cl.connect(proxy={'host':'someproxy.somedomain.org','port':'8080','user':'proxyuser','password':'proxyuserpassword'}): + raise IOError('Can not connect to server.') +# ...authorize client +if not cl.auth('jabberuser','jabberuserpassword','optional resource name'): + raise IOError('Can not auth with server.') +# ...register some handlers (if you will register them before auth they will be thrown away) +cl.RegisterHandler('presence',presenceHandler) +cl.RegisterHandler('iq',iqHandler) +cl.RegisterHandler('message',messageHandler) +# ...become available +cl.sendInitPresence() +# ...work some time +cl.Process(1) +# ...if connection is brocken - restore it +if not cl.isConnected(): cl.reconnectAndReauth() +# ...send an ASCII message +cl.send(Message('test@jabber.org','Test message')) +# ...send a national message +cl.send(Message('test@jabber.org',unicode('Проверка связи','koi8-r'))) +# ...send another national message +simplexml.ENCODING='koi8-r' +cl.send(Message('test@jabber.org','Проверка связи 2')) +# ...work some more time - collect replies +cl.Process(1) +# ...and then disconnect. +cl.disconnect() + +""" +If you have used jabberpy before you will find xmpppy very similar. +See the docs for more info about library features. +""" diff --git a/src/xmpppy-0.5.0rc1/doc/examples/bot.py b/src/xmpppy-0.5.0rc1/doc/examples/bot.py new file mode 100755 index 00000000..42636300 --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/examples/bot.py @@ -0,0 +1,94 @@ +#!/usr/bin/python +# -*- coding: koi8-r -*- +# $Id: bot.py,v 1.2 2006/10/06 12:30:42 normanr Exp $ +import sys +import xmpp + +commands={} +i18n={'ru':{},'en':{}} +########################### user handlers start ################################## +i18n['en']['HELP']="This is example jabber bot.\nAvailable commands: %s" +def helpHandler(user,command,args,mess): + lst=commands.keys() + lst.sort() + return "HELP",', '.join(lst) + +i18n['en']['EMPTY']="%s" +i18n['en']['HOOK1']='Responce 1: %s' +def hook1Handler(user,command,args,mess): + return "HOOK1",'You requested: %s'%args + +i18n['en']['HOOK2']='Responce 2: %s' +def hook2Handler(user,command,args,mess): + return "HOOK2","hook2 called with %s"%(`(user,command,args,mess)`) + +i18n['en']['HOOK3']='Responce 3: static string' +def hook3Handler(user,command,args,mess): + return "HOOK3"*int(args) +########################### user handlers stop ################################### +############################ bot logic start ##################################### +i18n['en']["UNKNOWN COMMAND"]='Unknown command "%s". Try "help"' +i18n['en']["UNKNOWN USER"]="I do not know you. Register first." + +def messageCB(conn,mess): + text=mess.getBody() + user=mess.getFrom() + user.lang='en' # dup + if text.find(' ')+1: command,args=text.split(' ',1) + else: command,args=text,'' + cmd=command.lower() + + if commands.has_key(cmd): reply=commands[cmd](user,command,args,mess) + else: reply=("UNKNOWN COMMAND",cmd) + + if type(reply)==type(()): + key,args=reply + if i18n[user.lang].has_key(key): pat=i18n[user.lang][key] + elif i18n['en'].has_key(key): pat=i18n['en'][key] + else: pat="%s" + if type(pat)==type(''): reply=pat%args + else: reply=pat(**args) + else: + try: reply=i18n[user.lang][reply] + except KeyError: + try: reply=i18n['en'][reply] + except KeyError: pass + if reply: conn.send(xmpp.Message(mess.getFrom(),reply)) + +for i in globals().keys(): + if i[-7:]=='Handler' and i[:-7].lower()==i[:-7]: commands[i[:-7]]=globals()[i] + +############################# bot logic stop ##################################### + +def StepOn(conn): + try: + conn.Process(1) + except KeyboardInterrupt: return 0 + return 1 + +def GoOn(conn): + while StepOn(conn): pass + +if len(sys.argv)<3: + print "Usage: bot.py username@server.net password" +else: + jid=xmpp.JID(sys.argv[1]) + user,server,password=jid.getNode(),jid.getDomain(),sys.argv[2] + + conn=xmpp.Client(server)#,debug=[]) + conres=conn.connect() + if not conres: + print "Unable to connect to server %s!"%server + sys.exit(1) + if conres<>'tls': + print "Warning: unable to estabilish secure connection - TLS failed!" + authres=conn.auth(user,password) + if not authres: + print "Unable to authorize on %s - check login/password."%server + sys.exit(1) + if authres<>'sasl': + print "Warning: unable to perform SASL auth os %s. Old authentication method used!"%server + conn.RegisterHandler('message',messageCB) + conn.sendInitPresence() + print "Bot started." + GoOn(conn) diff --git a/src/xmpppy-0.5.0rc1/doc/examples/commandsbot.py b/src/xmpppy-0.5.0rc1/doc/examples/commandsbot.py new file mode 100644 index 00000000..f32c13c6 --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/examples/commandsbot.py @@ -0,0 +1,289 @@ +#!/usr/bin/python +""" The example of using xmpppy's Ad-Hoc Commands (JEP-0050) implementation. +""" +import xmpp +from xmpp.protocol import * + +options = { + 'JID': 'circles@example.com', + 'Password': '********', +} + +class TestCommand(xmpp.commands.Command_Handler_Prototype): + """ Example class. You should read source if you wish to understate how it works. This one + actually does some calculations.""" + name = 'testcommand' + description = 'Circle calculations' + def __init__(self, jid=''): + """ Initialize some internals. Set the first request handler to self.calcTypeForm. + """ + xmpp.commands.Command_Handler_Prototype.__init__(self,jid) + self.initial = { + 'execute': self.initialForm + } + + def initialForm(self, conn, request): + """ Assign a session id and send the first form. """ + sessionid = self.getSessionID() + self.sessions[sessionid] = { + 'jid':request.getFrom(), + 'data':{'type':None} + } + + # simulate that the client sent sessionid, so calcTypeForm will be able + # to continue + request.getTag(name="command").setAttr('sessionid', sessionid) + + return self.calcTypeForm(conn, request) + + def calcTypeForm(self, conn, request): + """ Send first form to the requesting user. """ + # get the session data + sessionid = request.getTagAttr('command','sessionid') + session = self.sessions[sessionid] + + # What to do when a user sends us a response? Note, that we should always + # include 'execute', as it is a default action when requester does not send + # exact action to do (should be set to the same as 'next' or 'complete' fields) + session['actions'] = { + 'cancel': self.cancel, + 'next': self.calcTypeFormAccept, + 'execute': self.calcTypeFormAccept, + } + + # The form to send + calctypefield = xmpp.DataField( + name='calctype', + desc='Calculation Type', + value=session['data']['type'], + options=[ + ['Calculate the diameter of a circle','circlediameter'], + ['Calculate the area of a circle','circlearea'] + ], + typ='list-single', + required=1) + + # We set label attribute... seems that the xmpppy.DataField cannot do that + calctypefield.setAttr('label', 'Calculation Type') + + form = xmpp.DataForm( + title='Select type of operation', + data=[ + 'Use the combobox to select the type of calculation you would like'\ + 'to do, then click Next.', + calctypefield]) + + # Build a reply with the form + reply = request.buildReply('result') + replypayload = [ + xmpp.Node('actions', + attrs={'execute':'next'}, + payload=[xmpp.Node('next')]), + form] + reply.addChild( + name='command', + namespace=NS_COMMANDS, + attrs={ + 'node':request.getTagAttr('command','node'), + 'sessionid':sessionid, + 'status':'executing'}, + payload=replypayload) + self._owner.send(reply) # Question: self._owner or conn? + raise xmpp.NodeProcessed + + def calcTypeFormAccept(self, conn, request): + """ Load the calcType form filled in by requester, then reply with + the second form. """ + # get the session data + sessionid = request.getTagAttr('command','sessionid') + session = self.sessions[sessionid] + + # load the form + node = request.getTag(name='command').getTag(name='x',namespace=NS_DATA) + form = xmpp.DataForm(node=node) + + # retrieve the data + session['data']['type'] = form.getField('calctype').getValue() + + # send second form + return self.calcDataForm(conn, request) + + def calcDataForm(self, conn, request, notavalue=None): + """ Send a form asking for diameter. """ + # get the session data + sessionid = request.getTagAttr('command','sessionid') + session = self.sessions[sessionid] + + # set the actions taken on requester's response + session['actions'] = { + 'cancel': self.cancel, + 'prev': self.calcTypeForm, + 'next': self.calcDataFormAccept, + 'execute': self.calcDataFormAccept + } + + # create a form + radiusfield = xmpp.DataField(desc='Radius',name='radius',typ='text-single') + radiusfield.setAttr('label', 'Radius') + + form = xmpp.DataForm( + title = 'Enter the radius', + data=[ + 'Enter the radius of the circle (numbers only)', + radiusfield]) + + # build a reply stanza + reply = request.buildReply('result') + replypayload = [ + xmpp.Node('actions', + attrs={'execute':'complete'}, + payload=[xmpp.Node('complete'),xmpp.Node('prev')]), + form] + + if notavalue: + replypayload.append(xmpp.Node('note', + attrs={'type': 'warn'}, + payload=['You have to enter valid number.'])) + + reply.addChild( + name='command', + namespace=NS_COMMANDS, + attrs={ + 'node':request.getTagAttr('command','node'), + 'sessionid':request.getTagAttr('command','sessionid'), + 'status':'executing'}, + payload=replypayload) + + self._owner.send(reply) + raise xmpp.NodeProcessed + + def calcDataFormAccept(self, conn, request): + """ Load the calcType form filled in by requester, then reply with the result. """ + # get the session data + sessionid = request.getTagAttr('command','sessionid') + session = self.sessions[sessionid] + + # load the form + node = request.getTag(name='command').getTag(name='x',namespace=NS_DATA) + form = xmpp.DataForm(node=node) + + # retrieve the data; if the entered value is not a number, return to second stage + try: + value = float(form.getField('radius').getValue()) + except: + self.calcDataForm(conn, request, notavalue=True) + + # calculate the answer + from math import pi + if session['data']['type'] == 'circlearea': + result = (value**2) * pi + else: + result = 2 * value * pi + + # build the result form + form = xmpp.DataForm( + typ='result', + data=[xmpp.DataField(desc='result', name='result', value=result)]) + + # build the reply stanza + reply = request.buildReply('result') + reply.addChild( + name='command', + namespace=NS_COMMANDS, + attrs={ + 'node':request.getTagAttr('command','node'), + 'sessionid':sessionid, + 'status':'completed'}, + payload=[form]) + + self._owner.send(reply) + + # erase the data about session + del self.sessions[sessionid] + + raise xmpp.NodeProcessed + + def cancel(self, conn, request): + """ Requester canceled the session, send a short reply. """ + # get the session id + sessionid = request.getTagAttr('command','sessionid') + + # send the reply + reply = request.buildReply('result') + reply.addChild( + name='command', + namespace=NS_COMMANDS, + attrs={ + 'node':request.getTagAttr('command','node'), + 'sessionid':sessionid, + 'status':'cancelled'}) + self._owner.send(reply) + + # erase the data about session + del self.sessions[sessionid] + + raise xmpp.NodeProcessed + +class ConnectionError: pass +class AuthorizationError: pass +class NotImplemented: pass + +class Bot: + """ The main bot class. """ + + def __init__(self, JID, Password): + """ Create a new bot. Connect to the server and log in. """ + + # connect... + jid = xmpp.JID(JID) + self.connection = xmpp.Client(jid.getDomain(), debug=['always', 'browser', 'testcommand']) + + result = self.connection.connect() + + if result is None: + raise ConnectionError + + # authorize + result = self.connection.auth(jid.getNode(), Password) + + if result is None: + raise AuthorizationError + + # plugins + # disco - needed by commands + + # warning: case of "plugin" method names are important! + # to attach a command to Commands class, use .plugin() + # to attach anything to Client class, use .PlugIn() + self.disco = xmpp.browser.Browser() + self.disco.PlugIn(self.connection) + self.disco.setDiscoHandler({ + 'info': { + 'ids': [{ + 'category': 'client', + 'type': 'pc', + 'name': 'Bot' + }], + 'features': [NS_DISCO_INFO], + } + }) + + self.commands = xmpp.commands.Commands(self.disco) + self.commands.PlugIn(self.connection) + + self.command_test = TestCommand() + self.command_test.plugin(self.commands) + + # presence + self.connection.sendInitPresence(requestRoster=0) + + def loop(self): + """ Do nothing except handling new xmpp stanzas. """ + try: + while self.connection.Process(1): + pass + except KeyboardInterrupt: + pass + +bot = Bot(**options) +bot.loop() diff --git a/src/xmpppy-0.5.0rc1/doc/examples/logger.py b/src/xmpppy-0.5.0rc1/doc/examples/logger.py new file mode 100755 index 00000000..b99686c1 --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/examples/logger.py @@ -0,0 +1,75 @@ +#!/usr/bin/python +# -*- coding: koi8-r -*- +from xmpp import * +import time,os + +#BOT=(botjid,password) +BOT=('test@penza-gsm.ru','test') +#CONF=(confjid,password) +CONF=('talks@conference.jabber.ru','') +LOGDIR='./' +PROXY={} +#PROXY={'host':'192.168.0.1','port':3128,'username':'luchs','password':'secret'} +####################################### + +def LOG(stanza,nick,text): + ts=stanza.getTimestamp() + if not ts: + ts=stanza.setTimestamp() + ts=stanza.getTimestamp() + tp=time.mktime(time.strptime(ts,'%Y%m%dT%H:%M:%S %Z'))+3600*3 + if time.localtime()[-1]: tp+=3600 + tp=time.localtime(tp) + fold=stanza.getFrom().getStripped().replace('@','%')+'_'+time.strftime("%Y.%m",tp) + day=time.strftime("%d",tp) + tm=time.strftime("%H:%M:%S",tp) + try: os.mkdir(LOGDIR+fold) + except: pass + fName='%s%s/%s.%s.html'%(LOGDIR,fold,fold,day) + try: open(fName) + except: + open(fName,'w').write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xml:lang="ru-RU" lang="ru-RU" xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta content="text/html; charset=utf-8" http-equiv="content-type" /> + <title>%s logs for %s.%s.</title> + </head> + <body> +<table border="1"><tr><th>time</th><th>who</th><th>text</th></tr> +"""%(CONF[0],fold,day)) + text='<pre>%s</pre>'%text + open(fName,'a').write((u"<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n"%(tm,nick,text)).encode('utf-8')) + print (u"<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n"%(tm,nick,text)).encode('koi8-r','replace') +# print time.localtime(tp),nick,text + +def messageCB(sess,mess): + nick=mess.getFrom().getResource() + text=mess.getBody() + LOG(mess,nick,text) + +roster=[] +def presenceCB(sess,pres): + nick=pres.getFrom().getResource() + text='' + if pres.getType()=='unavailable': + if nick in roster: + text=nick+unicode(' покинул конференцию','koi8-r') + roster.remove(nick) + else: + if nick not in roster: + text=nick+unicode(' пришёл в конференцию','koi8-r') + roster.append(nick) + if text: LOG(pres,nick,text) + +if 1: + cl=Client(JID(BOT[0]).getDomain(),debug=[]) + cl.connect(proxy=PROXY) + cl.RegisterHandler('message',messageCB) + cl.RegisterHandler('presence',presenceCB) + cl.auth(JID(BOT[0]).getNode(),BOT[1]) + p=Presence(to='%s/logger'%CONF[0]) + p.setTag('x',namespace=NS_MUC).setTagData('password',CONF[1]) + p.getTag('x').addChild('history',{'maxchars':'0','maxstanzas':'0'}) + cl.send(p) + while 1: + cl.Process(1) diff --git a/src/xmpppy-0.5.0rc1/doc/examples/xsend.py b/src/xmpppy-0.5.0rc1/doc/examples/xsend.py new file mode 100755 index 00000000..59b202a9 --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/examples/xsend.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# $Id: xsend.py,v 1.8 2006/10/06 12:30:42 normanr Exp $ +import sys,os,xmpp,time + +if len(sys.argv) < 2: + print "Syntax: xsend JID text" + sys.exit(0) + +tojid=sys.argv[1] +text=' '.join(sys.argv[2:]) + +jidparams={} +if os.access(os.environ['HOME']+'/.xsend',os.R_OK): + for ln in open(os.environ['HOME']+'/.xsend').readlines(): + if not ln[0] in ('#',';'): + key,val=ln.strip().split('=',1) + jidparams[key.lower()]=val +for mandatory in ['jid','password']: + if mandatory not in jidparams.keys(): + open(os.environ['HOME']+'/.xsend','w').write('#Uncomment fields before use and type in correct credentials.\n#JID=romeo@montague.net/resource (/resource is optional)\n#PASSWORD=juliet\n') + print 'Please point ~/.xsend config file to valid JID for sending messages.' + sys.exit(0) + +jid=xmpp.protocol.JID(jidparams['jid']) +cl=xmpp.Client(jid.getDomain(),debug=[]) + +con=cl.connect() +if not con: + print 'could not connect!' + sys.exit() +print 'connected with',con +auth=cl.auth(jid.getNode(),jidparams['password'],resource=jid.getResource()) +if not auth: + print 'could not authenticate!' + sys.exit() +print 'authenticated using',auth + +#cl.SendInitPresence(requestRoster=0) # you may need to uncomment this for old server +id=cl.send(xmpp.protocol.Message(tojid,text)) +print 'sent message with id',id + +time.sleep(1) # some older servers will not send the message if you disconnect immediately after sending + +#cl.disconnect() diff --git a/src/xmpppy-0.5.0rc1/doc/examples/xtalk.py b/src/xmpppy-0.5.0rc1/doc/examples/xtalk.py new file mode 100644 index 00000000..8832875f --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/examples/xtalk.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# $Id: xtalk.py,v 1.4 2008/08/09 17:00:18 normanr Exp $ +import sys,os,xmpp,time,select + +class Bot: + + def __init__(self,jabber,remotejid): + self.jabber = jabber + self.remotejid = remotejid + + def register_handlers(self): + self.jabber.RegisterHandler('message',self.xmpp_message) + + def xmpp_message(self, con, event): + type = event.getType() + fromjid = event.getFrom().getStripped() + body = event.getBody() + if type in ['message', 'chat', None] and fromjid == self.remotejid and body: + sys.stdout.write(body + '\n') + + def stdio_message(self, message): + m = xmpp.protocol.Message(to=self.remotejid,body=message,typ='chat') + self.jabber.send(m) + + def xmpp_connect(self): + con=self.jabber.connect() + if not con: + sys.stderr.write('could not connect!\n') + return False + sys.stderr.write('connected with %s\n'%con) + auth=self.jabber.auth(jid.getNode(),jidparams['password'],resource=jid.getResource()) + if not auth: + sys.stderr.write('could not authenticate!\n') + return False + sys.stderr.write('authenticated using %s\n'%auth) + self.register_handlers() + return con + +if __name__ == '__main__': + + if len(sys.argv) < 2: + print "Syntax: xtalk JID" + sys.exit(0) + + tojid=sys.argv[1] + + jidparams={} + if os.access(os.environ['HOME']+'/.xtalk',os.R_OK): + for ln in open(os.environ['HOME']+'/.xtalk').readlines(): + if not ln[0] in ('#',';'): + key,val=ln.strip().split('=',1) + jidparams[key.lower()]=val + for mandatory in ['jid','password']: + if mandatory not in jidparams.keys(): + open(os.environ['HOME']+'/.xtalk','w').write('#Uncomment fields before use and type in correct credentials.\n#JID=romeo@montague.net/resource (/resource is optional)\n#PASSWORD=juliet\n') + print 'Please point ~/.xtalk config file to valid JID for sending messages.' + sys.exit(0) + + jid=xmpp.protocol.JID(jidparams['jid']) + cl=xmpp.Client(jid.getDomain())#,debug=[]) + + bot=Bot(cl,tojid) + + if not bot.xmpp_connect(): + sys.stderr.write("Could not connect to server, or password mismatch!\n") + sys.exit(1) + + #cl.SendInitPresence(requestRoster=0) # you may need to uncomment this for old server + + socketlist = {cl.Connection._sock:'xmpp',sys.stdin:'stdio'} + online = 1 + + while online: + (i , o, e) = select.select(socketlist.keys(),[],[],1) + for each in i: + if socketlist[each] == 'xmpp': + cl.Process(1) + elif socketlist[each] == 'stdio': + msg = sys.stdin.readline().rstrip('\r\n') + bot.stdio_message(msg) + else: + raise Exception("Unknown socket type: %s" % repr(socketlist[each])) + #cl.disconnect() diff --git a/src/xmpppy-0.5.0rc1/doc/index.html b/src/xmpppy-0.5.0rc1/doc/index.html new file mode 100644 index 00000000..583c72a0 --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/index.html @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC + "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>xmpppy: the jabber python project</title> + <link rel="stylesheet" type="text/css" href="xmpppy.css" /> + </head> + <body> + <table class="head"> + <tbody> + <tr> + <td class="head"> + <img src="xmpppy_title.png" alt="xmpppy" title="the xmpppy project" height="69" width="300" /> + </td> + <td class="sflogo"> + <a href="http://sourceforge.net/"> + <img src="http://sourceforge.net/sflogo.php?group_id=97081&type=4" alt="SourceForge Logo" title="SourceForge Logo" border="0" height="37" hspace="30" width="125" /> + </a> + </td> + </tr> + </tbody> + </table> + <table class="content"> + <tbody> + <tr> + <td class="leftside"> + <h3>about</h3> + <p><a href="http://xmpppy.sourceforge.net/">xmpppy</a> is a + <a href="http://www.python.org">Python</a> library + that is targeted to provide easy scripting with <a href="http://www.jabber.org">Jabber</a>. + Similar projects are <a href="http://twistedmatrix.com/projects/words/">Twisted Words</a> + and <a href="http://jabberpy.sourceforge.net/">jabber.py.</a></p> + <p>This library was not designed from scratch. It inherits some code from + jabberpy and have very similar API in many places. Though it is separate + project since it have almost completely different architecture and primarily + aims to work with jabberd2 - the new Open Source Jabber Server.</p> + <p>xmpppy is distributed under the terms of + <a href="http://www.gnu.org/licenses/gpl.txt">GNU General Public License</a> + and can be freely redistributed without any charge.</p> + <h3>documentation</h3> + <p>Documentation is now in the process of heavy development and not yet + finished but most critical docs exist - please feel free to ask any questions if + you will find the docs incomplete (see support section below).</p> + <div> + <ul> + <li><a href="basic.html">Basic documentation</a> - a simple script.</li> + <li><a href="advanced.html">Advanced documentation</a> - architecture of library and guidelines.</li> + <li><a href="apidocs/index.html">Expert documentation</a> - API docs.</li> + </ul> + </div> + <h3>examples</h3> + <p>For these who prefer reading samples of code than digging through [incomplete] docs - + here they are. Simple (but working) examples of xmpppy usage.</p> + <div> + <ul> + <li><a href="examples/README.py">README.py</a><br /> + Self-explanatory library usage example</li> + <li><a href="examples/xsend.py">xsend.py</a><br /> + Command-line utility for sending jabber messages</li> + <li><a href="examples/xtalk.py">xtalk.py</a><br /> + Command-line utility for chatting with a single user</li> + <li><a href="examples/bot.py">bot.py</a><br /> + Xmpppy bot framework, handles messages</li> + <li><a href="examples/commandsbot.py">commandsbot.py</a><br /> + Xmpppy bot framework, handles ad hoc commands</li> + <li><a href="examples/logger.py">logger.py</a><br /> + Simple conference logger bot</li> + </ul> + </div> + <p>You can also look to at the <a href="http://xmpppy.sourceforge.net/irc/">IRC transport</a>, + <a href="http://xmpppy.sourceforge.net/mail/">Mail transport</a>, + <a href="http://xmpppy.sourceforge.net/yahoo/">Yahoo transport</a> or + <a href="http://sourceforge.net/project/showfiles.php?group_id=97081&package_id=130713">xmppd</a> + project code if you wish to see the serious library usage.</p> + <h3>download</h3> + <div>You can look for released versions on + <a href="http://sourceforge.net/project/showfiles.php?group_id=97081">downloads page</a> + or alternatively you can grab the latest version directly from CVS tree + by typing the following commands: + <blockquote> + cvs -d:pserver:anonymous@xmpppy.cvs.sourceforge.net:/cvsroot/xmpppy login + </blockquote> + (hit "enter" when you will be prompted for password) + <blockquote> + cvs -z3 -d:pserver:anonymous@xmpppy.cvs.sourceforge.net:/cvsroot/xmpppy co xmpppy + </blockquote> + </div> + <p>You can also browse xmpppy (and several xmpppy-based + projects) CVS online <a href="http://xmpppy.cvs.sourceforge.net/xmpppy/xmpppy/">here</a>.</p> + <p>If you have an RSS feed reader, there is + an RSS feed of CVS commits <a href="http://xmpppy.sourceforge.net/cvs-xmpppy.xml">here</a>.</p> + <h3>support</h3> + <p>If you have any questions about using xmpppy you can join + <a href="http://lists.sourceforge.net/lists/listinfo/xmpppy-devel">xmpppy-devel maillist</a>. + Here you can always find the best support, as you can find the developers here.</p> + <h3>donations</h3> + <p>If you are willing to help you can consult + <a href="http://software.newsforge.com/article.pl?sid=05/01/06/1557225">this article</a> + for how to do it. Thanks!</p> + <p>If you want to donate some money to encourage me to continue work on + library (it helps, really!) you can do it via e-gold system (account 1552795) or via + bank transfer (contact me via jabber or email to get the details).</p> + <a name="author"></a> + <h3>author</h3> + <p>Alexey Nezhdanov<br /> + Russian, born 18 Nov 1976.<br /> + My timezone is GMT+3<br /> + e-mail & Jabber: snake at penza-gsm.ru<br /> + ICQ: 19515046</p> + <div>I'm seeking for a job over Internet. It may be jabber-related work or + any other.<br /> + Possible directions of work: + <ul> + <li>Python projects (preferred)</li> + <li>C++ projects</li> + <li>Remote systems administering</li> + </ul> + My skills: + <ul> + <li>16 years of programming. Basic -> Pascal -> C++ -> Python</li> + <li>9 years of system administrator work. DOS -> Win 3.1 -> Win95 -> Win98 -> linux2.2 -> linux2.4 -> linux2.6</li> + <li>Automation tasks</li> + <li>Automated instant messenging (state change/failures reporting)</li> + <li>Some research work: + <ul> + <li>wavelet audio analysis</li> + <li>speech recognising</li> + <li>realtime texture [de]compression (for 3D systems).</li> + </ul> + </li> + </ul> + </div> + </td> + <td class="rightside"> + <h3>downloads</h3> + <p> + <a href="http://sourceforge.net/project/showfiles.php?group_id=97081&package_id=103821">xmpppy</a><br /> + <a href="http://sourceforge.net/project/showfiles.php?group_id=97081&package_id=130713">xmppd.py</a><br /> + <a href="http://sourceforge.net/project/showfiles.php?group_id=97081&package_id=118831">xmpppy-irc</a><br /> + <a href="http://sourceforge.net/project/showfiles.php?group_id=97081&package_id=182511">xmpppy-yahoo</a><br /> + <a href="http://sourceforge.net/project/showfiles.php?group_id=97081&package_id=168390">pyGAIM-t</a> + </p> + <p><a href="http://sourceforge.net/project/showfiles.php?group_id=97081">List all files</a></p> + <h3>sourceforge</h3> + <p> + <a href="http://sourceforge.net/projects/xmpppy/">Project Summary</a><br /> + <a href="http://sourceforge.net/tracker/?atid=616918&group_id=97081">Feature Requests</a><br /> + <a href="http://sourceforge.net/tracker/?atid=616915&group_id=97081">Bugs</a><br /> + <a href="http://sourceforge.net/tracker/?atid=616917&group_id=97081">Patches</a><br /> + </p> + <h3>exits</h3> + <p> + <a href="http://www.jabber.org/">jabber.org</a><br /> + <a href="http://xmpppy.sourceforge.net/irc/">IRC transport</a><br /> + <a href="http://xmpppy.sourceforge.net/mail/">Mail transport</a><br /> + <a href="http://xmpppy.sourceforge.net/yahoo/">Yahoo transport</a><br /> + </p> + </td> + </tr> + </tbody> + </table> + <p>the <a href="http://sourceforge.net/projects/xmpppy/">xmpppy project</a></p> + </body> +</html> diff --git a/src/xmpppy-0.5.0rc1/doc/xmpppy.css b/src/xmpppy-0.5.0rc1/doc/xmpppy.css new file mode 100644 index 00000000..eeed2b2f --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/xmpppy.css @@ -0,0 +1,70 @@ +/* xmpppy.css - The stylesheet of the xmpppy homepage + * + * Parts are taken of ickle stylesheet + * + * Copyleft 2005 by Marek Kubica + * + * Version 0.0.20050507 + * + */ + +/* set a background color, a light grey*/ +body { + background-color: #F2F2F2; +} + +/* fonts - no serif */ +a, p, ul, td, div { + font-family: sans-serif; +} + +/* hyperlinks: blue, not decorated, just bold */ +a { + text-decoration: none; + color: #00488F; + font-weight: bold; +} + +/* the head table, blue like the sf.net logo */ +table.head { + width: 100%; + background-color: #00488F; + text-align: right; + border-collapse: collapse; +} + +td.head { + padding: 0px; +} + +table.content { + padding: 5px; + border-spacing: 30px; +} + +td.sflogo { + width: 99%; +} + +/* the conentent of the left side fills 80% of the screen */ +td.leftside { + width: 80%; +} + +/* the links on the right side fill the remaining 20% + * and are displayed on top + */ +td.rightside { + width: 20%; + vertical-align: top; +} + +/* not simple bullets, but squares */ +ul { + list-style-type: square; +} + +/* blockquotes in italic */ +blockquote { + font-style: italic; +} diff --git a/src/xmpppy-0.5.0rc1/doc/xmpppy_title.png b/src/xmpppy-0.5.0rc1/doc/xmpppy_title.png Binary files differnew file mode 100644 index 00000000..6ffdfb4e --- /dev/null +++ b/src/xmpppy-0.5.0rc1/doc/xmpppy_title.png |