Move the "Change status to" menu to be beside the checkbox controlling it.
[pidgin-git.git] / libpurple / purple-url-handler
blob083070b1ae80ac771bd93da59114a1bc39223afb
1 #!/usr/bin/env python
3 import dbus
4 import re
5 import sys
6 import time
7 import urllib
9 bus = dbus.SessionBus()
10 obj = None
11 try:
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."
17 sys.exit(1)
18 purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
20 class CheckedObject:
21 def __init__(self, obj):
22 self.obj = obj
24 def __getattr__(self, attr):
25 return CheckedAttribute(self, attr)
27 class CheckedAttribute:
28 def __init__(self, cobj, attr):
29 self.cobj = cobj
30 self.attr = 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
37 sys.stderr = None
38 result = self.cobj.obj.__getattr__(self.attr)(*args)
39 sys.stderr = real_stderr
41 # This can be useful for debugging.
42 # if (result == 0):
43 # print "Error: " + self.attr + " " + str(args) + " returned " + str(result)
45 return result
47 cpurple = CheckedObject(purple)
49 def extendlist(list, length, fill):
50 if len(list) < length:
51 return list + [fill] * (length - len(list))
52 else:
53 return list
55 def convert(value):
56 try:
57 return int(value)
58 except:
59 return value
61 def account_not_found():
62 print "No matching account found."
63 sys.exit(1)
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):
74 if matcher:
75 for account in cpurple.PurpleAccountsGetAll():
76 if accountname != "" and accountname != cpurple.PurpleAccountGetUsername(a):
77 continue
78 if matcher(account):
79 bring_account_online(account)
80 return account
81 account_not_found()
83 # prefer connected accounts
84 account = cpurple.PurpleAccountsFindConnected(accountname, protocolname)
85 if (account != 0):
86 return account
88 # try to get any account and connect it
89 account = cpurple.PurpleAccountsFindAny(accountname, protocolname)
90 if (account == 0):
91 account_not_found()
93 bring_account_online(account)
94 return account
96 def goim(account, screenname, message=None):
97 # XXX: 1 == PURPLE_CONV_TYPE_IM
98 conversation = cpurple.PurpleConversationNew(1, account, screenname)
99 if message:
100 purple.PurpleConvSendConfirm(conversation, message)
102 def gochat(account, params, message=None):
103 connection = cpurple.PurpleAccountGetConnection(account)
104 purple.ServJoinChat(connection, params)
106 if message != None:
107 for i in range(20):
108 # XXX: 2 == PURPLE_CONV_TYPE_CHAT
109 conversation = purple.PurpleFindConversationWithAccount(2, params.get("channel", params.get("room")), account)
110 if conversation:
111 purple.PurpleConvSendConfirm(conversation, message)
112 break
113 else:
114 time.sleep(0.5)
116 def addbuddy(account, screenname, group="", alias=""):
117 cpurple.PurpleBlistRequestAddBuddy(account, screenname, group, alias)
120 def aim(uri):
121 protocol = "prpl-aim"
122 match = re.match(r"^aim:([^?]*)(\?(.*))", uri)
123 if not match:
124 print "Invalid aim URI: %s" % uri
125 return
127 command = urllib.unquote_plus(match.group(1))
128 paramstring = match.group(3)
129 params = {}
130 if paramstring:
131 for param in paramstring.split("&"):
132 key, value = extendlist(param.split("=", 1), 2, "")
133 params[key] = urllib.unquote_plus(value)
134 accountname = params.get("account", "")
135 screenname = params.get("screenname", "")
137 account = findaccount(protocol, accountname)
139 if command.lower() == "goim":
140 goim(account, screenname, params.get("message"))
141 elif command.lower() == "gochat":
142 gochat(account, params)
143 elif command.lower() == "addbuddy":
144 addbuddy(account, screenname, params.get("group", ""))
146 def gg(uri):
147 protocol = "prpl-gg"
148 match = re.match(r"^gg:(.*)", uri)
149 if not match:
150 print "Invalid gg URI: %s" % uri
151 return
153 screenname = urllib.unquote_plus(match.group(1))
154 account = findaccount(protocol)
155 goim(account, screenname)
157 def icq(uri):
158 protocol = "prpl-icq"
159 match = re.match(r"^icq:([^?]*)(\?(.*))", uri)
160 if not match:
161 print "Invalid icq URI: %s" % uri
162 return
164 command = urllib.unquote_plus(match.group(1))
165 paramstring = match.group(3)
166 params = {}
167 if paramstring:
168 for param in paramstring.split("&"):
169 key, value = extendlist(param.split("=", 1), 2, "")
170 params[key] = urllib.unquote_plus(value)
171 accountname = params.get("account", "")
172 screenname = params.get("screenname", "")
174 account = findaccount(protocol, accountname)
176 if command.lower() == "goim":
177 goim(account, screenname, params.get("message"))
178 elif command.lower() == "gochat":
179 gochat(account, params)
180 elif command.lower() == "addbuddy":
181 addbuddy(account, screenname, params.get("group", ""))
183 def irc(uri):
184 protocol = "prpl-irc"
185 match = re.match(r"^irc:(//([^/]*)/)?([^?]*)(\?(.*))?", uri)
186 if not match:
187 print "Invalid irc URI: %s" % uri
188 return
190 server = urllib.unquote_plus(match.group(2)) or ""
191 target = match.group(3) or ""
192 query = match.group(5) or ""
194 modifiers = {}
195 if target:
196 for modifier in target.split(",")[1:]:
197 modifiers[modifier] = True
199 isnick = modifiers.has_key("isnick")
201 paramstring = match.group(5)
202 params = {}
203 if paramstring:
204 for param in paramstring.split("&"):
205 key, value = extendlist(param.split("=", 1), 2, "")
206 params[key] = urllib.unquote_plus(value)
208 def correct_server(account):
209 username = cpurple.PurpleAccountGetUsername(account)
210 return ("@" in username) and (server == (username.split("@"))[1])
212 account = findaccount(protocol, matcher=correct_server)
214 if (target != ""):
215 if (isnick):
216 goim(account, urllib.unquote_plus(target.split(",")[0]), params.get("msg"))
217 else:
218 channel = urllib.unquote_plus(target.split(",")[0])
219 if channel[0] != "#":
220 channel = "#" + channel
221 gochat(account, {"server": server, "channel": channel, "password": params.get("key", "")}, params.get("msg"))
223 def msnim(uri):
224 protocol = "prpl-msn"
225 match = re.match(r"^msnim:([^?]*)(\?(.*))", uri)
226 if not match:
227 print "Invalid msnim URI: %s" % uri
228 return
230 command = urllib.unquote_plus(match.group(1))
231 paramstring = match.group(3)
232 params = {}
233 if paramstring:
234 for param in paramstring.split("&"):
235 key, value = extendlist(param.split("=", 1), 2, "")
236 params[key] = urllib.unquote_plus(value)
237 screenname = params.get("contact", "")
239 account = findaccount(protocol)
241 if command.lower() == "chat":
242 goim(account, screenname)
243 elif command.lower() == "add":
244 addbuddy(account, screenname)
246 def myim(uri):
247 protocol = "prpl-myspace"
248 print "TODO: send uri: ", uri
249 assert False, "Not implemented"
251 def sip(uri):
252 protocol = "prpl-simple"
253 match = re.match(r"^sip:(.*)", uri)
254 if not match:
255 print "Invalid sip URI: %s" % uri
256 return
258 screenname = urllib.unquote_plus(match.group(1))
259 account = findaccount(protocol)
260 goim(account, screenname)
262 def xmpp(uri):
263 protocol = "prpl-jabber"
264 match = re.match(r"^xmpp:(//([^/?#]*)/?)?([^?#]*)(\?([^;#]*)(;([^#]*))?)?(#(.*))?", uri)
265 if not match:
266 print "Invalid xmpp URI: %s" % uri
267 return
269 tmp = match.group(2)
270 if (tmp):
271 accountname = urllib.unquote_plus(tmp)
272 else:
273 accountname = ""
275 screenname = urllib.unquote_plus(match.group(3))
277 tmp = match.group(5)
278 if (tmp):
279 command = urllib.unquote_plus(tmp)
280 else:
281 command = ""
283 paramstring = match.group(7)
284 params = {}
285 if paramstring:
286 for param in paramstring.split(";"):
287 key, value = extendlist(param.split("=", 1), 2, "")
288 params[key] = urllib.unquote_plus(value)
290 account = findaccount(protocol, accountname)
292 if command.lower() == "message":
293 goim(account, screenname, params.get("body"))
294 elif command.lower() == "join":
295 room, server = screenname.split("@")
296 gochat(account, {"room": room, "server": server})
297 elif command.lower() == "roster":
298 addbuddy(account, screenname, params.get("group", ""), params.get("name", ""))
299 else:
300 goim(account, screenname)
302 def gtalk(uri):
303 protocol = "prpl-jabber"
304 match = re.match(r"^gtalk:([^?]*)(\?(.*))", uri)
305 if not match:
306 print "Invalid gtalk URI: %s" % uri
307 return
309 command = urllib.unquote_plus(match.group(1))
310 paramstring = match.group(3)
311 params = {}
312 if paramstring:
313 for param in paramstring.split("&"):
314 key, value = extendlist(param.split("=", 1), 2, "")
315 params[key] = urllib.unquote_plus(value)
316 accountname = params.get("from_jid", "")
317 jid = params.get("jid", "")
319 account = findaccount(protocol, accountname)
321 if command.lower() == "chat":
322 goim(account, jid)
323 elif command.lower() == "call":
324 # XXX V&V prompt to establish call
325 goim(account, jid)
327 def ymsgr(uri):
328 protocol = "prpl-yahoo"
329 match = re.match(r"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri)
330 if not match:
331 print "Invalid ymsgr URI: %s" % uri
332 return
334 command = urllib.unquote_plus(match.group(1))
335 screenname = urllib.unquote_plus(match.group(3))
336 paramstring = match.group(5)
337 params = {}
338 if paramstring:
339 for param in paramstring.split("&"):
340 key, value = extendlist(param.split("=", 1), 2, "")
341 params[key] = urllib.unquote_plus(value)
343 account = findaccount(protocol)
345 if command.lower() == "sendim":
346 goim(account, screenname, params.get("m"))
347 elif command.lower() == "chat":
348 gochat(account, {"room": screenname})
349 elif command.lower() == "addfriend":
350 addbuddy(account, screenname)
353 def main(argv=sys.argv):
354 if len(argv) != 2 or argv[1] == "--help" or argv[1] == "-h":
355 print "Usage: %s URI" % argv[0]
356 print "Example: %s \"xmpp:romeo@montague.net?message\"" % argv[0]
358 if len(argv) != 2:
359 sys.exit(1)
360 else:
361 return 0
363 uri = argv[1]
364 type = uri.split(":")[0]
366 try:
367 if type == "aim":
368 aim(uri)
369 elif type == "gg":
370 gg(uri)
371 elif type == "icq":
372 icq(uri)
373 elif type == "irc":
374 irc(uri)
375 elif type == "msnim":
376 msnim(uri)
377 elif type == "myim":
378 myim(uri)
379 elif type == "sip":
380 sip(uri)
381 elif type == "xmpp":
382 xmpp(uri)
383 elif type == "gtalk":
384 gtalk(uri)
385 elif type == "ymsgr":
386 ymsgr(uri)
387 else:
388 print "Unknown protocol: %s" % type
389 except dbus.DBusException, e:
390 print "Error: %s" % (e.message)
391 sys.exit(1)
393 if __name__ == "__main__":
394 main()