]>
code.delx.au - pymsnt/blob - src/jabw.py
fa7f4f44cda807a45b795cdc2fece7fc027733ff
1 # Copyright 2004 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
5 if(utils
.checkTwisted()):
6 from twisted
.xish
.domish
import Element
7 from twisted
.words
.protocols
.jabber
import jid
9 from tlib
.domish
import Element
10 from tlib
.jabber
import jid
14 def sendMessage(pytrans
, to
, fro
, body
, mtype
=None, delay
=None):
15 """ Sends a Jabber message """
16 debug
.log("jabw: Sending a Jabber message \"%s\" \"%s\" \"%s\" \"%s\"" % (to
, fro
, utils
.latin1(body
), mtype
))
17 el
= Element((None, "message"))
18 el
.attributes
["to"] = to
19 el
.attributes
["from"] = fro
20 el
.attributes
["id"] = pytrans
.makeMessageID()
22 el
.attributes
["type"] = mtype
25 x
= el
.addElement("x")
26 x
.attributes
["xmlns"] = "jabber:x:delay"
27 x
.attributes
["from"] = fro
28 x
.attributes
["stamp"] = delay
30 b
= el
.addElement("body")
32 x
= el
.addElement("x")
33 x
.attributes
["xmlns"] = "jabber:x:event"
34 composing
= x
.addElement("composing")
37 def sendPresence(pytrans
, to
, fro
, show
=None, status
=None, priority
=None, ptype
=None):
38 # Strip the resource off any presence subscribes (as per XMPP RFC 3921 Section 5.1.6)
39 # Makes eJabberd behave :)
40 if(ptype
== "subscribe"):
41 (user
,host
,res
) = jid
.parse(to
)
42 to
= "%s@%s" % (user
, host
)
44 el
= Element((None, "presence"))
45 el
.attributes
["to"] = to
46 el
.attributes
["from"] = fro
48 el
.attributes
["type"] = ptype
50 s
= el
.addElement("show")
53 s
= el
.addElement("status")
56 s
= el
.addElement("priority")
57 s
.addContent(priority
)
61 def sendErrorMessage(pytrans
, to
, fro
, etype
, condition
, explanation
, body
=None):
62 el
= Element((None, "message"))
63 el
.attributes
["to"] = to
64 el
.attributes
["from"] = fro
65 el
.attributes
["type"] = "error"
66 error
= el
.addElement("error")
67 error
.attributes
["type"] = etype
68 error
.attributes
["code"] = str(utils
.errorCodeMap
[condition
])
69 desc
= error
.addElement(condition
)
70 desc
.attributes
["xmlns"] = "urn:ietf:params:xml:ns:xmpp-stanzas"
71 text
= error
.addElement("text")
72 text
.attributes
["xmlns"] = "urn:ietf:params:xml:ns:xmpp-stanzas"
73 text
.addContent(explanation
)
74 if(body
and len(body
) > 0):
75 b
= el
.addElement("body")
82 class JabberConnection
:
83 """ A class to handle a Jabber "Connection", ie, the Jabber side of the gateway.
84 If you want to send a Jabber event, this is the place, and this is where incoming
85 Jabber events for a session come to. """
87 def __init__(self
, pytrans
, jabberID
):
88 self
.pytrans
= pytrans
89 self
.jabberID
= jabberID
91 self
.typingUser
= False # Whether this user can accept typing notifications
92 self
.messageIDs
= dict() # The ID of the last message the user sent to a particular contact. Indexed by contact JID
94 debug
.log("User: %s - JabberConnection constructed" % (self
.jabberID
))
97 """ Cleanly deletes the object """
98 debug
.log("User: %s - JabberConnection removed" % (self
.jabberID
))
100 def checkFrom(self
, el
):
101 """ Checks to see that this packet was intended for this object """
102 fro
= el
.getAttribute("from")
105 return (froj
.userhost() == self
.jabberID
) # Compare with the Jabber ID that we're looking at
107 def sendMessage(self
, to
, fro
, body
, mtype
=None, delay
=None):
108 """ Sends a Jabber message
109 For this message to have a <x xmlns="jabber:x:delay"/> you must pass a correctly formatted timestamp (See JEP0091)
111 debug
.log("User: %s - JabberConnection sending message \"%s\" \"%s\" \"%s\" \"%s\"" % (self
.jabberID
, to
, fro
, utils
.latin1(body
), mtype
))
112 sendMessage(self
.pytrans
, to
, fro
, body
, mtype
, delay
)
114 def sendTypingNotification(self
, to
, fro
, typing
):
115 """ Sends the user the contact's current typing notification status """
117 debug
.log("jabw: Sending a Jabber typing notification message \"%s\" \"%s\" \"%s\"" % (to
, fro
, typing
))
118 el
= Element((None, "message"))
119 el
.attributes
["to"] = to
120 el
.attributes
["from"] = fro
121 x
= el
.addElement("x")
122 x
.attributes
["xmlns"] = "jabber:x:event"
124 composing
= x
.addElement("composing")
125 id = x
.addElement("id")
126 if(self
.messageIDs
.has_key(fro
) and self
.messageIDs
[fro
]):
127 id.addContent(self
.messageIDs
[fro
])
128 self
.pytrans
.send(el
)
130 def sendErrorMessage(self
, to
, fro
, etype
, condition
, explanation
, body
=None):
131 debug
.log("User: %s - JabberConnection sending error response." % (self
.jabberID
))
132 sendErrorMessage(self
.pytrans
, to
, fro
, etype
, condition
, explanation
, body
)
134 def sendPresence(self
, to
, fro
, show
=None, status
=None, priority
=None, ptype
=None):
135 """ Sends a Jabber presence packet """
136 debug
.log("User: %s - JabberConnection sending presence \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"" % (self
.jabberID
, to
, fro
, show
, utils
.latin1(status
), priority
, ptype
))
137 sendPresence(self
.pytrans
, to
, fro
, show
, status
, priority
, ptype
)
139 def sendRosterImport(self
, jid
, ptype
, sub
, name
="", groups
=[]):
140 """ Sends a special presence packet. This will work with all clients, but clients that support roster-import will give a better user experience
141 IMPORTANT - Only ever use this for contacts that have already been authorised on the legacy service """
142 el
= Element((None, "presence"))
143 el
.attributes
["to"] = self
.jabberID
144 el
.attributes
["from"] = jid
145 el
.attributes
["type"] = ptype
146 r
= el
.addElement("x")
147 r
.attributes
["xmlns"] = "http://jabber.org/protocol/roster-subsync"
148 item
= r
.addElement("item")
149 item
.attributes
["subscription"] = sub
151 item
.attributes
["name"] = unicode(name
)
153 g
= item
.addElement("group")
156 self
.pytrans
.send(el
)
158 def onMessage(self
, el
):
159 """ Handles incoming message packets """
160 if(not self
.checkFrom(el
)): return
161 debug
.log("User: %s - JabberConnection received message packet" % (self
.jabberID
))
162 fro
= el
.getAttribute("from")
164 to
= el
.getAttribute("to")
166 mID
= el
.getAttribute("id")
168 mtype
= el
.getAttribute("type")
174 for child
in el
.elements():
175 if(child
.name
== "body"):
176 body
= child
.__str
__()
177 if(child
.name
== "noerror" and child
.uri
== "sapo:noerror"):
179 if(child
.name
== "x"):
180 if(child
.uri
== "jabber:x:conference"):
181 invite
= child
.getAttribute("jid") # The room the contact is being invited to
182 if(child
.uri
== "jabber:x:event"):
185 for deepchild
in child
.elements():
186 if(deepchild
.name
== "composing"):
190 debug
.log("User: %s - JabberConnection parsed message groupchat invite packet \"%s\" \"%s\" \"%s\" \"%s\"" % (self
.jabberID
, froj
.userhost(), to
, froj
.resource
, utils
.latin1(invite
)))
191 self
.inviteReceived(froj
.userhost(), froj
.resource
, toj
.userhost(), toj
.resource
, invite
)
194 # Check message event stuff
195 if(body
and messageEvent
):
196 self
.typingUser
= True
197 elif(body
and not messageEvent
):
198 self
.typingUser
= False
199 elif(not body
and messageEvent
):
200 debug
.log("User: %s - JabberConnection parsed typing notification \"%s\" \"%s\"" % (self
.jabberID
, toj
.userhost(), composing
))
201 self
.typingNotificationReceived(toj
.userhost(), toj
.resource
, composing
)
205 # body = utils.utf8(body)
206 # Save the message ID for later
207 self
.messageIDs
[to
] = mID
208 debug
.log("User: %s - JabberConnection parsed message packet \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"" % (self
.jabberID
, froj
.userhost(), to
, froj
.resource
, mtype
, utils
.latin1(body
)))
209 self
.messageReceived(froj
.userhost(), froj
.resource
, toj
.userhost(), toj
.resource
, mtype
, body
, noerror
)
211 def onPresence(self
, el
):
212 """ Handles incoming presence packets """
213 if(not self
.checkFrom(el
)): return
214 debug
.log("User: %s - JabberConnection received presence packet" % (self
.jabberID
))
215 fro
= el
.getAttribute("from")
217 to
= el
.getAttribute("to")
220 # Grab the contents of the <presence/> packet
221 ptype
= el
.getAttribute("type")
222 if(ptype
in ["subscribe", "subscribed", "unsubscribe", "unsubscribed"]):
223 debug
.log("User: %s - JabberConnection parsed subscription presence packet \"%s\" \"%s\"" % (self
.jabberID
, toj
.userhost(), ptype
))
224 self
.subscriptionReceived(toj
.userhost(), ptype
)
229 for child
in el
.elements():
230 if(child
.name
== "status"):
231 status
= child
.__str
__()
232 elif(child
.name
== "show"):
233 show
= child
.__str
__()
234 elif(child
.name
== "priority"):
235 priority
= child
.__str
__()
237 debug
.log("User: %s - JabberConnection parsed presence packet \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"" % (self
.jabberID
, froj
.userhost(), froj
.resource
, priority
, ptype
, show
, utils
.latin1(status
)))
238 self
.presenceReceived(froj
.userhost(), froj
.resource
, toj
.userhost(), toj
.resource
, priority
, ptype
, show
, status
)
242 def messageReceived(self
, source
, resource
, dest
, destr
, mtype
, body
, noerror
):
243 """ Override this method to be notified when a message is received """
246 def inviteReceived(self
, source
, resource
, dest
, destr
, roomjid
):
247 """ Override this method to be notified when an invitation is received """
250 def presenceReceived(self
, source
, resource
, to
, tor
, priority
, ptype
, show
, status
):
251 """ Override this method to be notified when presence is received """
254 def subscriptionReceived(self
, source
, subtype
):
255 """ Override this method to be notified when a subscription packet is received """