9 bus
= dbus
.SessionBus()
12 obj
= bus
.get_object("im.pidgin.purple.PurpleService",
13 "/im/pidgin/purple/PurpleObject")
14 except dbus
.DBusException
, e
:
15 if e
._dbus
_error
_name
== "org.freedesktop.DBus.Error.ServiceUnknown":
16 print "Error: no libpurple-powered client is running. Try starting Pidgin or Finch."
18 purple
= dbus
.Interface(obj
, "im.pidgin.purple.PurpleInterface")
21 def __init__(self
, obj
):
24 def __getattr__(self
, attr
):
25 return CheckedAttribute(self
, attr
)
27 class CheckedAttribute
:
28 def __init__(self
, cobj
, attr
):
32 def __call__(self
, *args
):
33 # Redirect stderr to suppress the printing of an " Introspect error"
34 # message if nothing is listening on the bus. We print a friendly
35 # error message ourselves.
36 real_stderr
= sys
.stderr
38 result
= self
.cobj
.obj
.__getattr
__(self
.attr
)(*args
)
39 sys
.stderr
= real_stderr
41 # This can be useful for debugging.
43 # print "Error: " + self.attr + " " + str(args) + " returned " + str(result)
47 cpurple
= CheckedObject(purple
)
49 def extendlist(list, length
, fill
):
50 if len(list) < length
:
51 return list + [fill
] * (length
- len(list))
61 def account_not_found():
62 print "No matching account found."
65 def bring_account_online(account
):
66 if not cpurple
.PurpleAccountIsConnected(account
):
67 # The last argument is meant to be a GList * but the D-Bus binding
68 # generator thing just wants a UInt32, which is pretty failing.
69 # Happily, passing a 0 to mean an empty list turns out to work anyway.
70 purple
.PurpleAccountSetStatusList(account
, "online", 1, 0)
71 purple
.PurpleAccountConnect(account
)
73 def findaccount(protocolname
, accountname
="", matcher
=None):
75 for account
in cpurple
.PurpleAccountsGetAll():
76 if (protocolname
!= cpurple
.PurpleAccountGetProtocolID(account
)) or \
77 (accountname
!= "" and accountname
!= cpurple
.PurpleAccountGetUsername(account
)):
80 bring_account_online(account
)
84 # prefer connected accounts
85 account
= cpurple
.PurpleAccountsFindConnected(accountname
, protocolname
)
89 # try to get any account and connect it
90 account
= cpurple
.PurpleAccountsFindAny(accountname
, protocolname
)
94 bring_account_online(account
)
97 def goim(account
, screenname
, message
=None):
98 # XXX: 1 == PURPLE_CONV_TYPE_IM
99 conversation
= cpurple
.PurpleConversationNew(1, account
, screenname
)
101 purple
.PurpleConvSendConfirm(conversation
, message
)
103 def gochat(account
, params
, message
=None):
104 connection
= cpurple
.PurpleAccountGetConnection(account
)
105 purple
.ServJoinChat(connection
, params
)
109 # XXX: 2 == PURPLE_CONV_TYPE_CHAT
110 conversation
= purple
.PurpleFindConversationWithAccount(2, params
.get("channel", params
.get("room")), account
)
112 purple
.PurpleConvSendConfirm(conversation
, message
)
117 def addbuddy(account
, screenname
, group
="", alias
=""):
118 cpurple
.PurpleBlistRequestAddBuddy(account
, screenname
, group
, alias
)
122 protocol
= "prpl-aim"
123 match
= re
.match(r
"^aim:([^?]*)(\?(.*))", uri
)
125 print "Invalid aim URI: %s" % uri
128 command
= urllib
.unquote_plus(match
.group(1))
129 paramstring
= match
.group(3)
132 for param
in paramstring
.split("&"):
133 key
, value
= extendlist(param
.split("=", 1), 2, "")
134 params
[key
] = urllib
.unquote_plus(value
)
135 accountname
= params
.get("account", "")
136 screenname
= params
.get("screenname", "")
138 account
= findaccount(protocol
, accountname
)
140 if command
.lower() == "goim":
141 goim(account
, screenname
, params
.get("message"))
142 elif command
.lower() == "gochat":
143 gochat(account
, params
)
144 elif command
.lower() == "addbuddy":
145 addbuddy(account
, screenname
, params
.get("group", ""))
149 match
= re
.match(r
"^gg:(.*)", uri
)
151 print "Invalid gg URI: %s" % uri
154 screenname
= urllib
.unquote_plus(match
.group(1))
155 account
= findaccount(protocol
)
156 goim(account
, screenname
)
159 protocol
= "prpl-icq"
160 match
= re
.match(r
"^icq:([^?]*)(\?(.*))", uri
)
162 print "Invalid icq URI: %s" % uri
165 command
= urllib
.unquote_plus(match
.group(1))
166 paramstring
= match
.group(3)
169 for param
in paramstring
.split("&"):
170 key
, value
= extendlist(param
.split("=", 1), 2, "")
171 params
[key
] = urllib
.unquote_plus(value
)
172 accountname
= params
.get("account", "")
173 screenname
= params
.get("screenname", "")
175 account
= findaccount(protocol
, accountname
)
177 if command
.lower() == "goim":
178 goim(account
, screenname
, params
.get("message"))
179 elif command
.lower() == "gochat":
180 gochat(account
, params
)
181 elif command
.lower() == "addbuddy":
182 addbuddy(account
, screenname
, params
.get("group", ""))
185 protocol
= "prpl-irc"
186 match
= re
.match(r
"^irc:(//([^/]*))?/?([^?]*)(\?(.*))?", uri
)
188 print "Invalid irc URI: %s" % uri
191 server
= urllib
.unquote_plus(match
.group(2)) or ""
192 target
= match
.group(3) or ""
193 query
= match
.group(5) or ""
197 for modifier
in target
.split(",")[1:]:
198 modifiers
[modifier
] = True
200 isnick
= modifiers
.has_key("isnick")
202 paramstring
= match
.group(5)
205 for param
in paramstring
.split("&"):
206 key
, value
= extendlist(param
.split("=", 1), 2, "")
207 params
[key
] = urllib
.unquote_plus(value
)
209 def correct_server(account
):
210 username
= cpurple
.PurpleAccountGetUsername(account
)
211 return ((server
== "") or ("@" in username
) and (server
== (username
.split("@"))[1]))
213 account
= findaccount(protocol
, matcher
=correct_server
)
217 goim(account
, urllib
.unquote_plus(target
.split(",")[0]), params
.get("msg"))
219 channel
= urllib
.unquote_plus(target
.split(",")[0])
220 if channel
[0] != "#":
221 channel
= "#" + channel
222 gochat(account
, {"server": server
, "channel": channel
, "password": params
.get("key", "")}, params
.get("msg"))
225 protocol
= "prpl-msn"
226 match
= re
.match(r
"^msnim:([^?]*)(\?(.*))", uri
)
228 print "Invalid msnim URI: %s" % uri
231 command
= urllib
.unquote_plus(match
.group(1))
232 paramstring
= match
.group(3)
235 for param
in paramstring
.split("&"):
236 key
, value
= extendlist(param
.split("=", 1), 2, "")
237 params
[key
] = urllib
.unquote_plus(value
)
238 screenname
= params
.get("contact", "")
240 account
= findaccount(protocol
)
242 if command
.lower() == "chat":
243 goim(account
, screenname
)
244 elif command
.lower() == "add":
245 addbuddy(account
, screenname
)
248 protocol
= "prpl-myspace"
249 print "TODO: send uri: ", uri
250 assert False, "Not implemented"
253 protocol
= "prpl-simple"
254 match
= re
.match(r
"^sip:(.*)", uri
)
256 print "Invalid sip URI: %s" % uri
259 screenname
= urllib
.unquote_plus(match
.group(1))
260 account
= findaccount(protocol
)
261 goim(account
, screenname
)
264 protocol
= "prpl-jabber"
265 match
= re
.match(r
"^xmpp:(//([^/?#]*)/?)?([^?#]*)(\?([^;#]*)(;([^#]*))?)?(#(.*))?", uri
)
267 print "Invalid xmpp URI: %s" % uri
272 accountname
= urllib
.unquote_plus(tmp
)
276 screenname
= urllib
.unquote_plus(match
.group(3))
280 command
= urllib
.unquote_plus(tmp
)
284 paramstring
= match
.group(7)
287 for param
in paramstring
.split(";"):
288 key
, value
= extendlist(param
.split("=", 1), 2, "")
289 params
[key
] = urllib
.unquote_plus(value
)
291 account
= findaccount(protocol
, accountname
)
293 if command
.lower() == "message":
294 goim(account
, screenname
, params
.get("body"))
295 elif command
.lower() == "join":
296 room
, server
= screenname
.split("@")
297 gochat(account
, {"room": room
, "server": server
})
298 elif command
.lower() == "roster":
299 addbuddy(account
, screenname
, params
.get("group", ""), params
.get("name", ""))
301 goim(account
, screenname
)
304 protocol
= "prpl-jabber"
305 match
= re
.match(r
"^gtalk:([^?]*)(\?(.*))", uri
)
307 print "Invalid gtalk URI: %s" % uri
310 command
= urllib
.unquote_plus(match
.group(1))
311 paramstring
= match
.group(3)
314 for param
in paramstring
.split("&"):
315 key
, value
= extendlist(param
.split("=", 1), 2, "")
316 params
[key
] = urllib
.unquote_plus(value
)
317 accountname
= params
.get("from_jid", "")
318 jid
= params
.get("jid", "")
320 account
= findaccount(protocol
, accountname
)
322 if command
.lower() == "chat":
324 elif command
.lower() == "call":
325 # XXX V&V prompt to establish call
329 protocol
= "prpl-yahoo"
330 match
= re
.match(r
"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri
)
332 print "Invalid ymsgr URI: %s" % uri
335 command
= urllib
.unquote_plus(match
.group(1))
336 screenname
= urllib
.unquote_plus(match
.group(3))
337 paramstring
= match
.group(5)
340 for param
in paramstring
.split("&"):
341 key
, value
= extendlist(param
.split("=", 1), 2, "")
342 params
[key
] = urllib
.unquote_plus(value
)
344 account
= findaccount(protocol
)
346 if command
.lower() == "sendim":
347 goim(account
, screenname
, params
.get("m"))
348 elif command
.lower() == "chat":
349 gochat(account
, {"room": screenname
})
350 elif command
.lower() == "addfriend":
351 addbuddy(account
, screenname
)
354 def main(argv
=sys
.argv
):
355 if len(argv
) != 2 or argv
[1] == "--help" or argv
[1] == "-h":
356 print "Usage: %s URI" % argv
[0]
357 print "Example: %s \"xmpp:romeo@montague.net?message\"" % argv
[0]
365 type = uri
.split(":")[0]
376 elif type == "msnim":
384 elif type == "gtalk":
386 elif type == "ymsgr":
389 print "Unknown protocol: %s" % type
390 except dbus
.DBusException
, e
:
391 print "Error: %s" % (e
.message
)
394 if __name__
== "__main__":