-
Notifications
You must be signed in to change notification settings - Fork 0
/
xmppbot.py
178 lines (140 loc) · 5.57 KB
/
xmppbot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
"""
Module is an example of simple chat bot for any xmpp-server
"""
import twisted.words.protocols.jabber.client as twisted_client
from twisted.internet import threads, defer, reactor
from twisted.words.protocols.jabber.xmlstream import XmlStreamFactory
from twisted.words.protocols.jabber import xmlstream
from twisted.names.srvconnect import SRVConnector
from pydispatch import dispatcher
from twilix.stanzas import Message, Iq, Presence
from twilix.base.exceptions import WrongElement
from twilix.jid import internJID
from twilix.dispatcher import Dispatcher
from twilix.version import ClientVersion
from twilix.disco import Disco
from twilix.roster import Roster
from twilix.vcard import MyVCardQuery, VCard
import plugins
import ConfigParser
from optparse import OptionParser
class XMPPClientConnector(SRVConnector):
"""Pre-connect initialization for client connector"""
def __init__(self, reactor, domain, factory, port):
self.port = port
SRVConnector.__init__(self, reactor, 'xmpp-client',
domain, factory)
class Client(object):
"""main class for client to server connection"""
def __init__(self, reactor, client_jid, server, secret, port):
"""Setup handler and connect to server"""
self.reactor = reactor
self.client_jid = client_jid
a = twisted_client.XMPPAuthenticator(client_jid, secret)
self.f = XmlStreamFactory(a)
#set handlers for xmlstream's events
self.f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT,
self.onConnected)
self.f.addBootstrap(xmlstream.STREAM_END_EVENT,
self.onDisconnected)
self.f.addBootstrap(xmlstream.STREAM_AUTHD_EVENT,
self.onAuthenticated)
self.f.addBootstrap(xmlstream.INIT_FAILED_EVENT,
self.onInitFailed)
self.connector = XMPPClientConnector(reactor, server,
self.f, port)
self.connector.connect()
self.xmlstream = None
#handlers for xmlstream's events
def onConnected(self, xs):
"""
xmlstream.STREAM_CONNECTED_EVENT handler.
Calls when client connected to server
"""
self.xmlstream = xs
self.xmlstream.rawDataInFn = self.rawIn
self.xmlstream.rawDataOutFn = self.rawOut
def rawIn(self,data):
"""data is the input stanza"""
pass
def rawOut(self,data):
"""data is the output stanza"""
pass
def onDisconnected(self, xs):
"""
xmlstream.STREAM_END_EVENT handler.
Calls when client disconnected from server
"""
pass
def onAuthenticated(self, xs):
"""
xmlstream.STREAM_AUTHD_EVENT handler.
Calls when client authenticated on server.
Setup dispatcher and any features for client
"""
self.dispatcher = Dispatcher(xs, self.client_jid)
plugins.register(self.dispatcher, self)
self.disco = Disco(self.dispatcher)
self.disco.init()
p = Presence(status="Use me plz!")
self.roster = Roster(self.dispatcher, p)
self.roster.init()
self.version = ClientVersion(self.dispatcher,
"XmppBot",
'v%s' % version, 'Linux')
self.version.init(self.disco)
#set handlers for roster's signals
dispatcher.connect(self.onSubscribe,
self.roster.subscribe)
dispatcher.connect(self.onRosterGot,
self.roster.roster_got)
dispatcher.connect(self.onAvailable,
self.roster.resource_available)
dispatcher.connect(self.onUnvailable,
self.roster.resource_unavailable)
def onInitFailed(self, xs):
"""
xmlstream.STREAM_INIT_FAILED_EVENT handler.
Calls when client authenticated on server was failed.
"""
pass
#handlers for roster's signals
def onAvailable(self, sender, item, presence):
"""roster.resourse_available handler."""
pass
def onUnvailable(self, sender, item, presence):
"""roster.resourse_unavailable handler."""
pass
def onRosterGot(self, sender):
"""roster.roster_got handler."""
pass
def onSubscribe(self, sender, presence):
"""roster.subscribe handler."""
presence.type_ = 'subscribed'
presence.to = presence.from_
presence.from_ = None
self.dispatcher.send(presence)
presence.type_ = 'subscribe'
self.dispatcher.send(presence)
version = '0.1'
configDefault = 'xmppbot.conf'
#read command-line's params
optparser = OptionParser(version="Xmpp bot version : %s" % version)
optparser.add_option('-c',
'--config',
metavar='FILE',
dest='configFile',
help="Read config from custom file")
(options, args) = optparser.parse_args()
configFile = options.configFile
#load configuration settings
config = ConfigParser.ConfigParser()
config.read(configFile if configFile else configDefault)
jid = config.get('connect', 'jid')
host = config.get('connect', 'host')
password = config.get('connect', 'password')
port = config.get('connect', 'port')
#connection to server
cl = Client(reactor, internJID(jid),
host, password, port)
reactor.run()