]>
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
in ("subscribe", "subscribed", "unsubscribe", "unsubscribed"):
37 to
= jid
.intern(to
).userhost()
38 fro
= jid
.intern(fro
).userhost()
40 el
= Element((None, "presence"))
41 el
.attributes
["to"] = to
42 el
.attributes
["from"] = fro
44 el
.attributes
["type"] = ptype
46 s
= el
.addElement("show")
49 s
= el
.addElement("status")
52 s
= el
.addElement("priority")
53 s
.addContent(priority
)
56 x
= el
.addElement("x")
57 x
.attributes
["xmlns"] = disco
.XVCARDUPDATE
59 xx
= el
.addElement("x")
60 xx
.attributes
["xmlns"] = disco
.XAVATAR
61 h
= xx
.addElement("hash")
62 h
.addContent(avatarHash
)
63 h
= x
.addElement("photo")
64 h
.addContent(avatarHash
)
66 n
= x
.addElement("nickname")
67 n
.addContent(nickname
)
76 def sendErrorMessage(pytrans
, to
, fro
, etype
, condition
, explanation
, body
=None):
77 el
= Element((None, "message"))
78 el
.attributes
["to"] = to
79 el
.attributes
["from"] = fro
80 el
.attributes
["type"] = "error"
81 error
= el
.addElement("error")
82 error
.attributes
["type"] = etype
83 error
.attributes
["code"] = str(utils
.errorCodeMap
[condition
])
84 desc
= error
.addElement(condition
)
85 desc
.attributes
["xmlns"] = XMPP_STANZAS
86 text
= error
.addElement("text")
87 text
.attributes
["xmlns"] = XMPP_STANZAS
88 text
.addContent(explanation
)
89 if(body
and len(body
) > 0):
90 b
= el
.addElement("body")
97 class JabberConnection
:
98 """ A class to handle a Jabber "Connection", ie, the Jabber side of the gateway.
99 If you want to send a Jabber event, this is the place, and this is where incoming
100 Jabber events for a session come to. """
102 def __init__(self
, pytrans
, jabberID
):
103 self
.pytrans
= pytrans
104 self
.jabberID
= jabberID
106 self
.typingUser
= False # Whether this user can accept typing notifications
107 self
.messageIDs
= dict() # The ID of the last message the user sent to a particular contact. Indexed by contact JID
109 LogEvent(INFO
, self
.jabberID
)
112 """ Cleanly deletes the object """
113 LogEvent(INFO
, self
.jabberID
)
115 def sendMessage(self
, to
, fro
, body
, mtype
=None, delay
=None):
116 """ Sends a Jabber message
117 For this message to have a <x xmlns="jabber:x:delay"/> you must pass a correctly formatted timestamp (See JEP0091)
119 LogEvent(INFO
, self
.jabberID
)
120 sendMessage(self
.pytrans
, to
, fro
, body
, mtype
, delay
)
122 def sendTypingNotification(self
, to
, fro
, typing
):
123 """ Sends the user the contact's current typing notification status """
125 LogEvent(INFO
, self
.jabberID
)
126 el
= Element((None, "message"))
127 el
.attributes
["to"] = to
128 el
.attributes
["from"] = fro
129 x
= el
.addElement("x")
130 x
.attributes
["xmlns"] = disco
.XEVENT
132 composing
= x
.addElement("composing")
133 id = x
.addElement("id")
134 if(self
.messageIDs
.has_key(fro
) and self
.messageIDs
[fro
]):
135 id.addContent(self
.messageIDs
[fro
])
136 self
.pytrans
.send(el
)
138 def sendVCardRequest(self
, to
, fro
):
139 """ Requests the the vCard of 'to'
140 Returns a Deferred which fires when the vCard has been received.
141 First argument an Element object of the vCard
143 el
= Element((None, "iq"))
144 el
.attributes
["to"] = to
145 el
.attributes
["from"] = fro
146 el
.attributes
["type"] = "get"
147 el
.attributes
["id"] = self
.pytrans
.makeMessageID()
148 vCard
= el
.addElement("vCard")
149 vCard
.attributes
["xmlns"] = "vcard-temp"
150 return self
.pytrans
.discovery
.sendIq(el
)
152 def sendErrorMessage(self
, to
, fro
, etype
, condition
, explanation
, body
=None):
153 LogEvent(INFO
, self
.jabberID
)
154 sendErrorMessage(self
.pytrans
, to
, fro
, etype
, condition
, explanation
, body
)
156 def sendPresence(self
, to
, fro
, show
=None, status
=None, priority
=None, ptype
=None, avatarHash
=None, nickname
=None, payload
=[]):
157 """ Sends a Jabber presence packet """
158 LogEvent(INFO
, self
.jabberID
)
159 sendPresence(self
.pytrans
, to
, fro
, show
, status
, priority
, ptype
, avatarHash
, nickname
, payload
)
161 def sendRosterImport(self
, jid
, ptype
, sub
, name
="", groups
=[]):
162 """ Sends a special presence packet. This will work with all clients, but clients that support roster-import will give a better user experience
163 IMPORTANT - Only ever use this for contacts that have already been authorised on the legacy service """
164 el
= Element((None, "presence"))
165 el
.attributes
["to"] = self
.jabberID
166 el
.attributes
["from"] = jid
167 el
.attributes
["type"] = ptype
168 r
= el
.addElement("x")
169 r
.attributes
["xmlns"] = disco
.SUBSYNC
170 item
= r
.addElement("item")
171 item
.attributes
["subscription"] = sub
173 item
.attributes
["name"] = unicode(name
)
175 g
= item
.addElement("group")
178 self
.pytrans
.send(el
)
180 def onMessage(self
, el
):
181 """ Handles incoming message packets """
182 #LogEvent(INFO, self.jabberID)
183 fro
= el
.getAttribute("from")
184 to
= el
.getAttribute("to")
186 froj
= jid
.intern(fro
)
189 LogEvent(WARN
, self
.jabberID
)
192 mID
= el
.getAttribute("id")
193 mtype
= el
.getAttribute("type")
200 for child
in el
.elements():
201 if(child
.name
== "body"):
202 body
= child
.__str
__()
203 elif(child
.name
== "noerror" and child
.uri
== "sapo:noerror"):
205 elif(child
.name
== "x"):
206 if(child
.uri
== disco
.XCONFERENCE
):
208 inviteRoom
= child
.getAttribute("jid") # The room the contact is being invited to
209 elif(child
.uri
== disco
.MUC_USER
):
210 for child2
in child
.elements():
211 if(child2
.name
== "invite"):
212 inviteTo
= child2
.getAttribute("to")
215 elif(child
.uri
== disco
.XEVENT
):
218 for child2
in child
.elements():
219 if(child2
.name
== "composing"):
223 if(inviteTo
and inviteRoom
):
224 LogEvent(INFO
, self
.jabberID
, "Message groupchat invite packet")
225 self
.inviteReceived(source
=froj
.userhost(), resource
=froj
.resource
, dest
=inviteTo
, destr
="", roomjid
=inviteRoom
)
228 # Check message event stuff
229 if(body
and messageEvent
):
230 self
.typingUser
= True
231 elif(body
and not messageEvent
):
232 self
.typingUser
= False
233 elif(not body
and messageEvent
):
234 LogEvent(INFO
, self
.jabberID
, "Message typing notification packet")
235 self
.typingNotificationReceived(toj
.userhost(), toj
.resource
, composing
)
239 # Save the message ID for later
240 self
.messageIDs
[to
] = mID
241 LogEvent(INFO
, self
.jabberID
, "Message packet")
242 self
.messageReceived(froj
.userhost(), froj
.resource
, toj
.userhost(), toj
.resource
, mtype
, body
, noerror
)
244 def onPresence(self
, el
):
245 """ Handles incoming presence packets """
246 #LogEvent(INFO, self.jabberID)
247 fro
= el
.getAttribute("from")
248 froj
= jid
.intern(fro
)
249 to
= el
.getAttribute("to")
252 # Grab the contents of the <presence/> packet
253 ptype
= el
.getAttribute("type")
254 if ptype
and (ptype
.startswith("subscribe") or ptype
.startswith("unsubscribe")):
255 LogEvent(INFO
, self
.jabberID
, "Parsed subscription presence packet")
256 self
.subscriptionReceived(toj
.userhost(), ptype
)
263 for child
in el
.elements():
264 if(child
.name
== "status"):
265 status
= child
.__str
__()
266 elif(child
.name
== "show"):
267 show
= child
.__str
__()
268 elif(child
.name
== "priority"):
269 priority
= child
.__str
__()
270 elif(child
.defaultUri
== disco
.XVCARDUPDATE
):
272 for child2
in child
.elements():
273 if(child2
.name
== "photo"):
274 avatarHash
= child2
.__str__()
275 elif(child2
.name
== "nickname"):
276 nickname
= child2
.__str__()
281 self
.avatarHashReceived(froj
.userhost(), toj
.userhost(), avatarHash
)
283 self
.nicknameReceived(froj
.userhost(), toj
.userhost(), nickname
)
285 LogEvent(INFO
, self
.jabberID
, "Parsed presence packet")
286 self
.presenceReceived(froj
.userhost(), froj
.resource
, toj
.userhost(), toj
.resource
, priority
, ptype
, show
, status
)
290 def messageReceived(self
, source
, resource
, dest
, destr
, mtype
, body
, noerror
):
291 """ Override this method to be notified when a message is received """
294 def inviteReceived(self
, source
, resource
, dest
, destr
, roomjid
):
295 """ Override this method to be notified when an invitation is received """
298 def presenceReceived(self
, source
, resource
, to
, tor
, priority
, ptype
, show
, status
):
299 """ Override this method to be notified when presence is received """
302 def subscriptionReceived(self
, source
, subtype
):
303 """ Override this method to be notified when a subscription packet is received """
306 def nicknameReceived(self
, source
, dest
, nickname
):
307 """ Override this method to be notified when a nickname has been received """
310 def avatarHashReceieved(self
, source
, dest
, avatarHash
):
311 """ Override this method to be notified when an avatar hash is received """