| |
1 #!/usr/bin/python |
| |
2 |
| |
3 import dbus |
| |
4 import re |
| |
5 import urllib |
| |
6 import sys |
| |
7 |
| |
8 import xml.dom.minidom |
| |
9 |
| |
10 xml.dom.minidom.Element.all = xml.dom.minidom.Element.getElementsByTagName |
| |
11 |
| |
12 obj = dbus.SessionBus().get_object("net.sf.gaim.GaimService", "/net/sf/gaim/GaimObject") |
| |
13 gaim = dbus.Interface(obj, "net.sf.gaim.GaimInterface") |
| |
14 |
| |
15 class CheckedObject: |
| |
16 def __init__(self, obj): |
| |
17 self.obj = obj |
| |
18 |
| |
19 def __getattr__(self, attr): |
| |
20 return CheckedAttribute(self, attr) |
| |
21 |
| |
22 class CheckedAttribute: |
| |
23 def __init__(self, cobj, attr): |
| |
24 self.cobj = cobj |
| |
25 self.attr = attr |
| |
26 |
| |
27 def __call__(self, *args): |
| |
28 result = self.cobj.obj.__getattr__(self.attr)(*args) |
| |
29 if result == 0: |
| |
30 raise "Error: " + self.attr + " " + str(args) + " returned " + str(result) |
| |
31 return result |
| |
32 |
| |
33 cgaim = CheckedObject(gaim) |
| |
34 |
| |
35 urlregexp = r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?" |
| |
36 |
| |
37 def extendlist(list, length, fill): |
| |
38 if len(list) < length: |
| |
39 return list + [fill] * (length - len(list)) |
| |
40 else: |
| |
41 return list |
| |
42 |
| |
43 def convert(value): |
| |
44 try: |
| |
45 return int(value) |
| |
46 except: |
| |
47 return value |
| |
48 |
| |
49 def findaccount(accountname, protocolname): |
| |
50 try: |
| |
51 # prefer connected accounts |
| |
52 account = cgaim.GaimAccountsFindConnected(accountname, protocolname) |
| |
53 return account |
| |
54 except: |
| |
55 # try to get any account and connect it |
| |
56 account = cgaim.GaimAccountsFindAny(accountname, protocolname) |
| |
57 gaim.GaimAccountSetStatusVargs(account, "online", 1) |
| |
58 gaim.GaimAccountConnect(account) |
| |
59 return account |
| |
60 |
| |
61 |
| |
62 def execute(uri): |
| |
63 match = re.match(urlregexp, uri) |
| |
64 protocol = match.group(2) |
| |
65 if protocol == "aim" or protocol == "icq": |
| |
66 protocol = "oscar" |
| |
67 if protocol is not None: |
| |
68 protocol = "prpl-" + protocol |
| |
69 command = match.group(5) |
| |
70 paramstring = match.group(7) |
| |
71 params = {} |
| |
72 if paramstring is not None: |
| |
73 for param in paramstring.split("&"): |
| |
74 key, value = extendlist(param.split("=",1), 2, "") |
| |
75 params[key] = urllib.unquote(value) |
| |
76 |
| |
77 accountname = params.get("account", "") |
| |
78 |
| |
79 if command == "goim": |
| |
80 account = findaccount(accountname, protocol) |
| |
81 conversation = cgaim.GaimConversationNew(1, account, params["screenname"]) |
| |
82 if "message" in params: |
| |
83 im = cgaim.GaimConversationGetImData(conversation) |
| |
84 gaim.GaimConvImSend(im, params["message"]) |
| |
85 return None |
| |
86 |
| |
87 elif command == "gochat": |
| |
88 account = findaccount(accountname, protocol) |
| |
89 connection = cgaim.GaimAccountGetConnection(account) |
| |
90 return gaim.ServJoinChat(connection, params) |
| |
91 |
| |
92 elif command == "addbuddy": |
| |
93 account = findaccount(accountname, protocol) |
| |
94 return cgaim.GaimBlistRequestAddBuddy(account, params["screenname"], |
| |
95 params.get("group", ""), "") |
| |
96 |
| |
97 elif command == "setstatus": |
| |
98 current = gaim.GaimSavedstatusGetCurrent() |
| |
99 |
| |
100 if "status" in params: |
| |
101 status_id = params["status"] |
| |
102 status_type = gaim.GaimPrimitiveGetTypeFromId(status_id) |
| |
103 else: |
| |
104 status_type = gaim.GaimSavedStatusGetType(current) |
| |
105 status_id = gaim.GaimPrimitiveGetIdFromType(status_type) |
| |
106 |
| |
107 if "message" in params: |
| |
108 message = params["message"]; |
| |
109 else: |
| |
110 message = gaim.GaimSavedstatusGetMessage(current) |
| |
111 |
| |
112 if "account" in params: |
| |
113 accounts = [cgaim.GaimAccountsFindAny(accountname, protocol)] |
| |
114 |
| |
115 for account in accounts: |
| |
116 status = gaim.GaimAccountGetStatus(account, status_id) |
| |
117 type = gaim.GaimStatusGetType(status) |
| |
118 gaim.GaimSavedstatusSetSubstatus(current, account, type, message) |
| |
119 gaim.GaimSavedstatusActivateForAccount(current, account) |
| |
120 else: |
| |
121 accounts = gaim.GaimAccountsGetAllActive() |
| |
122 saved = gaim.GaimSavedstatusNew("", status_type) |
| |
123 gaim.GaimSavedstatusSetMessage(saved, message) |
| |
124 gaim.GaimSavedstatusActivate(saved) |
| |
125 |
| |
126 return None |
| |
127 |
| |
128 elif command == "getinfo": |
| |
129 account = findaccount(accountname, protocol) |
| |
130 connection = cgaim.GaimAccountGetConnection(account) |
| |
131 return gaim.ServGetInfo(connection, params["screenname"]) |
| |
132 |
| |
133 elif command == "quit": |
| |
134 return gaim.GaimCoreQuit() |
| |
135 |
| |
136 elif command == "uri": |
| |
137 return None |
| |
138 |
| |
139 else: |
| |
140 match = re.match(r"(\w+)\s*\(([^)]*)\)", command) |
| |
141 if match is not None: |
| |
142 name = match.group(1) |
| |
143 argstr = match.group(2) |
| |
144 if argstr == "": |
| |
145 args = [] |
| |
146 else: |
| |
147 args = argstr.split(",") |
| |
148 fargs = [] |
| |
149 for arg in args: |
| |
150 fargs.append(convert(arg.strip())) |
| |
151 return gaim.__getattr__(name)(*fargs) |
| |
152 else: |
| |
153 # introspect the object to get parameter names and types |
| |
154 # this is slow because the entire introspection info must be downloaded |
| |
155 data = dbus.Interface(obj, "org.freedesktop.DBus.Introspectable").\ |
| |
156 Introspect() |
| |
157 introspect = xml.dom.minidom.parseString(data).documentElement |
| |
158 for method in introspect.all("method"): |
| |
159 if command == method.getAttribute("name"): |
| |
160 methodparams = [] |
| |
161 for arg in method.all("arg"): |
| |
162 if arg.getAttribute("direction") == "in": |
| |
163 value = params[arg.getAttribute("name")] |
| |
164 type = arg.getAttribute("type") |
| |
165 if type == "s": |
| |
166 methodparams.append(value) |
| |
167 elif type == "i": |
| |
168 methodparams.append(int(value)) |
| |
169 else: |
| |
170 raise "Don't know how to handle type \"%s\"" % type |
| |
171 return gaim.__getattr__(command)(*methodparams) |
| |
172 raise "Unknown command: %s" % command |
| |
173 |
| |
174 |
| |
175 if len(sys.argv) == 1: |
| |
176 print """This program uses DBus to communicate with gaim. |
| |
177 |
| |
178 Usage: |
| |
179 |
| |
180 %s "command1" "command2" ... |
| |
181 |
| |
182 Each command is of one of the three types: |
| |
183 |
| |
184 [protocol:]commandname?param1=value1¶m2=value2&... |
| |
185 FunctionName?param1=value1¶m2=value2&... |
| |
186 FunctionName(value1,value2,...) |
| |
187 |
| |
188 The second and third form are provided for completeness but their use |
| |
189 is not recommended; use gaim-send or gaim-send-async instead. The |
| |
190 second form uses introspection to find out the parameter names and |
| |
191 their types, therefore it is rather slow. |
| |
192 |
| |
193 Examples of commands: |
| |
194 |
| |
195 jabber:goim?screenname=testone@localhost&message=hi |
| |
196 jabber:gochat?room=TestRoom&server=conference.localhost |
| |
197 jabber:getinfo?screenname=testone@localhost |
| |
198 jabber:addbuddy?screenname=my friend |
| |
199 |
| |
200 setstatus?status=away&message=don't disturb |
| |
201 quit |
| |
202 |
| |
203 GaimAccountsFindConnected?name=&protocol=prpl-jabber |
| |
204 GaimAccountFindConnected(,prpl-jabber) |
| |
205 """ % sys.argv[0] |
| |
206 |
| |
207 for arg in sys.argv[1:]: |
| |
208 output = execute(arg) |
| |
209 |
| |
210 if (output != None): |
| |
211 print output |
| |
212 |