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