2 # -*- coding: utf-8 -*-
5 Slixmpp: The Slick XMPP Library
6 Copyright (C) 2010 Nathanael C. Fritz
7 This file is part of Slixmpp.
9 See the file LICENSE for copying permission.
15 from optparse
import OptionParser
18 from slixmpp
.exceptions
import IqError
, IqTimeout
21 # Python versions before 3.0 do not use UTF-8 encoding
22 # by default. To ensure that Unicode is handled properly
23 # throughout Slixmpp, we will set the default encoding
25 if sys
.version_info
< (3, 0):
26 from slixmpp
.util
.misc_ops
import setdefaultencoding
27 setdefaultencoding('utf8')
32 class Disco(slixmpp
.ClientXMPP
):
35 A demonstration for using basic service discovery.
37 Send a disco#info and disco#items request to a JID/node combination,
38 and print out the results.
40 May also request only particular info categories such as just features,
44 def __init__(self
, jid
, password
, target_jid
, target_node
='', get
=''):
45 slixmpp
.ClientXMPP
.__init
__(self
, jid
, password
)
47 # Using service discovery requires the XEP-0030 plugin.
48 self
.register_plugin('xep_0030')
51 self
.target_jid
= target_jid
52 self
.target_node
= target_node
54 # Values to control which disco entities are reported
55 self
.info_types
= ['', 'all', 'info', 'identities', 'features']
56 self
.identity_types
= ['', 'all', 'info', 'identities']
57 self
.feature_types
= ['', 'all', 'info', 'features']
58 self
.items_types
= ['', 'all', 'items']
61 # The session_start event will be triggered when
62 # the bot establishes its connection with the server
63 # and the XML streams are ready for use. We want to
64 # listen for this event so that we we can initialize
66 self
.add_event_handler("session_start", self
.start
, threaded
=True)
68 def start(self
, event
):
70 Process the session_start event.
72 Typical actions for the session_start event are
73 requesting the roster and broadcasting an initial
76 In this case, we send disco#info and disco#items
77 stanzas to the requested JID and print the results.
80 event -- An empty dictionary. The session_start
81 event does not provide any additional
88 if self
.get
in self
.info_types
:
89 # By using block=True, the result stanza will be
90 # returned. Execution will block until the reply is
91 # received. Non-blocking options would be to listen
92 # for the disco_info event, or passing a handler
93 # function using the callback parameter.
94 info
= self
['xep_0030'].get_info(jid
=self
.target_jid
,
95 node
=self
.target_node
,
97 elif self
.get
in self
.items_types
:
98 # The same applies from above. Listen for the
99 # disco_items event or pass a callback function
100 # if you need to process a non-blocking request.
101 items
= self
['xep_0030'].get_items(jid
=self
.target_jid
,
102 node
=self
.target_node
,
105 logging
.error("Invalid disco request type.")
108 logging
.error("Entity returned an error: %s" % e
.iq
['error']['condition'])
110 logging
.error("No response received.")
112 header
= 'XMPP Service Discovery: %s' % self
.target_jid
114 print('-' * len(header
))
115 if self
.target_node
!= '':
116 print('Node: %s' % self
.target_node
)
117 print('-' * len(header
))
119 if self
.get
in self
.identity_types
:
121 for identity
in info
['disco_info']['identities']:
122 print(' - %s' % str(identity
))
124 if self
.get
in self
.feature_types
:
126 for feature
in info
['disco_info']['features']:
127 print(' - %s' % feature
)
129 if self
.get
in self
.items_types
:
131 for item
in items
['disco_items']['items']:
132 print(' - %s' % str(item
))
137 if __name__
== '__main__':
138 # Setup the command line arguments.
139 optp
= OptionParser()
140 optp
.version
= '%%prog 0.1'
141 optp
.usage
= "Usage: %%prog [options] %s <jid> [<node>]" % \
142 'all|info|items|identities|features'
144 optp
.add_option('-q','--quiet', help='set logging to ERROR',
145 action
='store_const',
148 default
=logging
.ERROR
)
149 optp
.add_option('-d','--debug', help='set logging to DEBUG',
150 action
='store_const',
153 default
=logging
.ERROR
)
154 optp
.add_option('-v','--verbose', help='set logging to COMM',
155 action
='store_const',
158 default
=logging
.ERROR
)
160 # JID and password options.
161 optp
.add_option("-j", "--jid", dest
="jid",
163 optp
.add_option("-p", "--password", dest
="password",
164 help="password to use")
165 opts
,args
= optp
.parse_args()
168 logging
.basicConfig(level
=opts
.loglevel
,
169 format
='%(levelname)-8s %(message)s')
176 args
= (args
[0], args
[1], '')
179 opts
.jid
= raw_input("Username: ")
180 if opts
.password
is None:
181 opts
.password
= getpass
.getpass("Password: ")
183 # Setup the Disco browser.
184 xmpp
= Disco(opts
.jid
, opts
.password
, args
[1], args
[2], args
[0])
186 # If you are working with an OpenFire server, you may need
187 # to adjust the SSL version used:
188 # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
190 # If you want to verify the SSL certificates offered by a server:
191 # xmpp.ca_certs = "path/to/ca/cert"
193 # Connect to the XMPP server and start processing XMPP stanzas.
195 # If you do not have the dnspython library installed, you will need
196 # to manually specify the name of the server if it does not match
197 # the one in the JID. For example, to use Google Talk you would
200 # if xmpp.connect(('talk.google.com', 5222)):
202 xmpp
.process(block
=True)
204 print("Unable to connect.")