2 # -*- coding: utf-8 -*-
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.
16 from optparse
import OptionParser
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
25 if sys
.version_info
< (3, 0):
27 sys
.setdefaultencoding('utf8')
30 class Disco(sleekxmpp
.ClientXMPP
):
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,
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')
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
64 self
.add_event_handler("session_start", self
.start
)
66 def start(self
, event
):
68 Process the session_start event.
70 Typical actions for the session_start event are
71 requesting the roster and broadcasting an intial
74 In this case, we send disco#info and disco#items
75 stanzas to the requested JID and print the results.
78 event -- An empty dictionary. The session_start
79 event does not provide any additional
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
,
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
,
102 logging
.error("Invalid disco request type.")
106 header
= 'XMPP Service Discovery: %s' % self
.target_jid
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
:
115 for identity
in info
['disco_info']['identities']:
116 print(' - %s' % str(identity
))
118 if self
.get
in self
.feature_types
:
120 for feature
in info
['disco_info']['features']:
121 print(' - %s' % feature
)
123 if self
.get
in self
.items_types
:
125 for item
in items
['disco_items']['items']:
126 print(' - %s' % str(item
))
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',
142 default
=logging
.ERROR
)
143 optp
.add_option('-d','--debug', help='set logging to DEBUG',
144 action
='store_const',
147 default
=logging
.ERROR
)
148 optp
.add_option('-v','--verbose', help='set logging to COMM',
149 action
='store_const',
152 default
=logging
.ERROR
)
154 # JID and password options.
155 optp
.add_option("-j", "--jid", dest
="jid",
157 optp
.add_option("-p", "--password", dest
="password",
158 help="password to use")
159 opts
,args
= optp
.parse_args()
162 logging
.basicConfig(level
=opts
.loglevel
,
163 format
='%(levelname)-8s %(message)s')
170 args
= (args
[0], args
[1], '')
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.
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
194 # if xmpp.connect(('talk.google.com', 5222)):
196 xmpp
.process(threaded
=False)
198 print("Unable to connect.")