diff options
Diffstat (limited to 'examples')
29 files changed, 1029 insertions, 146 deletions
diff --git a/examples/IoT_TestDevice.py b/examples/IoT_TestDevice.py new file mode 100755 index 00000000..cd80cee2 --- /dev/null +++ b/examples/IoT_TestDevice.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" + SleekXMPP: The Sleek XMPP Library + Implementation of xeps for Internet of Things + http://wiki.xmpp.org/web/Tech_pages/IoT_systems + Copyright (C) 2013 Sustainable Innovation, Joachim.lindborg@sust.se + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +import os +import sys +# This can be used when you are in a test environment and need to make paths right +sys.path=['/Users/jocke/Dropbox/06_dev/SleekXMPP']+sys.path + +import logging +import unittest +import distutils.core +import datetime + +from glob import glob +from os.path import splitext, basename, join as pjoin +from optparse import OptionParser +from urllib import urlopen + +import sleekxmpp +# Python versions before 3.0 do not use UTF-8 encoding +# by default. To ensure that Unicode is handled properly +# throughout SleekXMPP, we will set the default encoding +# ourselves to UTF-8. +if sys.version_info < (3, 0): + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') +else: + raw_input = input + +from sleekxmpp.plugins.xep_0323.device import Device + +#from sleekxmpp.exceptions import IqError, IqTimeout + +class IoT_TestDevice(sleekxmpp.ClientXMPP): + + """ + A simple IoT device that can act as server or client + """ + def __init__(self, jid, password): + sleekxmpp.ClientXMPP.__init__(self, jid, password) + self.add_event_handler("session_start", self.session_start) + self.add_event_handler("message", self.message) + self.device=None + self.releaseMe=False + self.beServer=True + self.clientJID=None + + def datacallback(self,from_jid,result,nodeId=None,timestamp=None,fields=None,error_msg=None): + """ + This method will be called when you ask another IoT device for data with the xep_0323 + se script below for the registration of the callback + """ + logging.debug("we got data %s from %s",str(result),from_jid) + + def beClientOrServer(self,server=True,clientJID=None ): + if server: + self.beServer=True + self.clientJID=None + else: + self.beServer=False + self.clientJID=clientJID + + def testForRelease(self): + # todo thread safe + return self.releaseMe + + def doReleaseMe(self): + # todo thread safe + self.releaseMe=True + + def addDevice(self, device): + self.device=device + + def session_start(self, event): + self.send_presence() + self.get_roster() + # tell your preffered friend that you are alive + self.send_message(mto='jocke@jabber.sust.se', mbody=self.boundjid.bare +' is now online use xep_323 stanza to talk to me') + + if not(self.beServer): + session=self['xep_0323'].request_data(self.boundjid.full,self.clientJID,self.datacallback) + + def message(self, msg): + if msg['type'] in ('chat', 'normal'): + logging.debug("got normal chat message" + str(msg)) + ip=urlopen('http://icanhazip.com').read() + msg.reply("Hi I am " + self.boundjid.full + " and I am on IP " + ip).send() + else: + logging.debug("got unknown message type %s", str(msg['type'])) + +class TheDevice(Device): + """ + This is the actual device object that you will use to get information from your real hardware + You will be called in the refresh method when someone is requesting information from you + """ + def __init__(self,nodeId): + Device.__init__(self,nodeId) + self.counter=0 + + def refresh(self,fields): + """ + the implementation of the refresh method + """ + self._set_momentary_timestamp(self._get_timestamp()) + self.counter+=self.counter + self._add_field_momentary_data(self, "Temperature", self.counter) + +if __name__ == '__main__': + + # Setup the command line arguments. + # + # This script can act both as + # "server" an IoT device that can provide sensorinformation + # python IoT_TestDevice.py -j "serverjid@yourdomain.com" -p "password" -n "TestIoT" --debug + # + # "client" an IoT device or other party that would like to get data from another device + + optp = OptionParser() + + # Output verbosity options. + optp.add_option('-q', '--quiet', help='set logging to ERROR', + action='store_const', dest='loglevel', + const=logging.ERROR, default=logging.INFO) + optp.add_option('-d', '--debug', help='set logging to DEBUG', + action='store_const', dest='loglevel', + const=logging.DEBUG, default=logging.INFO) + optp.add_option('-v', '--verbose', help='set logging to COMM', + action='store_const', dest='loglevel', + const=5, default=logging.INFO) + optp.add_option('-t', '--pingto', help='set jid to ping', + action='store', type='string', dest='pingjid', + default=None) + + # JID and password options. + optp.add_option("-j", "--jid", dest="jid", + help="JID to use") + optp.add_option("-p", "--password", dest="password", + help="password to use") + + # IoT test + optp.add_option("-c", "--sensorjid", dest="sensorjid", + help="Another device to call for data on", default=None) + optp.add_option("-n", "--nodeid", dest="nodeid", + help="I am a device get ready to be called", default=None) + + opts, args = optp.parse_args() + + # Setup logging. + logging.basicConfig(level=opts.loglevel, + format='%(levelname)-8s %(message)s') + + if opts.jid is None: + opts.jid = raw_input("Username: ") + if opts.password is None: + opts.password = getpass.getpass("Password: ") + + + xmpp = IoT_TestDevice(opts.jid,opts.password) + xmpp.register_plugin('xep_0030') + #xmpp['xep_0030'].add_feature(feature='urn:xmpp:iot:sensordata', + # node=None, + # jid=None) + xmpp.register_plugin('xep_0323') + xmpp.register_plugin('xep_0325') + + if opts.nodeid: + + # xmpp['xep_0030'].add_feature(feature='urn:xmpp:sn', + # node=opts.nodeid, + # jid=xmpp.boundjid.full) + + myDevice = TheDevice(opts.nodeid) + # myDevice._add_field(name="Relay", typename="numeric", unit="Bool"); + myDevice._add_field(name="Temperature", typename="numeric", unit="C") + myDevice._set_momentary_timestamp("2013-03-07T16:24:30") + myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"}) + + xmpp['xep_0323'].register_node(nodeId=opts.nodeid, device=myDevice, commTimeout=10) + xmpp.beClientOrServer(server=True) + while not(xmpp.testForRelease()): + xmpp.connect() + xmpp.process(block=True) + logging.debug("lost connection") + if opts.sensorjid: + logging.debug("will try to call another device for data") + xmpp.beClientOrServer(server=False,clientJID=opts.sensorjid) + xmpp.connect() + xmpp.process(block=True) + logging.debug("ready ending") + + else: + print "noopp didn't happen" + diff --git a/examples/adhoc_provider.py b/examples/adhoc_provider.py index a72158c3..86a575c9 100755 --- a/examples/adhoc_provider.py +++ b/examples/adhoc_provider.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/adhoc_user.py b/examples/adhoc_user.py index bbd42d81..7df9f793 100755 --- a/examples/adhoc_user.py +++ b/examples/adhoc_user.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/admin_commands.py b/examples/admin_commands.py new file mode 100755 index 00000000..5d9bf841 --- /dev/null +++ b/examples/admin_commands.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" + SleekXMPP: The Sleek XMPP Library + Copyright (C) 2010 Nathanael C. Fritz + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +import sys +import logging +import getpass +from optparse import OptionParser + +import sleekxmpp + +# Python versions before 3.0 do not use UTF-8 encoding +# by default. To ensure that Unicode is handled properly +# throughout SleekXMPP, we will set the default encoding +# ourselves to UTF-8. +if sys.version_info < (3, 0): + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') +else: + raw_input = input + + +class AdminCommands(sleekxmpp.ClientXMPP): + + """ + A simple SleekXMPP bot that uses admin commands to + add a new user to a server. + """ + + def __init__(self, jid, password, command): + sleekxmpp.ClientXMPP.__init__(self, jid, password) + + self.command = command + + self.add_event_handler("session_start", self.start) + + def start(self, event): + """ + Process the session_start event. + + Typical actions for the session_start event are + requesting the roster and broadcasting an initial + presence stanza. + + Arguments: + event -- An empty dictionary. The session_start + event does not provide any additional + data. + """ + self.send_presence() + self.get_roster() + + def command_success(iq, session): + print('Command completed') + if iq['command']['form']: + for var, field in iq['command']['form']['fields'].items(): + print('%s: %s' % (var, field['value'])) + if iq['command']['notes']: + print('Command Notes:') + for note in iq['command']['notes']: + print('%s: %s' % note) + self.disconnect() + + def command_error(iq, session): + print('Error completing command') + print('%s: %s' % (iq['error']['condition'], + iq['error']['text'])) + self['xep_0050'].terminate_command(session) + self.disconnect() + + def process_form(iq, session): + form = iq['command']['form'] + answers = {} + for var, field in form['fields'].items(): + if var != 'FORM_TYPE': + if field['type'] == 'boolean': + answers[var] = raw_input('%s (y/n): ' % field['label']) + if answers[var].lower() in ('1', 'true', 'y', 'yes'): + answers[var] = '1' + else: + answers[var] = '0' + else: + answers[var] = raw_input('%s: ' % field['label']) + else: + answers['FORM_TYPE'] = field['value'] + form['type'] = 'submit' + form['values'] = answers + + session['next'] = command_success + session['payload'] = form + + self['xep_0050'].complete_command(session) + + session = {'next': process_form, + 'error': command_error} + + command = self.command.replace('-', '_') + handler = getattr(self['xep_0133'], command, None) + + if handler: + handler(session={ + 'next': process_form, + 'error': command_error + }) + else: + print('Invalid command name: %s' % self.command) + self.disconnect() + + +if __name__ == '__main__': + # Setup the command line arguments. + optp = OptionParser() + + # Output verbosity options. + optp.add_option('-q', '--quiet', help='set logging to ERROR', + action='store_const', dest='loglevel', + const=logging.ERROR, default=logging.INFO) + optp.add_option('-d', '--debug', help='set logging to DEBUG', + action='store_const', dest='loglevel', + const=logging.DEBUG, default=logging.INFO) + optp.add_option('-v', '--verbose', help='set logging to COMM', + action='store_const', dest='loglevel', + const=5, default=logging.INFO) + + # JID and password options. + optp.add_option("-j", "--jid", dest="jid", + help="JID to use") + optp.add_option("-p", "--password", dest="password", + help="password to use") + optp.add_option("-c", "--command", dest="command", + help="admin command to use") + + opts, args = optp.parse_args() + + # Setup logging. + logging.basicConfig(level=opts.loglevel, + format='%(levelname)-8s %(message)s') + + if opts.jid is None: + opts.jid = raw_input("Username: ") + if opts.password is None: + opts.password = getpass.getpass("Password: ") + if opts.command is None: + opts.command = raw_input("Admin command: ") + + # Setup the CommandBot and register plugins. Note that while plugins may + # have interdependencies, the order in which you register them does + # not matter. + xmpp = AdminCommands(opts.jid, opts.password, opts.command) + xmpp.register_plugin('xep_0133') # Service Administration + + # If you are working with an OpenFire server, you may need + # to adjust the SSL version used: + # xmpp.ssl_version = ssl.PROTOCOL_SSLv3 + + # If you want to verify the SSL certificates offered by a server: + # xmpp.ca_certs = "path/to/ca/cert" + + # Connect to the XMPP server and start processing XMPP stanzas. + if xmpp.connect(): + # If you do not have the dnspython library installed, you will need + # to manually specify the name of the server if it does not match + # the one in the JID. For example, to use Google Talk you would + # need to use: + # + # if xmpp.connect(('talk.google.com', 5222)): + # ... + xmpp.process(block=True) + print("Done") + else: + print("Unable to connect.") diff --git a/examples/custom_stanzas/custom_stanza_provider.py b/examples/custom_stanzas/custom_stanza_provider.py index b532c17c..0ebdb77e 100755 --- a/examples/custom_stanzas/custom_stanza_provider.py +++ b/examples/custom_stanzas/custom_stanza_provider.py @@ -28,8 +28,8 @@ from stanza import Action # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input @@ -51,13 +51,13 @@ class ActionBot(sleekxmpp.ClientXMPP): # our roster. self.add_event_handler("session_start", self.start) - self.registerHandler( + self.register_handler( Callback('Some custom iq', StanzaPath('iq@type=set/action'), self._handle_action)) - self.add_event_handler('custom_action', - self._handle_action_event, + self.add_event_handler('custom_action', + self._handle_action_event, threaded=True) register_stanza_plugin(Iq, Action) diff --git a/examples/custom_stanzas/custom_stanza_user.py b/examples/custom_stanzas/custom_stanza_user.py index 5b5042c7..418e3218 100755 --- a/examples/custom_stanzas/custom_stanza_user.py +++ b/examples/custom_stanzas/custom_stanza_user.py @@ -26,8 +26,8 @@ from stanza import Action # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/disco_browser.py b/examples/disco_browser.py index ff0af97d..aeb4fb5e 100755 --- a/examples/disco_browser.py +++ b/examples/disco_browser.py @@ -15,6 +15,7 @@ import getpass from optparse import OptionParser import sleekxmpp +from sleekxmpp.exceptions import IqError, IqTimeout # Python versions before 3.0 do not use UTF-8 encoding @@ -22,8 +23,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input @@ -83,50 +84,54 @@ class Disco(sleekxmpp.ClientXMPP): self.get_roster() self.send_presence() - if self.get in self.info_types: - # By using block=True, the result stanza will be - # returned. Execution will block until the reply is - # received. Non-blocking options would be to listen - # for the disco_info event, or passing a handler - # function using the callback parameter. - info = self['xep_0030'].get_info(jid=self.target_jid, - node=self.target_node, - block=True) - if self.get in self.items_types: - # The same applies from above. Listen for the - # disco_items event or pass a callback function - # if you need to process a non-blocking request. - items = self['xep_0030'].get_items(jid=self.target_jid, - node=self.target_node, - block=True) + try: + if self.get in self.info_types: + # By using block=True, the result stanza will be + # returned. Execution will block until the reply is + # received. Non-blocking options would be to listen + # for the disco_info event, or passing a handler + # function using the callback parameter. + info = self['xep_0030'].get_info(jid=self.target_jid, + node=self.target_node, + block=True) + elif self.get in self.items_types: + # The same applies from above. Listen for the + # disco_items event or pass a callback function + # if you need to process a non-blocking request. + items = self['xep_0030'].get_items(jid=self.target_jid, + node=self.target_node, + block=True) + else: + logging.error("Invalid disco request type.") + return + except IqError as e: + logging.error("Entity returned an error: %s" % e.iq['error']['condition']) + except IqTimeout: + logging.error("No response received.") else: - logging.error("Invalid disco request type.") - self.disconnect() - return - - header = 'XMPP Service Discovery: %s' % self.target_jid - print(header) - print('-' * len(header)) - if self.target_node != '': - print('Node: %s' % self.target_node) + header = 'XMPP Service Discovery: %s' % self.target_jid + print(header) print('-' * len(header)) - - if self.get in self.identity_types: - print('Identities:') - for identity in info['disco_info']['identities']: - print(' - %s' % str(identity)) - - if self.get in self.feature_types: - print('Features:') - for feature in info['disco_info']['features']: - print(' - %s' % feature) - - if self.get in self.items_types: - print('Items:') - for item in items['disco_items']['items']: - print(' - %s' % str(item)) - - self.disconnect() + if self.target_node != '': + print('Node: %s' % self.target_node) + print('-' * len(header)) + + if self.get in self.identity_types: + print('Identities:') + for identity in info['disco_info']['identities']: + print(' - %s' % str(identity)) + + if self.get in self.feature_types: + print('Features:') + for feature in info['disco_info']['features']: + print(' - %s' % feature) + + if self.get in self.items_types: + print('Items:') + for item in items['disco_items']['items']: + print(' - %s' % str(item)) + finally: + self.disconnect() if __name__ == '__main__': diff --git a/examples/download_avatars.py b/examples/download_avatars.py new file mode 100755 index 00000000..64300cff --- /dev/null +++ b/examples/download_avatars.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" + SleekXMPP: The Sleek XMPP Library + Copyright (C) 2012 Nathanael C. Fritz + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +import sys +import logging +import getpass +import threading +from optparse import OptionParser + +import sleekxmpp +from sleekxmpp.exceptions import XMPPError + + +# Python versions before 3.0 do not use UTF-8 encoding +# by default. To ensure that Unicode is handled properly +# throughout SleekXMPP, we will set the default encoding +# ourselves to UTF-8. +if sys.version_info < (3, 0): + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') +else: + raw_input = input + + +FILE_TYPES = { + 'image/png': 'png', + 'image/gif': 'gif', + 'image/jpeg': 'jpg' +} + + +class AvatarDownloader(sleekxmpp.ClientXMPP): + + """ + A basic script for downloading the avatars for a user's contacts. + """ + + def __init__(self, jid, password): + sleekxmpp.ClientXMPP.__init__(self, jid, password) + self.add_event_handler("session_start", self.start, threaded=True) + self.add_event_handler("changed_status", self.wait_for_presences) + + self.add_event_handler('vcard_avatar_update', self.on_vcard_avatar) + self.add_event_handler('avatar_metadata_publish', self.on_avatar) + + self.received = set() + self.presences_received = threading.Event() + + def start(self, event): + """ + Process the session_start event. + + Typical actions for the session_start event are + requesting the roster and broadcasting an initial + presence stanza. + + Arguments: + event -- An empty dictionary. The session_start + event does not provide any additional + data. + """ + self.send_presence() + self.get_roster() + + print('Waiting for presence updates...\n') + self.presences_received.wait(15) + self.disconnect(wait=True) + + def on_vcard_avatar(self, pres): + print("Received vCard avatar update from %s" % pres['from'].bare) + try: + result = self['xep_0054'].get_vcard(pres['from'], cached=True) + except XMPPError: + print("Error retrieving avatar for %s" % pres['from']) + return + avatar = result['vcard_temp']['PHOTO'] + + filetype = FILE_TYPES.get(avatar['TYPE'], 'png') + filename = 'vcard_avatar_%s_%s.%s' % ( + pres['from'].bare, + pres['vcard_temp_update']['photo'], + filetype) + with open(filename, 'w+') as img: + img.write(avatar['BINVAL']) + + def on_avatar(self, msg): + print("Received avatar update from %s" % msg['from']) + metadata = msg['pubsub_event']['items']['item']['avatar_metadata'] + for info in metadata['items']: + if not info['url']: + try: + result = self['xep_0084'].retrieve_avatar(msg['from'], info['id']) + except XMPPError: + print("Error retrieving avatar for %s" % msg['from']) + return + + avatar = result['pubsub']['items']['item']['avatar_data'] + + filetype = FILE_TYPES.get(metadata['type'], 'png') + filename = 'avatar_%s_%s.%s' % (msg['from'].bare, info['id'], filetype) + with open(filename, 'w+') as img: + img.write(avatar['value']) + else: + # We could retrieve the avatar via HTTP, etc here instead. + pass + + def wait_for_presences(self, pres): + """ + Wait to receive updates from all roster contacts. + """ + self.received.add(pres['from'].bare) + if len(self.received) >= len(self.client_roster.keys()): + self.presences_received.set() + else: + self.presences_received.clear() + + +if __name__ == '__main__': + # Setup the command line arguments. + optp = OptionParser() + optp.add_option('-q','--quiet', help='set logging to ERROR', + action='store_const', + dest='loglevel', + const=logging.ERROR, + default=logging.ERROR) + optp.add_option('-d','--debug', help='set logging to DEBUG', + action='store_const', + dest='loglevel', + const=logging.DEBUG, + default=logging.ERROR) + optp.add_option('-v','--verbose', help='set logging to COMM', + action='store_const', + dest='loglevel', + const=5, + default=logging.ERROR) + + # JID and password options. + optp.add_option("-j", "--jid", dest="jid", + help="JID to use") + optp.add_option("-p", "--password", dest="password", + help="password to use") + opts,args = optp.parse_args() + + # Setup logging. + logging.basicConfig(level=opts.loglevel, + format='%(levelname)-8s %(message)s') + + if opts.jid is None: + opts.jid = raw_input("Username: ") + if opts.password is None: + opts.password = getpass.getpass("Password: ") + + xmpp = AvatarDownloader(opts.jid, opts.password) + xmpp.register_plugin('xep_0054') + xmpp.register_plugin('xep_0153') + xmpp.register_plugin('xep_0084') + + # If you are working with an OpenFire server, you may need + # to adjust the SSL version used: + # xmpp.ssl_version = ssl.PROTOCOL_SSLv3 + + # If you want to verify the SSL certificates offered by a server: + # xmpp.ca_certs = "path/to/ca/cert" + + # Connect to the XMPP server and start processing XMPP stanzas. + if xmpp.connect(): + # If you do not have the dnspython library installed, you will need + # to manually specify the name of the server if it does not match + # the one in the JID. For example, to use Google Talk you would + # need to use: + # + # if xmpp.connect(('talk.google.com', 5222)): + # ... + xmpp.process(block=True) + else: + print("Unable to connect.") diff --git a/examples/echo_client.py b/examples/echo_client.py index 73990089..f2d38847 100755 --- a/examples/echo_client.py +++ b/examples/echo_client.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/echo_component.py b/examples/echo_component.py index 82f6eb9f..9a24f2fa 100755 --- a/examples/echo_component.py +++ b/examples/echo_component.py @@ -22,8 +22,8 @@ from sleekxmpp.componentxmpp import ComponentXMPP # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/gtalk_custom_domain.py b/examples/gtalk_custom_domain.py index 0226c146..c974fc55 100755 --- a/examples/gtalk_custom_domain.py +++ b/examples/gtalk_custom_domain.py @@ -25,8 +25,8 @@ from sleekxmpp.xmlstream import cert # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/ibb_transfer/ibb_receiver.py b/examples/ibb_transfer/ibb_receiver.py index b11acabf..6aba98e3 100755 --- a/examples/ibb_transfer/ibb_receiver.py +++ b/examples/ibb_transfer/ibb_receiver.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input @@ -38,7 +38,7 @@ class IBBReceiver(sleekxmpp.ClientXMPP): self.register_plugin('xep_0030') # Service Discovery self.register_plugin('xep_0047', { - 'accept_stream': self.accept_stream + 'auto_accept': True }) # In-band Bytestreams # The session_start event will be triggered when @@ -48,7 +48,7 @@ class IBBReceiver(sleekxmpp.ClientXMPP): # our roster. self.add_event_handler("session_start", self.start) - self.add_event_handler("ibb_stream_start", self.stream_opened) + self.add_event_handler("ibb_stream_start", self.stream_opened, threaded=True) self.add_event_handler("ibb_stream_data", self.stream_data) def start(self, event): @@ -69,7 +69,7 @@ class IBBReceiver(sleekxmpp.ClientXMPP): def accept_stream(self, iq): """ - Check that it is ok to accept a stream request. + Check that it is ok to accept a stream request. Controlling stream acceptance can be done via either: - setting 'auto_accept' to False in the plugin @@ -83,9 +83,7 @@ class IBBReceiver(sleekxmpp.ClientXMPP): return True def stream_opened(self, stream): - # NOTE: IBB streams are bi-directional, so the original sender is - # now the opened stream's receiver. - print('Stream opened: %s from ' % (stream.sid, stream.receiver)) + print('Stream opened: %s from %s' % (stream.sid, stream.peer_jid)) # You could run a loop reading from the stream using stream.recv(), # or use the ibb_stream_data event. diff --git a/examples/ibb_transfer/ibb_sender.py b/examples/ibb_transfer/ibb_sender.py index cd856378..7c380b68 100755 --- a/examples/ibb_transfer/ibb_sender.py +++ b/examples/ibb_transfer/ibb_sender.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/migrate_roster.py b/examples/migrate_roster.py new file mode 100755 index 00000000..797e4f44 --- /dev/null +++ b/examples/migrate_roster.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import logging +import getpass +from optparse import OptionParser + +import sleekxmpp + +# Python versions before 3.0 do not use UTF-8 encoding +# by default. To ensure that Unicode is handled properly +# throughout SleekXMPP, we will set the default encoding +# ourselves to UTF-8. +if sys.version_info < (3, 0): + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') +else: + raw_input = input + + +# Setup the command line arguments. +optp = OptionParser() + +# Output verbosity options. +optp.add_option('-q', '--quiet', help='set logging to ERROR', + action='store_const', dest='loglevel', + const=logging.ERROR, default=logging.INFO) +optp.add_option('-d', '--debug', help='set logging to DEBUG', + action='store_const', dest='loglevel', + const=logging.DEBUG, default=logging.INFO) +optp.add_option('-v', '--verbose', help='set logging to COMM', + action='store_const', dest='loglevel', + const=5, default=logging.INFO) + +# JID and password options. +optp.add_option("--oldjid", dest="old_jid", + help="JID of the old account") +optp.add_option("--oldpassword", dest="old_password", + help="password of the old account") + +optp.add_option("--newjid", dest="new_jid", + help="JID of the old account") +optp.add_option("--newpassword", dest="new_password", + help="password of the old account") + + +opts, args = optp.parse_args() + +# Setup logging. +logging.basicConfig(level=opts.loglevel, + format='%(levelname)-8s %(message)s') + +if opts.old_jid is None: + opts.old_jid = raw_input("Old JID: ") +if opts.old_password is None: + opts.old_password = getpass.getpass("Old Password: ") + +if opts.new_jid is None: + opts.new_jid = raw_input("New JID: ") +if opts.new_password is None: + opts.new_password = getpass.getpass("New Password: ") + + +old_xmpp = sleekxmpp.ClientXMPP(opts.old_jid, opts.old_password) + +# If you are connecting to Facebook and wish to use the +# X-FACEBOOK-PLATFORM authentication mechanism, you will need +# your API key and an access token. Then you'll set: +# xmpp.credentials['api_key'] = 'THE_API_KEY' +# xmpp.credentials['access_token'] = 'THE_ACCESS_TOKEN' + +# If you are connecting to MSN, then you will need an +# access token, and it does not matter what JID you +# specify other than that the domain is 'messenger.live.com', +# so '_@messenger.live.com' will work. You can specify +# the access token as so: +# xmpp.credentials['access_token'] = 'THE_ACCESS_TOKEN' + +# If you are working with an OpenFire server, you may need +# to adjust the SSL version used: +# xmpp.ssl_version = ssl.PROTOCOL_SSLv3 + +# If you want to verify the SSL certificates offered by a server: +# xmpp.ca_certs = "path/to/ca/cert" + +roster = [] + +def on_session(event): + roster.append(old_xmpp.get_roster()) + old_xmpp.disconnect() +old_xmpp.add_event_handler('session_start', on_session) + +if old_xmpp.connect(): + old_xmpp.process(block=True) + +if not roster: + print('No roster to migrate') + sys.exit() + +new_xmpp = sleekxmpp.ClientXMPP(opts.new_jid, opts.new_password) +def on_session2(event): + new_xmpp.get_roster() + new_xmpp.send_presence() + + logging.info(roster[0]) + data = roster[0]['roster']['items'] + logging.info(data) + + for jid, item in data.items(): + if item['subscription'] != 'none': + new_xmpp.send_presence(ptype='subscribe', pto=jid) + new_xmpp.update_roster(jid, + name = item['name'], + groups = item['groups']) + new_xmpp.disconnect() +new_xmpp.add_event_handler('session_start', on_session2) + +if new_xmpp.connect(): + new_xmpp.process(block=True) diff --git a/examples/muc.py b/examples/muc.py index 7b93da16..5b5c764c 100755 --- a/examples/muc.py +++ b/examples/muc.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/ping.py b/examples/ping.py index fe4d23a4..1a1c2e94 100755 --- a/examples/ping.py +++ b/examples/ping.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input @@ -37,7 +37,7 @@ class PingTest(sleekxmpp.ClientXMPP): def __init__(self, jid, password, pingjid): sleekxmpp.ClientXMPP.__init__(self, jid, password) if pingjid is None: - pingjid = self.jid + pingjid = self.boundjid.bare self.pingjid = pingjid # The session_start event will be triggered when @@ -62,16 +62,18 @@ class PingTest(sleekxmpp.ClientXMPP): """ self.send_presence() self.get_roster() - result = self['xep_0199'].send_ping(self.pingjid, - timeout=10, - errorfalse=True) - logging.info("Pinging...") - if result is False: - logging.info("Couldn't ping.") - self.disconnect() - sys.exit(1) - else: - logging.info("Success! RTT: %s", str(result)) + + try: + rtt = self['xep_0199'].ping(self.pingjid, + timeout=10) + logging.info("Success! RTT: %s", rtt) + except IqError as e: + logging.info("Error pinging %s: %s", + self.pingjid, + e.iq['error']['condition']) + except IqTimeout: + logging.info("No response from %s", self.pingjid) + finally: self.disconnect() diff --git a/examples/proxy_echo_client.py b/examples/proxy_echo_client.py index 25bfc891..98935b9c 100755 --- a/examples/proxy_echo_client.py +++ b/examples/proxy_echo_client.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/pubsub_client.py b/examples/pubsub_client.py index 0a244f3b..9a65553b 100644..100755 --- a/examples/pubsub_client.py +++ b/examples/pubsub_client.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + import sys import logging import getpass @@ -12,15 +15,15 @@ from sleekxmpp.xmlstream import ET, tostring # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input class PubsubClient(sleekxmpp.ClientXMPP): - def __init__(self, jid, password, server, + def __init__(self, jid, password, server, node=None, action='list', data=''): super(PubsubClient, self).__init__(jid, password) @@ -28,7 +31,7 @@ class PubsubClient(sleekxmpp.ClientXMPP): self.register_plugin('xep_0059') self.register_plugin('xep_0060') - self.actions = ['nodes', 'create', 'delete', + self.actions = ['nodes', 'create', 'delete', 'publish', 'get', 'retract', 'purge', 'subscribe', 'unsubscribe'] diff --git a/examples/pubsub_events.py b/examples/pubsub_events.py index 6fe7159b..12c33a76 100644..100755 --- a/examples/pubsub_events.py +++ b/examples/pubsub_events.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + import sys import logging import getpass @@ -14,8 +17,8 @@ from sleekxmpp.xmlstream.handler import Callback # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input @@ -77,7 +80,7 @@ class PubsubEvents(sleekxmpp.ClientXMPP): """Handle receiving a node deletion event.""" print('Deleted node %s' % ( msg['pubsub_event']['delete']['node'])) - + def _config(self, msg): """Handle receiving a node configuration event.""" print('Configured node %s:' % ( diff --git a/examples/register_account.py b/examples/register_account.py index 20377b26..422e5602 100644..100755 --- a/examples/register_account.py +++ b/examples/register_account.py @@ -22,8 +22,8 @@ from sleekxmpp.exceptions import IqError, IqTimeout # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input @@ -51,7 +51,7 @@ class RegisterBot(sleekxmpp.ClientXMPP): # The register event provides an Iq result stanza with # a registration form from the server. This may include - # the basic registration fields, a data form, an + # the basic registration fields, a data form, an # out-of-band URL, or any combination. For more advanced # cases, you will need to examine the fields provided # and respond accordingly. SleekXMPP provides plugins @@ -104,7 +104,7 @@ class RegisterBot(sleekxmpp.ClientXMPP): resp.send(now=True) logging.info("Account created for %s!" % self.boundjid) except IqError as e: - logging.error("Could not register account: %s" % + logging.error("Could not register account: %s" % e.iq['error']['text']) self.disconnect() except IqTimeout: @@ -153,6 +153,10 @@ if __name__ == '__main__': xmpp.register_plugin('xep_0066') # Out-of-band Data xmpp.register_plugin('xep_0077') # In-band Registration + # Some servers don't advertise support for inband registration, even + # though they allow it. If this applies to your server, use: + xmpp['xep_0077'].force_registration = True + # If you are working with an OpenFire server, you may need # to adjust the SSL version used: # xmpp.ssl_version = ssl.PROTOCOL_SSLv3 diff --git a/examples/roster_browser.py b/examples/roster_browser.py index b366d00f..a16de24c 100644..100755 --- a/examples/roster_browser.py +++ b/examples/roster_browser.py @@ -24,8 +24,8 @@ from sleekxmpp.exceptions import IqError, IqTimeout # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input @@ -68,7 +68,7 @@ class RosterBrowser(sleekxmpp.ClientXMPP): try: self.get_roster() except IqError as err: - print('Error: %' % err.iq['error']['condition']) + print('Error: %s' % err.iq['error']['condition']) except IqTimeout: print('Error: Request timed out') self.send_presence() diff --git a/examples/rpc_async.py b/examples/rpc_async.py index 0b6d1936..e3e23b69 100644..100755 --- a/examples/rpc_async.py +++ b/examples/rpc_async.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + """ SleekXMPP: The Sleek XMPP Library Copyright (C) 2011 Dann Martens @@ -11,34 +14,34 @@ from sleekxmpp.plugins.xep_0009.remote import Endpoint, remote, Remote, \ import time class Boomerang(Endpoint): - + def FQN(self): return 'boomerang' - + @remote def throw(self): print "Duck!" - + def main(): session = Remote.new_session('kangaroo@xmpp.org/rpc', '*****') - session.new_handler(ANY_ALL, Boomerang) - + session.new_handler(ANY_ALL, Boomerang) + boomerang = session.new_proxy('kangaroo@xmpp.org/rpc', Boomerang) - + callback = Future() - + boomerang.async(callback).throw() - + time.sleep(10) - + session.close() - - - + + + if __name__ == '__main__': main() -
\ No newline at end of file + diff --git a/examples/rpc_client_side.py b/examples/rpc_client_side.py index 135d6237..e792fc94 100644..100755 --- a/examples/rpc_client_side.py +++ b/examples/rpc_client_side.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + """ SleekXMPP: The Sleek XMPP Library Copyright (C) 2011 Dann Martens @@ -12,18 +15,18 @@ import threading import time class Thermostat(Endpoint): - + def FQN(self): return 'thermostat' - + def __init__(self, initial_temperature): self._temperature = initial_temperature - self._event = threading.Event() - + self._event = threading.Event() + @remote def set_temperature(self, temperature): return NotImplemented - + @remote def get_temperature(self): return NotImplemented @@ -31,23 +34,23 @@ class Thermostat(Endpoint): @remote(False) def release(self): return NotImplemented - + def main(): session = Remote.new_session('operator@xmpp.org/rpc', '*****') - + thermostat = session.new_proxy('thermostat@xmpp.org/rpc', Thermostat) - + print("Current temperature is %s" % thermostat.get_temperature()) - + thermostat.set_temperature(20) - + time.sleep(10) - + session.close() - + if __name__ == '__main__': main() - + diff --git a/examples/rpc_server_side.py b/examples/rpc_server_side.py index d1a11c17..9e8b48d6 100644..100755 --- a/examples/rpc_server_side.py +++ b/examples/rpc_server_side.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + """ SleekXMPP: The Sleek XMPP Library Copyright (C) 2011 Dann Martens @@ -11,42 +14,42 @@ from sleekxmpp.plugins.xep_0009.remote import Endpoint, remote, Remote, \ import threading class Thermostat(Endpoint): - + def FQN(self): return 'thermostat' - + def __init__(self, initial_temperature): self._temperature = initial_temperature - self._event = threading.Event() - + self._event = threading.Event() + @remote def set_temperature(self, temperature): print("Setting temperature to %s" % temperature) self._temperature = temperature - + @remote def get_temperature(self): return self._temperature @remote(False) def release(self): - self._event.set() - + self._event.set() + def wait_for_release(self): - self._event.wait() - + self._event.wait() + def main(): session = Remote.new_session('sleek@xmpp.org/rpc', '*****') - + thermostat = session.new_handler(ANY_ALL, Thermostat, 18) - + thermostat.wait_for_release() - + session.close() - + if __name__ == '__main__': main() - + diff --git a/examples/send_client.py b/examples/send_client.py index 5b34bbc9..192469ae 100755 --- a/examples/send_client.py +++ b/examples/send_client.py @@ -21,8 +21,8 @@ import sleekxmpp # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/set_avatar.py b/examples/set_avatar.py new file mode 100755 index 00000000..08e0b664 --- /dev/null +++ b/examples/set_avatar.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" + SleekXMPP: The Sleek XMPP Library + Copyright (C) 2012 Nathanael C. Fritz + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +import os +import sys +import imghdr +import logging +import getpass +import threading +from optparse import OptionParser + +import sleekxmpp +from sleekxmpp.exceptions import XMPPError + + +# Python versions before 3.0 do not use UTF-8 encoding +# by default. To ensure that Unicode is handled properly +# throughout SleekXMPP, we will set the default encoding +# ourselves to UTF-8. +if sys.version_info < (3, 0): + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') +else: + raw_input = input + + +class AvatarSetter(sleekxmpp.ClientXMPP): + + """ + A basic script for downloading the avatars for a user's contacts. + """ + + def __init__(self, jid, password, filepath): + sleekxmpp.ClientXMPP.__init__(self, jid, password) + + self.add_event_handler("session_start", self.start, threaded=True) + + self.filepath = filepath + + def start(self, event): + """ + Process the session_start event. + + Typical actions for the session_start event are + requesting the roster and broadcasting an initial + presence stanza. + + Arguments: + event -- An empty dictionary. The session_start + event does not provide any additional + data. + """ + self.send_presence() + self.get_roster() + + avatar_file = None + try: + avatar_file = open(os.path.expanduser(self.filepath), 'rb') + except IOError: + print('Could not find file: %s' % self.filepath) + return self.disconnect() + + avatar = avatar_file.read() + + avatar_type = 'image/%s' % imghdr.what('', avatar) + avatar_id = self['xep_0084'].generate_id(avatar) + avatar_bytes = len(avatar) + + avatar_file.close() + + used_xep84 = False + try: + print('Publish XEP-0084 avatar data') + self['xep_0084'].publish_avatar(avatar) + used_xep84 = True + except XMPPError: + print('Could not publish XEP-0084 avatar') + + try: + print('Update vCard with avatar') + self['xep_0153'].set_avatar(avatar=avatar, mtype=avatar_type) + except XMPPError: + print('Could not set vCard avatar') + + if used_xep84: + try: + print('Advertise XEP-0084 avatar metadata') + self['xep_0084'].publish_avatar_metadata([ + {'id': avatar_id, + 'type': avatar_type, + 'bytes': avatar_bytes} + # We could advertise multiple avatars to provide + # options in image type, source (HTTP vs pubsub), + # size, etc. + # {'id': ....} + ]) + except XMPPError: + print('Could not publish XEP-0084 metadata') + + print('Wait for presence updates to propagate...') + self.schedule('end', 5, self.disconnect, kwargs={'wait': True}) + + +if __name__ == '__main__': + # Setup the command line arguments. + optp = OptionParser() + optp.add_option('-q','--quiet', help='set logging to ERROR', + action='store_const', + dest='loglevel', + const=logging.ERROR, + default=logging.ERROR) + optp.add_option('-d','--debug', help='set logging to DEBUG', + action='store_const', + dest='loglevel', + const=logging.DEBUG, + default=logging.ERROR) + optp.add_option('-v','--verbose', help='set logging to COMM', + action='store_const', + dest='loglevel', + const=5, + default=logging.ERROR) + + # JID and password options. + optp.add_option("-j", "--jid", dest="jid", + help="JID to use") + optp.add_option("-p", "--password", dest="password", + help="password to use") + optp.add_option("-f", "--file", dest="filepath", + help="path to the avatar file") + opts,args = optp.parse_args() + + # Setup logging. + logging.basicConfig(level=opts.loglevel, + format='%(levelname)-8s %(message)s') + + if opts.jid is None: + opts.jid = raw_input("Username: ") + if opts.password is None: + opts.password = getpass.getpass("Password: ") + if opts.filepath is None: + opts.filepath = raw_input("Avatar file location: ") + + xmpp = AvatarSetter(opts.jid, opts.password, opts.filepath) + xmpp.register_plugin('xep_0054') + xmpp.register_plugin('xep_0153') + xmpp.register_plugin('xep_0084') + + # If you are working with an OpenFire server, you may need + # to adjust the SSL version used: + # xmpp.ssl_version = ssl.PROTOCOL_SSLv3 + + # If you want to verify the SSL certificates offered by a server: + # xmpp.ca_certs = "path/to/ca/cert" + + # Connect to the XMPP server and start processing XMPP stanzas. + if xmpp.connect(): + # If you do not have the dnspython library installed, you will need + # to manually specify the name of the server if it does not match + # the one in the JID. For example, to use Google Talk you would + # need to use: + # + # if xmpp.connect(('talk.google.com', 5222)): + # ... + xmpp.process(block=True) + else: + print("Unable to connect.") diff --git a/examples/thirdparty_auth.py b/examples/thirdparty_auth.py index 727311ae..f4d5c400 100644..100755 --- a/examples/thirdparty_auth.py +++ b/examples/thirdparty_auth.py @@ -29,8 +29,8 @@ from sleekxmpp.xmlstream import JID # throughout SleekXMPP, we will set the default encoding # ourselves to UTF-8. if sys.version_info < (3, 0): - reload(sys) - sys.setdefaultencoding('utf8') + from sleekxmpp.util.misc_ops import setdefaultencoding + setdefaultencoding('utf8') else: raw_input = input diff --git a/examples/user_location.py b/examples/user_location.py index 2a64cada..2a64cada 100644..100755 --- a/examples/user_location.py +++ b/examples/user_location.py diff --git a/examples/user_tune.py b/examples/user_tune.py index 09e050f0..09e050f0 100644..100755 --- a/examples/user_tune.py +++ b/examples/user_tune.py |