]>
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 tlib
.xmlw
import Element
, jid
7 from debug
import LogEvent
, INFO
, WARN
, ERROR
18 def __init__(self
, pytrans
):
19 self
.pytrans
= pytrans
20 self
.pytrans
.adHocCommands
.addCommand("connectusers", self
.incomingIq
, "command_ConnectUsers")
23 for jid
in self
.pytrans
.xdb
.files():
24 jabw
.sendPresence(self
.pytrans
, jid
, config
.jid
, ptype
="probe")
26 def incomingIq(self
, el
):
27 to
= el
.getAttribute("from")
28 ID
= el
.getAttribute("id")
29 ulang
= utils
.getLang(el
)
31 if config
.admins
.count(jid
.intern(to
).userhost()) == 0:
32 self
.pytrans
.discovery
.sendIqError(to
=to
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.COMMANDS
, etype
="cancel", condition
="not-authorized")
38 iq
= Element((None, "iq"))
39 iq
.attributes
["to"] = to
40 iq
.attributes
["from"] = config
.jid
42 iq
.attributes
["id"] = ID
43 iq
.attributes
["type"] = "result"
45 command
= iq
.addElement("command")
46 command
.attributes
["sessionid"] = self
.pytrans
.makeMessageID()
47 command
.attributes
["xmlns"] = disco
.COMMANDS
48 command
.attributes
["status"] = "completed"
50 x
= command
.addElement("x")
51 x
.attributes
["xmlns"] = "jabber:x:data"
52 x
.attributes
["type"] = "result"
54 title
= x
.addElement("title")
55 title
.addContent(lang
.get(ulang
).command_ConnectUsers
)
57 field
= x
.addElement("field")
58 field
.attributes
["type"] = "fixed"
59 field
.addElement("value").addContent(lang
.get(ulang
).command_Done
)
65 def __init__(self
, pytrans
):
66 self
.pytrans
= pytrans
67 self
.pytrans
.adHocCommands
.addCommand("stats", self
.incomingIq
, "command_Statistics")
69 # self.stats is indexed by a unique ID, with value being the value for that statistic
71 self
.stats
["Uptime"] = 0
72 self
.stats
["OnlineUsers"] = 0
73 self
.stats
["TotalUsers"] = 0
75 legacy
.startStats(self
)
77 def incomingIq(self
, el
):
78 to
= el
.getAttribute("from")
79 ID
= el
.getAttribute("id")
80 ulang
= utils
.getLang(el
)
82 iq
= Element((None, "iq"))
83 iq
.attributes
["to"] = to
84 iq
.attributes
["from"] = config
.jid
86 iq
.attributes
["id"] = ID
87 iq
.attributes
["type"] = "result"
89 command
= iq
.addElement("command")
90 command
.attributes
["sessionid"] = self
.pytrans
.makeMessageID()
91 command
.attributes
["xmlns"] = disco
.COMMANDS
92 command
.attributes
["status"] = "completed"
94 x
= command
.addElement("x")
95 x
.attributes
["xmlns"] = "jabber:x:data"
96 x
.attributes
["type"] = "result"
98 title
= x
.addElement("title")
99 title
.addContent(lang
.get(ulang
).command_Statistics
)
101 for key
in self
.stats
:
102 label
= getattr(lang
.get(ulang
), "command_%s" % key
)
103 description
= getattr(lang
.get(ulang
), "command_%s_Desc" % key
)
104 field
= x
.addElement("field")
105 field
.attributes
["var"] = key
106 field
.attributes
["label"] = label
107 field
.attributes
["type"] = "text-single"
108 field
.addElement("value").addContent(str(self
.stats
[key
]))
109 field
.addElement("desc").addContent(description
)
111 self
.pytrans
.send(iq
)
116 def __init__(self
, pytrans
):
117 self
.pytrans
= pytrans
118 self
.pytrans
.discovery
.addFeature(disco
.COMMANDS
, self
.incomingIq
, config
.jid
)
119 self
.pytrans
.discovery
.addNode(disco
.COMMANDS
, self
.sendCommandList
, "command_CommandList", config
.jid
, True)
121 self
.commands
= {} # Dict of handlers indexed by node
122 self
.commandNames
= {} # Dict of names indexed by node
124 def addCommand(self
, command
, handler
, name
):
125 self
.commands
[command
] = handler
126 self
.commandNames
[command
] = name
127 self
.pytrans
.discovery
.addNode(command
, self
.incomingIq
, name
, config
.jid
, False)
129 def incomingIq(self
, el
):
130 itype
= el
.getAttribute("type")
131 fro
= el
.getAttribute("from")
132 froj
= jid
.intern(fro
)
133 to
= el
.getAttribute("to")
134 ID
= el
.getAttribute("id")
136 LogEvent(INFO
, "", "Looking for handler")
139 for child
in el
.elements():
140 xmlns
= child
.defaultUri
141 node
= child
.getAttribute("node")
144 if(child
.name
== "query" and xmlns
== disco
.DISCO_INFO
):
145 if(node
and self
.commands
.has_key(node
) and (itype
== "get")):
146 self
.sendCommandInfoResponse(to
=fro
, ID
=ID
)
148 elif(child
.name
== "query" and xmlns
== disco
.DISCO_ITEMS
):
149 if(node
and self
.commands
.has_key(node
) and (itype
== "get")):
150 self
.sendCommandItemsResponse(to
=fro
, ID
=ID
)
152 elif(child
.name
== "command" and xmlns
== disco
.COMMANDS
):
153 if((node
and self
.commands
.has_key(node
)) and (itype
== "set" or itype
== "error")):
154 self
.commands
[node
](el
)
157 LogEvent(WARN
, "", "Unknown Ad-Hoc command received.")
158 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=xmlns
, etype
="cancel", condition
="feature-not-implemented")
161 def sendCommandList(self
, el
):
162 to
= el
.getAttribute("from")
163 ID
= el
.getAttribute("id")
164 ulang
= utils
.getLang(el
)
166 iq
= Element((None, "iq"))
167 iq
.attributes
["to"] = to
168 iq
.attributes
["from"] = config
.jid
170 iq
.attributes
["id"] = ID
171 iq
.attributes
["type"] = "result"
173 query
= iq
.addElement("query")
174 query
.attributes
["xmlns"] = disco
.DISCO_ITEMS
175 query
.attributes
["node"] = disco
.COMMANDS
177 for command
in self
.commands
:
178 item
= query
.addElement("item")
179 item
.attributes
["jid"] = config
.jid
180 item
.attributes
["node"] = command
181 item
.attributes
["name"] = getattr(lang
.get(ulang
), self
.commandNames
[command
])
183 self
.pytrans
.send(iq
)
185 def sendCommandInfoResponse(self
, to
, ID
):
186 LogEvent(INFO
, "", "Replying to disco#info")
187 iq
= Element((None, "iq"))
188 iq
.attributes
["type"] = "result"
189 iq
.attributes
["from"] = config
.jid
190 iq
.attributes
["to"] = to
191 if(ID
): iq
.attributes
["id"] = ID
192 query
= iq
.addElement("query")
193 query
.attributes
["xmlns"] = disco
.DISCO_INFO
195 feature
= query
.addElement("feature")
196 feature
.attributes
["var"] = disco
.COMMANDS
197 self
.pytrans
.send(iq
)
199 def sendCommandItemsResponse(self
, to
, ID
):
200 LogEvent(INFO
, "", "Replying to disco#items")
201 iq
= Element((None, "iq"))
202 iq
.attributes
["type"] = "result"
203 iq
.attributes
["from"] = config
.jid
204 iq
.attributes
["to"] = to
205 if(ID
): iq
.attributes
["id"] = ID
206 query
= iq
.addElement("query")
207 query
.attributes
["xmlns"] = disco
.DISCO_ITEMS
208 self
.pytrans
.send(iq
)
212 def __init__(self
, pytrans
):
213 self
.pytrans
= pytrans
214 self
.pytrans
.discovery
.addFeature("vcard-temp", self
.incomingIq
, "USER")
215 self
.pytrans
.discovery
.addFeature("vcard-temp", self
.incomingIq
, config
.jid
)
217 def incomingIq(self
, el
):
218 itype
= el
.getAttribute("type")
219 fro
= el
.getAttribute("from")
220 froj
= jid
.intern(fro
)
221 to
= el
.getAttribute("to")
222 ID
= el
.getAttribute("id")
223 if(itype
!= "get" and itype
!= "error"):
224 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
="vcard-temp", etype
="cancel", condition
="feature-not-implemented")
227 LogEvent(INFO
, "", "Sending vCard")
229 toGateway
= not (to
.find('@') > 0)
232 if(not self
.pytrans
.sessions
.has_key(froj
.userhost())):
233 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
="vcard-temp", etype
="auth", condition
="not-authorized")
235 s
= self
.pytrans
.sessions
[froj
.userhost()]
237 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
="vcard-temp", etype
="auth", condition
="not-authorized")
240 c
= s
.contactList
.findContact(to
)
242 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
="vcard-temp", etype
="cancel", condition
="recipient-unavailable")
246 iq
= Element((None, "iq"))
247 iq
.attributes
["to"] = fro
248 iq
.attributes
["from"] = to
250 iq
.attributes
["id"] = ID
251 iq
.attributes
["type"] = "result"
252 vCard
= iq
.addElement("vCard")
253 vCard
.attributes
["xmlns"] = "vcard-temp"
255 FN
= vCard
.addElement("FN")
256 FN
.addContent(legacy
.name
)
257 DESC
= vCard
.addElement("DESC")
258 DESC
.addContent(legacy
.name
)
259 URL
= vCard
.addElement("URL")
260 URL
.addContent(legacy
.url
)
263 NICKNAME
= vCard
.addElement("NICKNAME")
264 NICKNAME
.addContent(c
.nickname
)
266 PHOTO
= c
.avatar
.makePhotoElement()
267 vCard
.addChild(PHOTO
)
269 self
.pytrans
.send(iq
)
271 class IqAvatarFactory
:
272 def __init__(self
, pytrans
):
273 self
.pytrans
= pytrans
274 self
.pytrans
.discovery
.addFeature(disco
.IQAVATAR
, self
.incomingIq
, "USER")
275 self
.pytrans
.discovery
.addFeature(disco
.STORAGEAVATAR
, self
.incomingIq
, "USER")
277 def incomingIq(self
, el
):
278 itype
= el
.getAttribute("type")
279 fro
= el
.getAttribute("from")
280 froj
= jid
.intern(fro
)
281 to
= el
.getAttribute("to")
282 ID
= el
.getAttribute("id")
284 if(itype
!= "get" and itype
!= "error"):
285 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQAVATAR
, etype
="cancel", condition
="feature-not-implemented")
288 LogEvent(INFO
, "", "Retrieving avatar")
290 if(not self
.pytrans
.sessions
.has_key(froj
.userhost())):
291 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQAVATAR
, etype
="auth", condition
="not-authorized")
293 s
= self
.pytrans
.sessions
[froj
.userhost()]
295 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQAVATAR
, etype
="auth", condition
="not-authorized")
298 c
= s
.contactList
.findContact(to
)
300 self
.pytrans
.discovery
.sendIqError(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQAVATAR
, etype
="cancel", condition
="recipient-unavailable")
303 iq
= Element((None, "iq"))
304 iq
.attributes
["to"] = fro
305 iq
.attributes
["from"] = to
307 iq
.attributes
["id"] = ID
308 iq
.attributes
["type"] = "result"
309 query
= iq
.addElement("query")
310 query
.attributes
["xmlns"] = disco
.IQAVATAR
312 DATA
= c
.avatar
.makeDataElement()
315 self
.pytrans
.send(iq
)
320 def __init__(self
, pytrans
):
321 self
.pytrans
= pytrans
322 # self.pingCounter = 0
323 # self.pingTask = task.LoopingCall(self.pingCheck)
324 self
.pingTask
= task
.LoopingCall(self
.whitespace
)
325 # reactor.callLater(10.0, self.start)
328 # self.pingTask.start(120.0)
330 def whitespace(self
):
331 self
.pytrans
.send(" ")
333 # def pingCheck(self):
334 # if(self.pingCounter >= 2 and self.pytrans.xmlstream): # Two minutes of no response from the main server
335 # LogEvent(WARN, "", "Disconnecting because the main server has ignored our pings for too long.")
336 # self.pytrans.xmlstream.transport.loseConnection()
337 # elif(config.mainServerJID):
338 # d = self.pytrans.discovery.sendIq(self.makePingPacket())
339 # d.addCallback(self.pongReceived)
340 # d.addErrback(self.pongFailed)
341 # self.pingCounter += 1
343 # def pongReceived(self, el):
344 # self.pingCounter = 0
346 # def pongFailed(self, el):
349 # def makePingPacket(self):
350 # iq = Element((None, "iq"))
351 # iq.attributes["from"] = config.jid
352 # iq.attributes["to"] = config.mainServerJID
353 # iq.attributes["type"] = "get"
354 # query = iq.addElement("query")
355 # query.attributes["xmlns"] = disco.IQVERSION
358 class GatewayTranslator
:
359 def __init__(self
, pytrans
):
360 self
.pytrans
= pytrans
361 self
.pytrans
.discovery
.addFeature(disco
.IQGATEWAY
, self
.incomingIq
, config
.jid
)
363 def incomingIq(self
, el
):
364 fro
= el
.getAttribute("from")
365 ID
= el
.getAttribute("id")
366 itype
= el
.getAttribute("type")
368 self
.sendPrompt(fro
, ID
, utils
.getLang(el
))
369 elif(itype
== "set"):
370 self
.sendTranslation(fro
, ID
, el
)
373 def sendPrompt(self
, to
, ID
, ulang
):
376 iq
= Element((None, "iq"))
378 iq
.attributes
["type"] = "result"
379 iq
.attributes
["from"] = config
.jid
380 iq
.attributes
["to"] = to
382 iq
.attributes
["id"] = ID
383 query
= iq
.addElement("query")
384 query
.attributes
["xmlns"] = disco
.IQGATEWAY
385 desc
= query
.addElement("desc")
386 desc
.addContent(lang
.get(ulang
).gatewayTranslator
)
387 prompt
= query
.addElement("prompt")
389 self
.pytrans
.send(iq
)
391 def sendTranslation(self
, to
, ID
, el
):
394 # Find the user's legacy account
396 for query
in el
.elements():
397 if(query
.name
== "query"):
398 for child
in query
.elements():
399 if(child
.name
== "prompt"):
400 legacyaccount
= str(child
)
405 if(legacyaccount
and len(legacyaccount
) > 0):
406 LogEvent(INFO
, "", "Sending translated account.")
407 iq
= Element((None, "iq"))
408 iq
.attributes
["type"] = "result"
409 iq
.attributes
["from"] = config
.jid
410 iq
.attributes
["to"] = to
412 iq
.attributes
["id"] = ID
413 query
= iq
.addElement("query")
414 query
.attributes
["xmlns"] = disco
.IQGATEWAY
415 prompt
= query
.addElement("prompt")
416 prompt
.addContent(legacy
.translateAccount(legacyaccount
))
418 self
.pytrans
.send(iq
)
421 self
.pytrans
.discovery
.sendIqError(to
, ID
, disco
.IQGATEWAY
)
422 self
.pytrans
.discovery
.sendIqError(to
=to
, fro
=config
.jid
, ID
=ID
, xmlns
=disco
.IQGATEWAY
, etype
="retry", condition
="bad-request")
427 def __init__(self
, pytrans
):
428 self
.pytrans
= pytrans
429 self
.pytrans
.discovery
.addFeature(disco
.IQVERSION
, self
.incomingIq
, config
.jid
)
430 self
.pytrans
.discovery
.addFeature(disco
.IQVERSION
, self
.incomingIq
, "USER")
432 def incomingIq(self
, el
):
433 eltype
= el
.getAttribute("type")
434 if(eltype
!= "get"): return # Only answer "get" stanzas
438 def sendVersion(self
, el
):
440 iq
= Element((None, "iq"))
441 iq
.attributes
["type"] = "result"
442 iq
.attributes
["from"] = el
.getAttribute("to")
443 iq
.attributes
["to"] = el
.getAttribute("from")
444 if(el
.getAttribute("id")):
445 iq
.attributes
["id"] = el
.getAttribute("id")
446 query
= iq
.addElement("query")
447 query
.attributes
["xmlns"] = disco
.IQVERSION
448 name
= query
.addElement("name")
449 name
.addContent(legacy
.name
)
450 version
= query
.addElement("version")
451 version
.addContent(legacy
.version
)
452 os
= query
.addElement("os")
453 os
.addContent("Python" + ".".join([str(x
) for x
in sys
.version_info
[0:3]]) + " - " + sys
.platform
)
455 self
.pytrans
.send(iq
)