]>
code.delx.au - pymsnt/blob - src/misciq.py
1 # Copyright 2004-2005 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
5 from twisted
.internet
import reactor
, task
6 from debug
import LogEvent
, INFO
, WARN
, ERROR
17 def __init__(self
, pytrans
):
18 self
.pytrans
= pytrans
19 self
.pytrans
.adHocCommands
.addCommand("connectusers", self
.incomingIq
, "command_ConnectUsers")
22 for jid
in self
.pytrans
.xdb
.files():
23 jabw
.sendPresence(self
.pytrans
, jid
, config
.jid
, ptype
="probe")
25 def incomingIq(self
, el
):
26 to
= el
.getAttribute("from")
27 ID
= el
.getAttribute("id")
28 ulang
= utils
.getLang(el
)
30 if config
.admins
.count(utils
.jid(to
).userhost()) == 0:
31 self
.pytrans
.discovery
.sendIqError(to
=to
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.COMMANDS
, etype
="cancel", condition
="not-authorized")
37 iq
= Element((None, "iq"))
38 iq
.attributes
["to"] = to
39 iq
.attributes
["from"] = config
.jid
41 iq
.attributes
["id"] = ID
42 iq
.attributes
["type"] = "result"
44 command
= iq
.addElement("command")
45 command
.attributes
["sessionid"] = self
.pytrans
.makeMessageID()
46 command
.attributes
["xmlns"] = disco
.COMMANDS
47 command
.attributes
["status"] = "completed"
49 x
= command
.addElement("x")
50 x
.attributes
["xmlns"] = "jabber:x:data"
51 x
.attributes
["type"] = "result"
53 title
= x
.addElement("title")
54 title
.addContent(lang
.get(ulang
).command_ConnectUsers
)
56 field
= x
.addElement("field")
57 field
.attributes
["type"] = "fixed"
58 field
.addElement("value").addContent(lang
.get(ulang
).command_Done
)
64 def __init__(self
, pytrans
):
65 self
.pytrans
= pytrans
66 self
.pytrans
.adHocCommands
.addCommand("stats", self
.incomingIq
, "command_Statistics")
68 # self.stats is indexed by a unique ID, with value being the value for that statistic
70 self
.stats
["Uptime"] = 0
71 self
.stats
["OnlineUsers"] = 0
72 self
.stats
["TotalUsers"] = 0
74 legacy
.startStats(self
)
76 def incomingIq(self
, el
):
77 to
= el
.getAttribute("from")
78 ID
= el
.getAttribute("id")
79 ulang
= utils
.getLang(el
)
81 iq
= Element((None, "iq"))
82 iq
.attributes
["to"] = to
83 iq
.attributes
["from"] = config
.jid
85 iq
.attributes
["id"] = ID
86 iq
.attributes
["type"] = "result"
88 command
= iq
.addElement("command")
89 command
.attributes
["sessionid"] = self
.pytrans
.makeMessageID()
90 command
.attributes
["xmlns"] = disco
.COMMANDS
91 command
.attributes
["status"] = "completed"
93 x
= command
.addElement("x")
94 x
.attributes
["xmlns"] = "jabber:x:data"
95 x
.attributes
["type"] = "result"
97 title
= x
.addElement("title")
98 title
.addContent(lang
.get(ulang
).command_Statistics
)
100 for key
in self
.stats
:
101 label
= getattr(lang
.get(ulang
), "command_%s" % key
)
102 description
= getattr(lang
.get(ulang
), "command_%s_Desc" % key
)
103 field
= x
.addElement("field")
104 field
.attributes
["var"] = key
105 field
.attributes
["label"] = label
106 field
.attributes
["type"] = "text-single"
107 field
.addElement("value").addContent(str(self
.stats
[key
]))
108 field
.addElement("desc").addContent(description
)
110 self
.pytrans
.send(iq
)
115 def __init__(self
, pytrans
):
116 self
.pytrans
= pytrans
117 self
.pytrans
.discovery
.addFeature(disco
.COMMANDS
, self
.incomingIq
, config
.jid
)
118 self
.pytrans
.discovery
.addNode(disco
.COMMANDS
, self
.sendCommandList
, "command_CommandList", config
.jid
, True)
120 self
.commands
= {} # Dict of handlers indexed by node
121 self
.commandNames
= {} # Dict of names indexed by node
123 def addCommand(self
, command
, handler
, name
):
124 self
.commands
[command
] = handler
125 self
.commandNames
[command
] = name
126 self
.pytrans
.discovery
.addNode(command
, self
.incomingIq
, name
, config
.jid
, False)
128 def incomingIq(self
, el
):
129 itype
= el
.getAttribute("type")
130 fro
= el
.getAttribute("from")
131 froj
= utils
.jid(fro
)
132 to
= el
.getAttribute("to")
133 ID
= el
.getAttribute("id")
135 LogEvent(INFO
, "", "Looking for handler")
138 for child
in el
.elements():
139 xmlns
= child
.defaultUri
140 node
= child
.getAttribute("node")
143 if(child
.name
== "query" and xmlns
== disco
.DISCO_INFO
):
144 if(node
and self
.commands
.has_key(node
) and (itype
== "get")):
145 self
.sendCommandInfoResponse(to
=fro
, ID
=ID
)
147 elif(child
.name
== "query" and xmlns
== disco
.DISCO_ITEMS
):
148 if(node
and self
.commands
.has_key(node
) and (itype
== "get")):
149 self
.sendCommandItemsResponse(to
=fro
, ID
=ID
)
151 elif(child
.name
== "command" and xmlns
== disco
.COMMANDS
):
152 if((node
and self
.commands
.has_key(node
)) and (itype
== "set" or itype
== "error")):
153 self
.commands
[node
](el
)
156 LogEvent(WARN
, "", "Unknown Ad-Hoc command received.")
157 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=xmlns
, etype
="cancel", condition
="feature-not-implemented")
160 def sendCommandList(self
, el
):
161 to
= el
.getAttribute("from")
162 ID
= el
.getAttribute("id")
163 ulang
= utils
.getLang(el
)
165 iq
= Element((None, "iq"))
166 iq
.attributes
["to"] = to
167 iq
.attributes
["from"] = config
.jid
169 iq
.attributes
["id"] = ID
170 iq
.attributes
["type"] = "result"
172 query
= iq
.addElement("query")
173 query
.attributes
["xmlns"] = disco
.DISCO_ITEMS
174 query
.attributes
["node"] = disco
.COMMANDS
176 for command
in self
.commands
:
177 item
= query
.addElement("item")
178 item
.attributes
["jid"] = config
.jid
179 item
.attributes
["node"] = command
180 item
.attributes
["name"] = getattr(lang
.get(ulang
), self
.commandNames
[command
])
182 self
.pytrans
.send(iq
)
184 def sendCommandInfoResponse(self
, to
, ID
):
185 LogEvent(INFO
, "", "Replying to disco#info")
186 iq
= Element((None, "iq"))
187 iq
.attributes
["type"] = "result"
188 iq
.attributes
["from"] = config
.jid
189 iq
.attributes
["to"] = to
190 if(ID
): iq
.attributes
["id"] = ID
191 query
= iq
.addElement("query")
192 query
.attributes
["xmlns"] = disco
.DISCO_INFO
194 feature
= query
.addElement("feature")
195 feature
.attributes
["var"] = disco
.COMMANDS
196 self
.pytrans
.send(iq
)
198 def sendCommandItemsResponse(self
, to
, ID
):
199 LogEvent(INFO
, "", "Replying to disco#items")
200 iq
= Element((None, "iq"))
201 iq
.attributes
["type"] = "result"
202 iq
.attributes
["from"] = config
.jid
203 iq
.attributes
["to"] = to
204 if(ID
): iq
.attributes
["id"] = ID
205 query
= iq
.addElement("query")
206 query
.attributes
["xmlns"] = disco
.DISCO_ITEMS
207 self
.pytrans
.send(iq
)
211 def __init__(self
, pytrans
):
212 self
.pytrans
= pytrans
213 self
.pytrans
.discovery
.addFeature("vcard-temp", self
.incomingIq
, "USER")
214 self
.pytrans
.discovery
.addFeature("vcard-temp", self
.incomingIq
, config
.jid
)
216 def incomingIq(self
, el
):
217 itype
= el
.getAttribute("type")
218 fro
= el
.getAttribute("from")
219 froj
= utils
.jid(fro
)
220 to
= el
.getAttribute("to")
221 ID
= el
.getAttribute("id")
222 if(itype
!= "get" and itype
!= "error"):
223 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
="vcard-temp", etype
="cancel", condition
="feature-not-implemented")
226 LogEvent(INFO
, "", "Sending vCard")
228 toGateway
= not (to
.find('@') > 0)
231 if(not self
.pytrans
.sessions
.has_key(froj
.userhost())):
232 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
="vcard-temp", etype
="auth", condition
="not-authorized")
234 s
= self
.pytrans
.sessions
[froj
.userhost()]
236 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
="vcard-temp", etype
="auth", condition
="not-authorized")
239 c
= s
.contactList
.findContact(to
)
241 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
="vcard-temp", etype
="cancel", condition
="recipient-unavailable")
245 iq
= Element((None, "iq"))
246 iq
.attributes
["to"] = fro
247 iq
.attributes
["from"] = to
249 iq
.attributes
["id"] = ID
250 iq
.attributes
["type"] = "result"
251 vCard
= iq
.addElement("vCard")
252 vCard
.attributes
["xmlns"] = "vcard-temp"
254 FN
= vCard
.addElement("FN")
255 FN
.addContent(legacy
.name
)
256 DESC
= vCard
.addElement("DESC")
257 DESC
.addContent(legacy
.name
)
258 URL
= vCard
.addElement("URL")
259 URL
.addContent(legacy
.url
)
262 NICKNAME
= vCard
.addElement("NICKNAME")
263 NICKNAME
.addContent(c
.nickname
)
265 PHOTO
= c
.avatar
.makePhotoElement()
266 vCard
.addChild(PHOTO
)
268 self
.pytrans
.send(iq
)
270 class IqAvatarFactory
:
271 def __init__(self
, pytrans
):
272 self
.pytrans
= pytrans
273 self
.pytrans
.discovery
.addFeature(disco
.IQAVATAR
, self
.incomingIq
, "USER")
274 self
.pytrans
.discovery
.addFeature(disco
.STORAGEAVATAR
, self
.incomingIq
, "USER")
276 def incomingIq(self
, el
):
277 itype
= el
.getAttribute("type")
278 fro
= el
.getAttribute("from")
279 froj
= utils
.jid(fro
)
280 to
= el
.getAttribute("to")
281 ID
= el
.getAttribute("id")
283 if(itype
!= "get" and itype
!= "error"):
284 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQAVATAR
, etype
="cancel", condition
="feature-not-implemented")
287 LogEvent(INFO
, "", "Retrieving avatar")
289 if(not self
.pytrans
.sessions
.has_key(froj
.userhost())):
290 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQAVATAR
, etype
="auth", condition
="not-authorized")
292 s
= self
.pytrans
.sessions
[froj
.userhost()]
294 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQAVATAR
, etype
="auth", condition
="not-authorized")
297 c
= s
.contactList
.findContact(to
)
299 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQAVATAR
, etype
="cancel", condition
="recipient-unavailable")
302 iq
= Element((None, "iq"))
303 iq
.attributes
["to"] = fro
304 iq
.attributes
["from"] = to
306 iq
.attributes
["id"] = ID
307 iq
.attributes
["type"] = "result"
308 query
= iq
.addElement("query")
309 query
.attributes
["xmlns"] = disco
.IQAVATAR
311 DATA
= c
.avatar
.makeDataElement()
314 self
.pytrans
.send(iq
)
319 def __init__(self
, pytrans
):
320 self
.pytrans
= pytrans
321 # self.pingCounter = 0
322 # self.pingTask = task.LoopingCall(self.pingCheck)
323 self
.pingTask
= task
.LoopingCall(self
.whitespace
)
324 # reactor.callLater(10.0, self.start)
327 # self.pingTask.start(120.0)
329 def whitespace(self
):
330 self
.pytrans
.send(" ")
332 # def pingCheck(self):
333 # if(self.pingCounter >= 2 and self.pytrans.xmlstream): # Two minutes of no response from the main server
334 # LogEvent(WARN, "", "Disconnecting because the main server has ignored our pings for too long.")
335 # self.pytrans.xmlstream.transport.loseConnection()
336 # elif(config.mainServerJID):
337 # d = self.pytrans.discovery.sendIq(self.makePingPacket())
338 # d.addCallback(self.pongReceived)
339 # d.addErrback(self.pongFailed)
340 # self.pingCounter += 1
342 # def pongReceived(self, el):
343 # self.pingCounter = 0
345 # def pongFailed(self, el):
348 # def makePingPacket(self):
349 # iq = Element((None, "iq"))
350 # iq.attributes["from"] = config.jid
351 # iq.attributes["to"] = config.mainServerJID
352 # iq.attributes["type"] = "get"
353 # query = iq.addElement("query")
354 # query.attributes["xmlns"] = disco.IQVERSION
357 class GatewayTranslator
:
358 def __init__(self
, pytrans
):
359 self
.pytrans
= pytrans
360 self
.pytrans
.discovery
.addFeature(disco
.IQGATEWAY
, self
.incomingIq
, config
.jid
)
362 def incomingIq(self
, el
):
363 fro
= el
.getAttribute("from")
364 ID
= el
.getAttribute("id")
365 itype
= el
.getAttribute("type")
367 self
.sendPrompt(fro
, ID
, utils
.getLang(el
))
368 elif(itype
== "set"):
369 self
.sendTranslation(fro
, ID
, el
)
372 def sendPrompt(self
, to
, ID
, ulang
):
375 iq
= Element((None, "iq"))
377 iq
.attributes
["type"] = "result"
378 iq
.attributes
["from"] = config
.jid
379 iq
.attributes
["to"] = to
381 iq
.attributes
["id"] = ID
382 query
= iq
.addElement("query")
383 query
.attributes
["xmlns"] = disco
.IQGATEWAY
384 desc
= query
.addElement("desc")
385 desc
.addContent(lang
.get(ulang
).gatewayTranslator
)
386 prompt
= query
.addElement("prompt")
388 self
.pytrans
.send(iq
)
390 def sendTranslation(self
, to
, ID
, el
):
393 # Find the user's legacy account
395 for query
in el
.elements():
396 if(query
.name
== "query"):
397 for child
in query
.elements():
398 if(child
.name
== "prompt"):
399 legacyaccount
= str(child
)
404 if(legacyaccount
and len(legacyaccount
) > 0):
405 LogEvent(INFO
, "", "Sending translated account.")
406 iq
= Element((None, "iq"))
407 iq
.attributes
["type"] = "result"
408 iq
.attributes
["from"] = config
.jid
409 iq
.attributes
["to"] = to
411 iq
.attributes
["id"] = ID
412 query
= iq
.addElement("query")
413 query
.attributes
["xmlns"] = disco
.IQGATEWAY
414 prompt
= query
.addElement("prompt")
415 prompt
.addContent(legacy
.translateAccount(legacyaccount
))
417 self
.pytrans
.send(iq
)
420 self
.pytrans
.discovery
.sendIqError(to
, ID
, disco
.IQGATEWAY
)
421 self
.pytrans
.discovery
.sendIqError(to
=to
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQGATEWAY
, etype
="retry", condition
="bad-request")
426 def __init__(self
, pytrans
):
427 self
.pytrans
= pytrans
428 self
.pytrans
.discovery
.addFeature(disco
.IQVERSION
, self
.incomingIq
, config
.jid
)
429 self
.pytrans
.discovery
.addFeature(disco
.IQVERSION
, self
.incomingIq
, "USER")
431 def incomingIq(self
, el
):
432 eltype
= el
.getAttribute("type")
433 if(eltype
!= "get"): return # Only answer "get" stanzas
437 def sendVersion(self
, el
):
439 iq
= Element((None, "iq"))
440 iq
.attributes
["type"] = "result"
441 iq
.attributes
["from"] = el
.getAttribute("to")
442 iq
.attributes
["to"] = el
.getAttribute("from")
443 if(el
.getAttribute("id")):
444 iq
.attributes
["id"] = el
.getAttribute("id")
445 query
= iq
.addElement("query")
446 query
.attributes
["xmlns"] = disco
.IQVERSION
447 name
= query
.addElement("name")
448 name
.addContent(legacy
.name
)
449 version
= query
.addElement("version")
450 version
.addContent(legacy
.version
)
451 os
= query
.addElement("os")
452 os
.addContent("Python" + ".".join([str(x
) for x
in sys
.version_info
[0:3]]) + " - " + sys
.platform
)
454 self
.pytrans
.send(iq
)