mirror of
https://github.com/correl/SleekXMPP.git
synced 2024-11-24 03:00:15 +00:00
added pubsub state stanzas and scheduled events
This commit is contained in:
parent
0bda5fd3f2
commit
3a28f9e5d2
8 changed files with 67 additions and 23 deletions
|
@ -5,7 +5,6 @@ from xml.etree import cElementTree as ET
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
import thread
|
|
||||||
import unittest
|
import unittest
|
||||||
import sleekxmpp.plugins.xep_0004
|
import sleekxmpp.plugins.xep_0004
|
||||||
from sleekxmpp.xmlstream.matcher.stanzapath import StanzaPath
|
from sleekxmpp.xmlstream.matcher.stanzapath import StanzaPath
|
||||||
|
|
|
@ -10,6 +10,39 @@ def stanzaPlugin(stanza, plugin):
|
||||||
stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin
|
stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin
|
||||||
stanza.plugin_tag_map["{%s}%s" % (plugin.namespace, plugin.name)] = plugin
|
stanza.plugin_tag_map["{%s}%s" % (plugin.namespace, plugin.name)] = plugin
|
||||||
|
|
||||||
|
class PubsubState(ElementBase):
|
||||||
|
namespace = 'http://jabber.org/protocol/psstate'
|
||||||
|
name = 'state'
|
||||||
|
plugin_attrib = 'psstate'
|
||||||
|
interfaces = set(('node', 'item', 'payload'))
|
||||||
|
plugin_attrib_map = {}
|
||||||
|
plugin_tag_map = {}
|
||||||
|
|
||||||
|
def setPayload(self, value):
|
||||||
|
self.xml.append(value)
|
||||||
|
|
||||||
|
def getPayload(self):
|
||||||
|
childs = self.xml.getchildren()
|
||||||
|
if len(childs) > 0:
|
||||||
|
return childs[0]
|
||||||
|
|
||||||
|
def delPayload(self):
|
||||||
|
for child in self.xml.getchildren():
|
||||||
|
self.xml.remove(child)
|
||||||
|
|
||||||
|
stanzaPlugin(Iq, PubsubState)
|
||||||
|
|
||||||
|
class PubsubStateEvent(ElementBase):
|
||||||
|
namespace = 'http://jabber.org/protocol/psstate#event'
|
||||||
|
name = 'event'
|
||||||
|
plugin_attrib = 'psstate_event'
|
||||||
|
intefaces = set(tuple())
|
||||||
|
plugin_attrib_map = {}
|
||||||
|
plugin_tag_map = {}
|
||||||
|
|
||||||
|
stanzaPlugin(Message, PubsubState)
|
||||||
|
stanzaPlugin(PubsubState, PubsubStateEvent)
|
||||||
|
|
||||||
class Pubsub(ElementBase):
|
class Pubsub(ElementBase):
|
||||||
namespace = 'http://jabber.org/protocol/pubsub'
|
namespace = 'http://jabber.org/protocol/pubsub'
|
||||||
name = 'pubsub'
|
name = 'pubsub'
|
||||||
|
@ -321,18 +354,6 @@ class Options(ElementBase):
|
||||||
stanzaPlugin(Pubsub, Options)
|
stanzaPlugin(Pubsub, Options)
|
||||||
stanzaPlugin(Subscribe, Options)
|
stanzaPlugin(Subscribe, Options)
|
||||||
|
|
||||||
#iq = Iq()
|
|
||||||
#iq['pubsub']['defaultconfig']
|
|
||||||
#print(iq)
|
|
||||||
|
|
||||||
#from xml.etree import cElementTree as ET
|
|
||||||
#iq = Iq()
|
|
||||||
#item = Item()
|
|
||||||
#item['payload'] = ET.Element("{http://netflint.net/p/crap}stupidshit")
|
|
||||||
#item['id'] = 'aa11bbcc'
|
|
||||||
#iq['pubsub']['items'].append(item)
|
|
||||||
#print(iq)
|
|
||||||
|
|
||||||
class OwnerAffiliations(Affiliations):
|
class OwnerAffiliations(Affiliations):
|
||||||
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
namespace = 'http://jabber.org/protocol/pubsub#owner'
|
||||||
interfaces = set(('node'))
|
interfaces = set(('node'))
|
||||||
|
|
|
@ -188,7 +188,6 @@ class Form(FieldContainer):
|
||||||
|
|
||||||
#def getXML(self, tostring = False):
|
#def getXML(self, tostring = False):
|
||||||
def getXML(self, ftype=None):
|
def getXML(self, ftype=None):
|
||||||
logging.debug("creating form as %s" % ftype)
|
|
||||||
if ftype:
|
if ftype:
|
||||||
self.type = ftype
|
self.type = ftype
|
||||||
form = ET.Element('{jabber:x:data}x')
|
form = ET.Element('{jabber:x:data}x')
|
||||||
|
|
|
@ -14,12 +14,14 @@ class xep_0060(base.base_plugin):
|
||||||
self.xep = '0060'
|
self.xep = '0060'
|
||||||
self.description = 'Publish-Subscribe'
|
self.description = 'Publish-Subscribe'
|
||||||
|
|
||||||
def create_node(self, jid, node, config=None, collection=False):
|
def create_node(self, jid, node, config=None, collection=False, ntype=None):
|
||||||
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
|
||||||
create = ET.Element('create')
|
create = ET.Element('create')
|
||||||
create.set('node', node)
|
create.set('node', node)
|
||||||
pubsub.append(create)
|
pubsub.append(create)
|
||||||
configure = ET.Element('configure')
|
configure = ET.Element('configure')
|
||||||
|
if collection:
|
||||||
|
ntype = 'collection'
|
||||||
#if config is None:
|
#if config is None:
|
||||||
# submitform = self.xmpp.plugin['xep_0004'].makeForm('submit')
|
# submitform = self.xmpp.plugin['xep_0004'].makeForm('submit')
|
||||||
#else:
|
#else:
|
||||||
|
@ -29,11 +31,11 @@ class xep_0060(base.base_plugin):
|
||||||
submitform.field['FORM_TYPE'].setValue('http://jabber.org/protocol/pubsub#node_config')
|
submitform.field['FORM_TYPE'].setValue('http://jabber.org/protocol/pubsub#node_config')
|
||||||
else:
|
else:
|
||||||
submitform.addField('FORM_TYPE', 'hidden', value='http://jabber.org/protocol/pubsub#node_config')
|
submitform.addField('FORM_TYPE', 'hidden', value='http://jabber.org/protocol/pubsub#node_config')
|
||||||
if collection:
|
if ntype:
|
||||||
if 'pubsub#node_type' in submitform.field:
|
if 'pubsub#node_type' in submitform.field:
|
||||||
submitform.field['pubsub#node_type'].setValue('collection')
|
submitform.field['pubsub#node_type'].setValue(ntype)
|
||||||
else:
|
else:
|
||||||
submitform.addField('pubsub#node_type', value='collection')
|
submitform.addField('pubsub#node_type', value=ntype)
|
||||||
else:
|
else:
|
||||||
if 'pubsub#node_type' in submitform.field:
|
if 'pubsub#node_type' in submitform.field:
|
||||||
submitform.field['pubsub#node_type'].setValue('leaf')
|
submitform.field['pubsub#node_type'].setValue('leaf')
|
||||||
|
|
|
@ -4,6 +4,7 @@ except ImportError:
|
||||||
import Queue as queue
|
import Queue as queue
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
import logging
|
||||||
|
|
||||||
class Task(object):
|
class Task(object):
|
||||||
"""Task object for the Scheduler class"""
|
"""Task object for the Scheduler class"""
|
||||||
|
@ -34,7 +35,7 @@ class Scheduler(object):
|
||||||
self.addq = queue.Queue()
|
self.addq = queue.Queue()
|
||||||
self.schedule = []
|
self.schedule = []
|
||||||
self.thread = None
|
self.thread = None
|
||||||
self.run = True
|
self.run = False
|
||||||
|
|
||||||
def process(self, threaded=True):
|
def process(self, threaded=True):
|
||||||
if threaded:
|
if threaded:
|
||||||
|
@ -44,6 +45,7 @@ class Scheduler(object):
|
||||||
self._process()
|
self._process()
|
||||||
|
|
||||||
def _process(self):
|
def _process(self):
|
||||||
|
self.run = True
|
||||||
while self.run:
|
while self.run:
|
||||||
wait = 5
|
wait = 5
|
||||||
updated = False
|
updated = False
|
||||||
|
@ -67,7 +69,7 @@ class Scheduler(object):
|
||||||
self.schedule.append(newtask)
|
self.schedule.append(newtask)
|
||||||
finally:
|
finally:
|
||||||
if updated: self.schedule = sorted(self.schedule, key=lambda task: task.next)
|
if updated: self.schedule = sorted(self.schedule, key=lambda task: task.next)
|
||||||
print [x.name for x in self.schedule]
|
logging.debug("Qutting Scheduler thread")
|
||||||
|
|
||||||
def add(self, name, seconds, callback, args=None, kwargs=None, repeat=False, qpointer=None):
|
def add(self, name, seconds, callback, args=None, kwargs=None, repeat=False, qpointer=None):
|
||||||
self.addq.put(Task(name, seconds, callback, args, kwargs, repeat, qpointer))
|
self.addq.put(Task(name, seconds, callback, args, kwargs, repeat, qpointer))
|
||||||
|
|
|
@ -319,6 +319,8 @@ class StanzaBase(ElementBase):
|
||||||
|
|
||||||
def __init__(self, stream=None, xml=None, stype=None, sto=None, sfrom=None, sid=None):
|
def __init__(self, stream=None, xml=None, stype=None, sto=None, sfrom=None, sid=None):
|
||||||
self.stream = stream
|
self.stream = stream
|
||||||
|
if stream is not None:
|
||||||
|
self.namespace = stream.default_ns
|
||||||
ElementBase.__init__(self, xml)
|
ElementBase.__init__(self, xml)
|
||||||
if stype is not None:
|
if stype is not None:
|
||||||
self['type'] = stype
|
self['type'] = stype
|
||||||
|
@ -326,8 +328,6 @@ class StanzaBase(ElementBase):
|
||||||
self['to'] = sto
|
self['to'] = sto
|
||||||
if sfrom is not None:
|
if sfrom is not None:
|
||||||
self['from'] = sfrom
|
self['from'] = sfrom
|
||||||
if stream is not None:
|
|
||||||
self.namespace = stream.default_ns
|
|
||||||
self.tag = "{%s}%s" % (self.namespace, self.name)
|
self.tag = "{%s}%s" % (self.namespace, self.name)
|
||||||
|
|
||||||
def setType(self, value):
|
def setType(self, value):
|
||||||
|
|
|
@ -180,6 +180,7 @@ class XMLStream(object):
|
||||||
self.state.set('reconnect', False)
|
self.state.set('reconnect', False)
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
self.run = False
|
self.run = False
|
||||||
|
self.scheduler.run = False
|
||||||
self.eventqueue.put(('quit', None, None))
|
self.eventqueue.put(('quit', None, None))
|
||||||
return
|
return
|
||||||
except CloseStream:
|
except CloseStream:
|
||||||
|
@ -226,6 +227,7 @@ class XMLStream(object):
|
||||||
edepth += -1
|
edepth += -1
|
||||||
if edepth == 0 and event == b'end':
|
if edepth == 0 and event == b'end':
|
||||||
self.disconnect(reconnect=self.state['reconnect'])
|
self.disconnect(reconnect=self.state['reconnect'])
|
||||||
|
logging.debug("Ending readXML loop")
|
||||||
return False
|
return False
|
||||||
elif edepth == 1:
|
elif edepth == 1:
|
||||||
#self.xmlin.put(xmlobj)
|
#self.xmlin.put(xmlobj)
|
||||||
|
@ -234,11 +236,13 @@ class XMLStream(object):
|
||||||
except RestartStream:
|
except RestartStream:
|
||||||
return True
|
return True
|
||||||
except CloseStream:
|
except CloseStream:
|
||||||
|
logging.debug("Ending readXML loop")
|
||||||
return False
|
return False
|
||||||
if root:
|
if root:
|
||||||
root.clear()
|
root.clear()
|
||||||
if event == b'start':
|
if event == b'start':
|
||||||
edepth += 1
|
edepth += 1
|
||||||
|
logging.debug("Ending readXML loop")
|
||||||
|
|
||||||
def _sendThread(self):
|
def _sendThread(self):
|
||||||
while self.run:
|
while self.run:
|
||||||
|
@ -268,6 +272,7 @@ class XMLStream(object):
|
||||||
logging.debug("Disconnecting...")
|
logging.debug("Disconnecting...")
|
||||||
self.state.set('disconnecting', True)
|
self.state.set('disconnecting', True)
|
||||||
self.run = False
|
self.run = False
|
||||||
|
self.scheduler.run = False
|
||||||
if self.state['connected']:
|
if self.state['connected']:
|
||||||
self.sendRaw(self.stream_footer)
|
self.sendRaw(self.stream_footer)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
@ -339,7 +344,8 @@ class XMLStream(object):
|
||||||
args[0].exception(e)
|
args[0].exception(e)
|
||||||
elif etype == 'schedule':
|
elif etype == 'schedule':
|
||||||
try:
|
try:
|
||||||
handler.run(*args)
|
logging.debug(args)
|
||||||
|
handler(*args[0])
|
||||||
except:
|
except:
|
||||||
logging.error(traceback.format_exc())
|
logging.error(traceback.format_exc())
|
||||||
elif etype == 'quit':
|
elif etype == 'quit':
|
||||||
|
|
|
@ -97,6 +97,21 @@ class testpubsubstanzas(unittest.TestCase):
|
||||||
iq3.setValues(values)
|
iq3.setValues(values)
|
||||||
self.failUnless(xmlstring == str(iq) == str(iq2) == str(iq3))
|
self.failUnless(xmlstring == str(iq) == str(iq2) == str(iq3))
|
||||||
|
|
||||||
|
def testState(self):
|
||||||
|
"Testing iq/psstate stanzas"
|
||||||
|
from sleekxmpp.plugins import xep_0004
|
||||||
|
iq = self.ps.Iq()
|
||||||
|
iq['psstate']['node']= 'mynode'
|
||||||
|
iq['psstate']['item']= 'myitem'
|
||||||
|
pl = ET.Element('{http://andyet.net/protocol/pubsubqueue}claimed')
|
||||||
|
iq['psstate']['payload'] = pl
|
||||||
|
xmlstring = """<iq id="0"><state xmlns="http://jabber.org/protocol/psstate" node="mynode" item="myitem"><claimed xmlns="http://andyet.net/protocol/pubsubqueue" /></state></iq>"""
|
||||||
|
iq2 = self.ps.Iq(None, self.ps.ET.fromstring(xmlstring))
|
||||||
|
iq3 = self.ps.Iq()
|
||||||
|
values = iq2.getValues()
|
||||||
|
iq3.setValues(values)
|
||||||
|
self.failUnless(xmlstring == str(iq) == str(iq2) == str(iq3))
|
||||||
|
|
||||||
def testDefault(self):
|
def testDefault(self):
|
||||||
"Testing iq/pubsub_owner/default stanzas"
|
"Testing iq/pubsub_owner/default stanzas"
|
||||||
from sleekxmpp.plugins import xep_0004
|
from sleekxmpp.plugins import xep_0004
|
||||||
|
|
Loading…
Reference in a new issue