]>
code.delx.au - pymsnt/blob - src/jabw.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 tlib
.xmlw
import Element
, jid
6 from debug
import LogEvent
, INFO
, WARN
, ERROR
10 def sendMessage(pytrans
, to
, fro
, body
, mtype
=None, delay
=None):
11 """ Sends a Jabber message """
13 el
= Element((None, "message"))
14 el
.attributes
["to"] = to
15 el
.attributes
["from"] = fro
16 el
.attributes
["id"] = pytrans
.makeMessageID()
18 el
.attributes
["type"] = mtype
21 x
= el
.addElement("x")
22 x
.attributes
["xmlns"] = disco
.XDELAY
23 x
.attributes
["from"] = fro
24 x
.attributes
["stamp"] = delay
26 b
= el
.addElement("body")
28 x
= el
.addElement("x")
29 x
.attributes
["xmlns"] = disco
.XEVENT
30 composing
= x
.addElement("composing")
33 def sendPresence(pytrans
, to
, fro
, show
=None, status
=None, priority
=None, ptype
=None, avatarHash
=None, nickname
=None, payload
=[]):
34 # Strip the resource off any presence subscribes (as per XMPP RFC 3921 Section 5.1.6)
35 # Makes eJabberd behave :)
36 if ptype
== "subscribe":
37 to
= jid
.intern(to
).userhost()
39 el
= Element((None, "presence"))
40 el
.attributes
["to"] = to
41 el
.attributes
["from"] = fro
43 el
.attributes
["type"] = ptype
45 s
= el
.addElement("show")
48 s
= el
.addElement("status")
51 s
= el
.addElement("priority")
52 s
.addContent(priority
)
55 x
= el
.addElement("x")
56 x
.attributes
["xmlns"] = disco
.XVCARDUPDATE
58 xx
= el
.addElement("x")
59 xx
.attributes
["xmlns"] = disco
.XAVATAR
60 h
= xx
.addElement("hash")
61 h
.addContent(avatarHash
)
62 h
= x
.addElement("photo")
63 h
.addContent(avatarHash
)
65 n
= x
.addElement("nickname")
66 n
.addContent(nickname
)
75 def sendErrorMessage(pytrans
, to
, fro
, etype
, condition
, explanation
, body
=None):
76 el
= Element((None, "message"))
77 el
.attributes
["to"] = to
78 el
.attributes
["from"] = fro
79 el
.attributes
["type"] = "error"
80 error
= el
.addElement("error")
81 error
.attributes
["type"] = etype
82 error
.attributes
["code"] = str(utils
.errorCodeMap
[condition
])
83 desc
= error
.addElement(condition
)
84 desc
.attributes
["xmlns"] = "urn:ietf:params:xml:ns:xmpp-stanzas"
85 text
= error
.addElement("text")
86 text
.attributes
["xmlns"] = "urn:ietf:params:xml:ns:xmpp-stanzas"
87 text
.addContent(explanation
)
88 if(body
and len(body
) > 0):
89 b
= el
.addElement("body")
96 class JabberConnection
:
97 """ A class to handle a Jabber "Connection", ie, the Jabber side of the gateway.
98 If you want to send a Jabber event, this is the place, and this is where incoming
99 Jabber events for a session come to. """
101 def __init__(self
, pytrans
, jabberID
):
102 self
.pytrans
= pytrans
103 self
.jabberID
= jabberID
105 self
.typingUser
= False # Whether this user can accept typing notifications
106 self
.messageIDs
= dict() # The ID of the last message the user sent to a particular contact. Indexed by contact JID
108 LogEvent(INFO
, self
.jabberID
)
111 """ Cleanly deletes the object """
112 LogEvent(INFO
, self
.jabberID
)
114 def sendMessage(self
, to
, fro
, body
, mtype
=None, delay
=None):
115 """ Sends a Jabber message
116 For this message to have a <x xmlns="jabber:x:delay"/> you must pass a correctly formatted timestamp (See JEP0091)
118 LogEvent(INFO
, self
.jabberID
)
119 sendMessage(self
.pytrans
, to
, fro
, body
, mtype
, delay
)
121 def sendTypingNotification(self
, to
, fro
, typing
):
122 """ Sends the user the contact's current typing notification status """
124 LogEvent(INFO
, self
.jabberID
)
125 el
= Element((None, "message"))
126 el
.attributes
["to"] = to
127 el
.attributes
["from"] = fro
128 x
= el
.addElement("x")
129 x
.attributes
["xmlns"] = disco
.XEVENT
131 composing
= x
.addElement("composing")
132 id = x
.addElement("id")
133 if(self
.messageIDs
.has_key(fro
) and self
.messageIDs
[fro
]):
134 id.addContent(self
.messageIDs
[fro
])
135 self
.pytrans
.send(el
)
137 def sendVCardRequest(self
, to
, fro
):
138 """ Requests the the vCard of 'to'
139 Returns a Deferred which fires when the vCard has been received.
140 First argument an Element object of the vCard
142 el
= Element((None, "iq"))
143 el
.attributes
["to"] = to
144 el
.attributes
["from"] = fro
145 el
.attributes
["type"] = "get"
146 el
.attributes
["id"] = self
.pytrans
.makeMessageID()
147 vCard
= el
.addElement("vCard")
148 vCard
.attributes
["xmlns"] = "vcard-temp"
149 return self
.pytrans
.discovery
.sendIq(el
)
151 def sendErrorMessage(self
, to
, fro
, etype
, condition
, explanation
, body
=None):
152 LogEvent(INFO
, self
.jabberID
)
153 sendErrorMessage(self
.pytrans
, to
, fro
, etype
, condition
, explanation
, body
)
155 def sendPresence(self
, to
, fro
, show
=None, status
=None, priority
=None, ptype
=None, avatarHash
=None, nickname
=None, payload
=[]):
156 """ Sends a Jabber presence packet """
157 LogEvent(INFO
, self
.jabberID
)
158 sendPresence(self
.pytrans
, to
, fro
, show
, status
, priority
, ptype
, avatarHash
, nickname
, payload
)
160 def sendRosterImport(self
, jid
, ptype
, sub
, name
="", groups
=[]):
161 """ Sends a special presence packet. This will work with all clients, but clients that support roster-import will give a better user experience
162 IMPORTANT - Only ever use this for contacts that have already been authorised on the legacy service """
163 el
= Element((None, "presence"))
164 el
.attributes
["to"] = self
.jabberID
165 el
.attributes
["from"] = jid
166 el
.attributes
["type"] = ptype
167 r
= el
.addElement("x")
168 r
.attributes
["xmlns"] = disco
.SUBSYNC
169 item
= r
.addElement("item")
170 item
.attributes
["subscription"] = sub
172 item
.attributes
["name"] = unicode(name
)
174 g
= item
.addElement("group")
177 self
.pytrans
.send(el
)
179 def onMessage(self
, el
):
180 """ Handles incoming message packets """
181 #LogEvent(INFO, self.jabberID)
182 fro
= el
.getAttribute("from")
183 to
= el
.getAttribute("to")
185 froj
= jid
.intern(fro
)
188 LogEvent(WARN
, self
.jabberID
)
191 mID
= el
.getAttribute("id")
192 mtype
= el
.getAttribute("type")
199 for child
in el
.elements():
200 if(child
.name
== "body"):
201 body
= child
.__str
__()
202 elif(child
.name
== "noerror" and child
.uri
== "sapo:noerror"):
204 elif(child
.name
== "x"):
205 if(child
.uri
== disco
.XCONFERENCE
):
207 inviteRoom
= child
.getAttribute("jid") # The room the contact is being invited to
208 elif(child
.uri
== disco
.MUC_USER
):
209 for child2
in child
.elements():
210 if(child2
.name
== "invite"):
211 inviteTo
= child2
.getAttribute("to")
214 elif(child
.uri
== disco
.XEVENT
):
217 for child2
in child
.elements():
218 if(child2
.name
== "composing"):
222 if(inviteTo
and inviteRoom
):
223 LogEvent(INFO
, self
.jabberID
, "Message groupchat invite packet")
224 self
.inviteReceived(source
=froj
.userhost(), resource
=froj
.resource
, dest
=inviteTo
, destr
="", roomjid
=inviteRoom
)
227 # Check message event stuff
228 if(body
and messageEvent
):
229 self
.typingUser
= True
230 elif(body
and not messageEvent
):
231 self
.typingUser
= False
232 elif(not body
and messageEvent
):
233 LogEvent(INFO
, self
.jabberID
, "Message typing notification packet")
234 self
.typingNotificationReceived(toj
.userhost(), toj
.resource
, composing
)
238 # Save the message ID for later
239 self
.messageIDs
[to
] = mID
240 LogEvent(INFO
, self
.jabberID
, "Message packet")
241 self
.messageReceived(froj
.userhost(), froj
.resource
, toj
.userhost(), toj
.resource
, mtype
, body
, noerror
)
243 def onPresence(self
, el
):
244 """ Handles incoming presence packets """
245 #LogEvent(INFO, self.jabberID)
246 fro
= el
.getAttribute("from")
247 froj
= jid
.intern(fro
)
248 to
= el
.getAttribute("to")
251 # Grab the contents of the <presence/> packet
252 ptype
= el
.getAttribute("type")
253 if ptype
and (ptype
.startswith("subscribe") or ptype
.startswith("unsubscribe")):
254 LogEvent(INFO
, self
.jabberID
, "Parsed subscription presence packet")
255 self
.subscriptionReceived(toj
.userhost(), ptype
)
262 for child
in el
.elements():
263 if(child
.name
== "status"):
264 status
= child
.__str
__()
265 elif(child
.name
== "show"):
266 show
= child
.__str
__()
267 elif(child
.name
== "priority"):
268 priority
= child
.__str
__()
269 elif(child
.defaultUri
== disco
.XVCARDUPDATE
):
271 for child2
in child
.elements():
272 if(child2
.name
== "photo"):
273 avatarHash
= child2
.__str__()
274 elif(child2
.name
== "nickname"):
275 nickname
= child2
.__str__()
280 self
.avatarHashReceived(froj
.userhost(), toj
.userhost(), avatarHash
)
282 self
.nicknameReceived(froj
.userhost(), toj
.userhost(), nickname
)
284 LogEvent(INFO
, self
.jabberID
, "Parsed presence packet")
285 self
.presenceReceived(froj
.userhost(), froj
.resource
, toj
.userhost(), toj
.resource
, priority
, ptype
, show
, status
)
289 def messageReceived(self
, source
, resource
, dest
, destr
, mtype
, body
, noerror
):
290 """ Override this method to be notified when a message is received """
293 def inviteReceived(self
, source
, resource
, dest
, destr
, roomjid
):
294 """ Override this method to be notified when an invitation is received """
297 def presenceReceived(self
, source
, resource
, to
, tor
, priority
, ptype
, show
, status
):
298 """ Override this method to be notified when presence is received """
301 def subscriptionReceived(self
, source
, subtype
):
302 """ Override this method to be notified when a subscription packet is received """
305 def nicknameReceived(self
, source
, dest
, nickname
):
306 """ Override this method to be notified when a nickname has been received """
309 def avatarHashReceieved(self
, source
, dest
, avatarHash
):
310 """ Override this method to be notified when an avatar hash is received """