Add an example for dumping the roster to the command line.
[slixmpp.git] / examples / disco_browser.py
blobb2b96f9514566cdfe764913dd3c5ada7feff4600
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 """
5 SleekXMPP: The Sleek XMPP Library
6 Copyright (C) 2010 Nathanael C. Fritz
7 This file is part of SleekXMPP.
9 See the file LICENSE for copying permission.
10 """
12 import sys
13 import time
14 import logging
15 import getpass
16 from optparse import OptionParser
18 import sleekxmpp
21 # Python versions before 3.0 do not use UTF-8 encoding
22 # by default. To ensure that Unicode is handled properly
23 # throughout SleekXMPP, we will set the default encoding
24 # ourselves to UTF-8.
25 if sys.version_info < (3, 0):
26 reload(sys)
27 sys.setdefaultencoding('utf8')
30 class Disco(sleekxmpp.ClientXMPP):
32 """
33 A demonstration for using basic service discovery.
35 Send a disco#info and disco#items request to a JID/node combination,
36 and print out the results.
38 May also request only particular info categories such as just features,
39 or just items.
40 """
42 def __init__(self, jid, password, target_jid, target_node='', get=''):
43 sleekxmpp.ClientXMPP.__init__(self, jid, password)
45 # Using service discovery requires the XEP-0030 plugin.
46 self.register_plugin('xep_0030')
48 self.get = get
49 self.target_jid = target_jid
50 self.target_node = target_node
52 # Values to control which disco entities are reported
53 self.info_types = ['', 'all', 'info', 'identities', 'features']
54 self.identity_types = ['', 'all', 'info', 'identities']
55 self.feature_types = ['', 'all', 'info', 'features']
56 self.items_types = ['', 'all', 'items']
59 # The session_start event will be triggered when
60 # the bot establishes its connection with the server
61 # and the XML streams are ready for use. We want to
62 # listen for this event so that we we can intialize
63 # our roster.
64 self.add_event_handler("session_start", self.start)
66 def start(self, event):
67 """
68 Process the session_start event.
70 Typical actions for the session_start event are
71 requesting the roster and broadcasting an intial
72 presence stanza.
74 In this case, we send disco#info and disco#items
75 stanzas to the requested JID and print the results.
77 Arguments:
78 event -- An empty dictionary. The session_start
79 event does not provide any additional
80 data.
81 """
82 self.get_roster()
83 self.send_presence()
85 if self.get in self.info_types:
86 # By using block=True, the result stanza will be
87 # returned. Execution will block until the reply is
88 # received. Non-blocking options would be to listen
89 # for the disco_info event, or passing a handler
90 # function using the callback parameter.
91 info = self['xep_0030'].get_info(jid=self.target_jid,
92 node=self.target_node,
93 block=True)
94 if self.get in self.items_types:
95 # The same applies from above. Listen for the
96 # disco_items event or pass a callback function
97 # if you need to process a non-blocking request.
98 items = self['xep_0030'].get_items(jid=self.target_jid,
99 node=self.target_node,
100 block=True)
101 else:
102 logging.error("Invalid disco request type.")
103 self.disconnect()
104 return
106 header = 'XMPP Service Discovery: %s' % self.target_jid
107 print(header)
108 print('-' * len(header))
109 if self.target_node != '':
110 print('Node: %s' % self.target_node)
111 print('-' * len(header))
113 if self.get in self.identity_types:
114 print('Identities:')
115 for identity in info['disco_info']['identities']:
116 print(' - %s' % str(identity))
118 if self.get in self.feature_types:
119 print('Features:')
120 for feature in info['disco_info']['features']:
121 print(' - %s' % feature)
123 if self.get in self.items_types:
124 print('Items:')
125 for item in items['disco_items']['items']:
126 print(' - %s' % str(item))
128 self.disconnect()
131 if __name__ == '__main__':
132 # Setup the command line arguments.
133 optp = OptionParser()
134 optp.version = '%%prog 0.1'
135 optp.usage = "Usage: %%prog [options] %s <jid> [<node>]" % \
136 'all|info|items|identities|features'
138 optp.add_option('-q','--quiet', help='set logging to ERROR',
139 action='store_const',
140 dest='loglevel',
141 const=logging.ERROR,
142 default=logging.ERROR)
143 optp.add_option('-d','--debug', help='set logging to DEBUG',
144 action='store_const',
145 dest='loglevel',
146 const=logging.DEBUG,
147 default=logging.ERROR)
148 optp.add_option('-v','--verbose', help='set logging to COMM',
149 action='store_const',
150 dest='loglevel',
151 const=5,
152 default=logging.ERROR)
154 # JID and password options.
155 optp.add_option("-j", "--jid", dest="jid",
156 help="JID to use")
157 optp.add_option("-p", "--password", dest="password",
158 help="password to use")
159 opts,args = optp.parse_args()
161 # Setup logging.
162 logging.basicConfig(level=opts.loglevel,
163 format='%(levelname)-8s %(message)s')
165 if len(args) < 2:
166 optp.print_help()
167 exit()
169 if len(args) == 2:
170 args = (args[0], args[1], '')
172 if opts.jid is None:
173 opts.jid = raw_input("Username: ")
174 if opts.password is None:
175 opts.password = getpass.getpass("Password: ")
177 # Setup the Disco browser.
178 xmpp = Disco(opts.jid, opts.password, args[1], args[2], args[0])
180 # If you are working with an OpenFire server, you may need
181 # to adjust the SSL version used:
182 # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
184 # If you want to verify the SSL certificates offered by a server:
185 # xmpp.ca_certs = "path/to/ca/cert"
187 # Connect to the XMPP server and start processing XMPP stanzas.
188 if xmpp.connect():
189 # If you do not have the pydns library installed, you will need
190 # to manually specify the name of the server if it does not match
191 # the one in the JID. For example, to use Google Talk you would
192 # need to use:
194 # if xmpp.connect(('talk.google.com', 5222)):
195 # ...
196 xmpp.process(threaded=False)
197 else:
198 print("Unable to connect.")