def _action(self, action, feed, hostname=None, sleep_time=1): if not hostname: hostname = 'firehoser.superfeedr.com' data = Iq(typ='set', to=hostname, frm=str(self.jid)) child = data.addChild('pubsub', namespace='http://jabber.org/protocol/pubsub') child.addChild(action, {'node': feed, 'jid': str(self.jid)}) self.client.send(data) if sleep_time: time.sleep(sleep_time) self.client.Process(1) self.client.disconnect()
def _get_uptime(component, client): seconds = None if 'jabber:iq:last' in component[u'info'][1] or not 'info' in component: node = client.Dispatcher.SendAndWaitForResponse( Iq(to=component[u'jid'], typ='get', queryNS='jabber:iq:last')) if isResultNode(node): # Openfire gives a 403 error seconds = int(node.getTag('query').getAttr('seconds')) return seconds
def _get_version(component, client): version = {} if 'jabber:iq:version' in component[u'info'][1] or not 'info' in component: node = client.Dispatcher.SendAndWaitForResponse( Iq(to=component[u'jid'], typ='get', queryNS='jabber:iq:version')) if isResultNode(node): for element in node.getTag('query').getChildren(): version[element.getName()] = element.getData() return version
def kick(self, room, nick, reason=None): """Kicks user from muc Works only with sufficient rights.""" NS_MUCADMIN = 'http://jabber.org/protocol/muc#admin' item = simplexml.Node('item') item.setAttr('nick', nick) item.setAttr('role', 'none') iq = Iq(typ='set', queryNS=NS_MUCADMIN, xmlns=None, to=room, payload=item) if reason is not None: item.setTagData('reason', reason) self.connect().send(iq)
def _keep_alive_clients(clients): '''Prevent client disconnections. Not sure if it really does something, but at least it captures some exceptions''' for client in list(clients): try: #client.send(' ') #client.send('<!--keepalive-->') response = client.Dispatcher.SendAndWaitForResponse( Iq(to=client.Server, typ='get', queryNS='urn:xmpp:ping')) client.Process(0.1) except ConnectionTimeout: logging.error( 'ConnectionTimeout exception on %s@%s/%s: Reconecting ' % (client.User, client.Server, client.Resource), exc_info=sys.exc_info()) # Substitute the crashed client account = { 'user': client.User, 'server': client.Server, 'password': client._Password, 'resource': client.Resource } index = clients.index(client) try: client.disconnect() except: logging.info('Error while disconecting client', exc_info=sys.exc_info()) finally: try: client = _get_connected_client(account) clients[index] = client except: logging.error("Exception while trying to log in on %s@%s", account['user'], account['server'], exc_info=True) del (clients[index]) #client.reconnectAndReauth() #client.sendInitPresence() #client.Process(1) except: logging.critical('Uncaught exception on %s@%s/%s ' % (client.User, client.Server, client.Resource), exc_info=sys.exc_info())
def send_iq(self, iq): """ Convenience function that calls L{send_stanza} and casts the response to an U{IQ node<http://xmpppy.sourceforge.net/apidocs/xmpp.protocol.Iq-class.html>}. Note that no error-checking of any kind is done, this method just assumes that the parameter you pass represents an IQ node. This will also fail if you use this method to send a response (type "error" or "result") since there is no response to be cast. @param iq: The IQ node to send @type iq: U{xmpp.protocol.Iq<http://xmpppy.sourceforge.net/apidocs/xmpp.protocol.Iq-class.html>} @return: The response cast to an IQ node. @rtype: U{xmpp.protocol.Iq<http://xmpppy.sourceforge.net/apidocs/xmpp.protocol.Iq-class.html>} @raises RuntimeError: In case communicating with the socket fails. """ from xmpp.protocol import Iq return Iq(node=self.send_stanza(iq))
def query(self, children, ns, typ='get'): """ Shortcut to send an IQ query. This method uses I{send_iq} to automatically set from/to attributes and cast the response to an IQ node. @param children: A list of U{nodes<http://xmpppy.sourceforge.net/apidocs/index.html>} that should be added as children. @type children: list @param ns: The namespace of the node. @type ns: str @param typ: The type of the node to send. @type typ: str @return: the IQ stanza returned. @rtype: U{xmpp.protocol.Iq<http://xmpppy.sourceforge.net/apidocs/xmpp.protocol.Iq-class.html>} @raises RuntimeError: In case communicating with the socket fails. """ from xmpp.protocol import Iq iq = Iq(typ=typ, queryNS=ns, payload=children) return self.send_iq(iq)
def send_tune(self, song, debug=False): """Set information about the currently played tune Song is a dictionary with keys: file, title, artist, album, pos, track, length, uri. For details see <http://xmpp.org/protocols/tune/>. """ NS_TUNE = 'http://jabber.org/protocol/tune' iq = Iq(typ='set') iq.setFrom(self.jid) iq.pubsub = iq.addChild('pubsub', namespace=NS_PUBSUB) iq.pubsub.publish = iq.pubsub.addChild('publish', attrs={'node': NS_TUNE}) iq.pubsub.publish.item = iq.pubsub.publish.addChild( 'item', attrs={'id': 'current'}) tune = iq.pubsub.publish.item.addChild('tune') tune.setNamespace(NS_TUNE) title = None if song.has_key('title'): title = song['title'] elif song.has_key('file'): title = os.path.splitext(os.path.basename(song['file']))[0] if title is not None: tune.addChild('title').addData(title) if song.has_key('artist'): tune.addChild('artist').addData(song['artist']) if song.has_key('album'): tune.addChild('source').addData(song['album']) if song.has_key('pos') and song['pos'] > 0: tune.addChild('track').addData(str(song['pos'])) if song.has_key('time'): tune.addChild('length').addData(str(song['time'])) if song.has_key('uri'): tune.addChild('uri').addData(song['uri']) if debug: self.log.info('Sending tune: %s' % iq.__str__().encode('utf8')) self.conn.send_message(iq)
def send_tune(self, song, debug=False): """Set information about the currently played tune Song is a dictionary with keys: file, title, artist, album, pos, track, length, uri. For details see <http://xmpp.org/protocols/tune/>. """ NS_TUNE = 'http://jabber.org/protocol/tune' iq = Iq(typ='set') iq.setFrom(self.jid) iq.pubsub = iq.addChild('pubsub', namespace=NS_PUBSUB) iq.pubsub.publish = iq.pubsub.addChild('publish', attrs={'node': NS_TUNE}) iq.pubsub.publish.item = iq.pubsub.publish.addChild('item', attrs={'id': 'current'}) tune = iq.pubsub.publish.item.addChild('tune') tune.setNamespace(NS_TUNE) title = None if song.has_key('title'): title = song['title'] elif song.has_key('file'): title = os.path.splitext(os.path.basename(song['file']))[0] if title is not None: tune.addChild('title').addData(title) if song.has_key('artist'): tune.addChild('artist').addData(song['artist']) if song.has_key('album'): tune.addChild('source').addData(song['album']) if song.has_key('pos') and song['pos'] > 0: tune.addChild('track').addData(str(song['pos'])) if song.has_key('time'): tune.addChild('length').addData(str(song['time'])) if song.has_key('uri'): tune.addChild('uri').addData(song['uri']) if debug: self.log.info('Sending tune: %s' % iq.__str__().encode('utf8')) self.conn.send_message(iq)
def send_tune(self, song, debug=False): """Set information about the currently played tune Song is a dictionary with keys: file, title, artist, album, pos, track, length, uri. For details see <http://xmpp.org/protocols/tune/>. """ NS_TUNE = "http://jabber.org/protocol/tune" iq = Iq(typ="set") iq.setFrom(self.jid) iq.pubsub = iq.addChild("pubsub", namespace=NS_PUBSUB) iq.pubsub.publish = iq.pubsub.addChild("publish", attrs={"node": NS_TUNE}) iq.pubsub.publish.item = iq.pubsub.publish.addChild("item", attrs={"id": "current"}) tune = iq.pubsub.publish.item.addChild("tune") tune.setNamespace(NS_TUNE) title = None if song.has_key("title"): title = song["title"] elif song.has_key("file"): title = os.path.splitext(os.path.basename(song["file"]))[0] if title is not None: tune.addChild("title").addData(title) if song.has_key("artist"): tune.addChild("artist").addData(song["artist"]) if song.has_key("album"): tune.addChild("source").addData(song["album"]) if song.has_key("pos") and song["pos"] > 0: tune.addChild("track").addData(str(song["pos"])) if song.has_key("time"): tune.addChild("length").addData(str(song["time"])) if song.has_key("uri"): tune.addChild("uri").addData(song["uri"]) if debug: self.log.info("Sending tune: %s" % iq.__str__().encode("utf8")) self.conn.send_message(iq)
def command(self, adhoc_state, vars): """ Send an ad-hoc command. The parameter vars is a list of tupels each defining name, type, and value. So if you pass the following tuple as vars:: [("var-name", "text-single", "example")] ... a field with the following XML will be send:: <field var="var-name" type="text-single"> <value>example</value> </field> The adhoc_state parameter is special to spectrumctl and identifies the command being executed. @param adhoc_state: The command identifier. @type adhoc_state: str @param vars: A list of tuples defining the fields to send. See above for more information. @todo: return str instead of None with the payload of the note stanza in case of a non-error note. @todo: use send_iq instead of doing our own wrapping/casting. @raises RuntimeError: If communicating with the socket fails or the command itself fails. """ from xmpp.simplexml import Node from xmpp.protocol import Iq, NS_DATA, NS_COMMANDS # build adhoc_state field: state_value = Node(tag='value', payload=[adhoc_state]) state = Node(tag='field', payload=[state_value], attrs={ 'type': 'hidden', 'var': 'adhoc_state' }) # build variable fields: fields = [state] for var in vars: name, typ, val = var # build payload for field: var_payload = [] if typ == 'text-multi': for line in val.splitlines(): var_payload.append(Node(tag='value', payload=[line])) else: var_payload.append(Node(tag='value', payload=[val])) # build field stanza: var_node = Node(tag='field', payload=var_payload, attrs={ 'type': typ, 'var': name }) fields.append(var_node) # build x stanza x = Node(tag='x', payload=fields, attrs={ 'xmlns': NS_DATA, 'type': 'submit' }) # build command node cmd_attrs = { 'node': 'transport_admin', 'sessionid': 'WHATEVER', 'xmlns': NS_COMMANDS } cmd = Node(tag='command', attrs=cmd_attrs, payload=[x]) # build IQ node iq = Iq(typ='set', xmlns=None) iq.addChild(node=cmd) answer = self.send_iq(iq) print("Answer: " + str(answer)) cmd = answer.kids[0] if len(cmd.kids) == 0: return note = cmd.kids[0] if note.getAttr('type') == 'error': raise RuntimeError(note.getPayload()[0])
def _try_register(client, jid, account, use_data_form): '''Try to register and unregister as specified on XEP-0100''' # TODO: Managing this with exceptions should be cleaner # Perform registration if use_data_form: reg_iq = Iq(to=jid, typ='set', queryNS='jabber:iq:register') data_form = DataForm('submit', account) reg_iq.getTag('query').addChild(node=data_form) node = client.Dispatcher.SendAndWaitForResponse(reg_iq) else: if features.register(client, jid, info=account) == 1: # Success logging.debug('Registered on %s gateway', jid) else: #print client.lastErrCode.encode('utf-8'), ' ', client.lastErr.encode('utf-8') logging.debug('Can not register on %s gateway (%s: %s)', jid, client.lastErrCode, client.lastErr) return False roster = client.getRoster() # Seconds to wait # A openfire gtalk gateway on localhost can take 21 seconds on inform of a # invalid username/password max_wait = 30 # Wait for a error message (Openfire gateways send messages) for time in range(0, max_wait): if (MESSAGES.has_key(jid) and MESSAGES[jid].has_key('error') and len(MESSAGES[jid]['error']) > 0): for message in MESSAGES[jid]['error']: logging.warning('Error message received from %s gateway: %s', jid, message) MESSAGES[jid]['error'] = [] _unregister(client, roster, jid) return False #break client.Process(1) if time < max_wait - 1: _unregister(client, roster, jid) return False # Perform subscriptions # Wait subscrition request for time in range(0, max_wait): if jid in roster.keys( ) and roster.getSubscriptionFromStatus(jid) != None: break client.Process(1) if time >= max_wait - 1: # The gateway didn't requested subscription logging.debug('Subcription request from %s gateway not received', jid) _unregister(client, roster, jid) return False if roster.getSubscriptionFromStatus(jid) == 'pending': roster.Authorize(jid) if roster.getSubscriptionToStatus(jid) == None: roster.Subscribe(jid) for time in range(0, max_wait): if roster.getSubscriptionToStatus(jid) == 'subscribed': break client.Process(1) if time >= max_wait - 1: # The gateway rejected our subscription request logging.debug('Subcription request rejected by %s gateway', jid) _unregister(client, roster, jid) return False # Try to login client.Dispatcher.send(Presence(jid)) full_client_jid = "%s@%s/%s" % (client.User, client.Server, client.Resource) for time in range(0, max_wait): if len(roster.getResources(jid)) > 0: full_gw_jid = "%s/%s" % (jid, roster.getResources(jid)[0]) if (roster.getShow(full_gw_jid) == 'unavailable' and roster.getStatus(full_gw_jid) == 'error'): # Error in login, was the account data correct? time = max_wait break elif roster.getShow(full_gw_jid) == 'xa': # J2J Transport (http://JRuDevels.org) Twisted-version uses 'xa' show # and 'Logging in...' status while trying to login pass elif ( roster.getShow(full_gw_jid) == 'available' or (roster.getShow(full_gw_jid) == roster.getShow(full_client_jid) and roster.getStatus(full_gw_jid) == roster.getStatus(full_client_jid))): # Transport seems to have logged in break client.Process(1) if time >= max_wait - 1: # Login failed logging.debug('Can not login on %s gateway', jid) _unregister(client, roster, jid) return False logging.debug('Successfull login on %s gateway', jid) # Successfull registration, now unregister _unregister(client, roster, jid) return True
def command( self, adhoc_state, vars ): """ Send an ad-hoc command. The parameter vars is a list of tupels each defining name, type, and value. So if you pass the following tuple as vars:: [("var-name", "text-single", "example")] ... a field with the following XML will be send:: <field var="var-name" type="text-single"> <value>example</value> </field> The adhoc_state parameter is special to spectrumctl and identifies the command being executed. @param adhoc_state: The command identifier. @type adhoc_state: str @param vars: A list of tuples defining the fields to send. See above for more information. @todo: return str instead of None with the payload of the note stanza in case of a non-error note. @todo: use send_iq instead of doing our own wrapping/casting. @raises RuntimeError: If communicating with the socket fails or the command itself fails. """ from xmpp.simplexml import Node from xmpp.protocol import Iq, NS_DATA, NS_COMMANDS # build adhoc_state field: state_value = Node( tag='value', payload=[adhoc_state] ) state = Node( tag='field', payload=[state_value], attrs={'type': 'hidden', 'var': 'adhoc_state'} ) # build variable fields: fields = [state] for var in vars: name, typ, val = var # build payload for field: var_payload = [] if typ == 'text-multi': for line in val.splitlines(): var_payload.append( Node( tag='value', payload=[line] ) ) else: var_payload.append( Node( tag='value', payload=[val] ) ) # build field stanza: var_node = Node( tag='field', payload=var_payload, attrs={'type': typ, 'var': name } ) fields.append( var_node ) # build x stanza x = Node( tag='x', payload=fields, attrs={ 'xmlns': NS_DATA, 'type': 'submit' } ) # build command node cmd_attrs = { 'node': 'transport_admin', 'sessionid': 'WHATEVER', 'xmlns': NS_COMMANDS } cmd = Node( tag='command', attrs=cmd_attrs, payload=[x] ) # build IQ node iq = Iq( typ='set', xmlns=None ) iq.addChild( node=cmd ) answer = self.send_iq( iq ) print( "Answer: " + str(answer) ) cmd = answer.kids[0] if len( cmd.kids ) == 0: return note = cmd.kids[0] if note.getAttr( 'type' ) == 'error': raise RuntimeError( note.getPayload()[0] )