Oops, I forgot this. This is done internally in libgadu, and not doing it
[pidgin-git.git] / libpurple / purple-remote
blob498a5a5f8a6520ec4da9eed9453b58fb113681b3
1 #!/usr/bin/env python
3 import dbus
4 import re
5 import urllib
6 import sys
8 import xml.dom.minidom
10 xml.dom.minidom.Element.all = xml.dom.minidom.Element.getElementsByTagName
12 obj = None
13 try:
14 obj = dbus.SessionBus().get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
15 except:
16 pass
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 result = self.cobj.obj.__getattr__(self.attr)(*args)
34 if result == 0:
35 raise "Error: " + self.attr + " " + str(args) + " returned " + str(result)
36 return result
38 def show_help(requested=False):
39 print """This program uses D-Bus to communicate with purple.
41 Usage:
43 %s "command1" "command2" ...
45 Each command is of one of the three types:
47 [protocol:]commandname?param1=value1&param2=value2&...
48 FunctionName?param1=value1&param2=value2&...
49 FunctionName(value1,value2,...)
51 The second and third form are provided for completeness but their use
52 is not recommended; use purple-send or purple-send-async instead. The
53 second form uses introspection to find out the parameter names and
54 their types, therefore it is rather slow.
56 Examples of commands:
58 jabber:goim?screenname=testone@localhost&message=hi
59 jabber:gochat?room=TestRoom&server=conference.localhost
60 jabber:getinfo?screenname=testone@localhost
61 jabber:addbuddy?screenname=my friend
63 setstatus?status=away&message=don't disturb
64 getstatus
65 getstatusmessage
66 quit
68 PurpleAccountsFindConnected?name=&protocol=prpl-jabber
69 PurpleAccountsFindConnected(,prpl-jabber)
70 """ % sys.argv[0]
71 if (requested):
72 sys.exit(0)
73 else:
74 sys.exit(1)
76 cpurple = CheckedObject(purple)
78 urlregexp = r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?"
80 def extendlist(list, length, fill):
81 if len(list) < length:
82 return list + [fill] * (length - len(list))
83 else:
84 return list
86 def convert(value):
87 try:
88 return int(value)
89 except:
90 return value
92 def findaccount(accountname, protocolname):
93 try:
94 # prefer connected accounts
95 account = cpurple.PurpleAccountsFindConnected(accountname, protocolname)
96 return account
97 except:
98 # try to get any account and connect it
99 account = cpurple.PurpleAccountsFindAny(accountname, protocolname)
100 purple.PurpleAccountSetStatusVargs(account, "online", 1)
101 purple.PurpleAccountConnect(account)
102 return account
105 def execute(uri):
106 match = re.match(urlregexp, uri)
107 protocol = match.group(2)
108 if protocol == "xmpp":
109 protocol = "jabber"
110 if protocol is not None:
111 protocol = "prpl-" + protocol
112 command = match.group(5)
113 paramstring = match.group(7)
114 params = {}
115 if paramstring is not None:
116 for param in paramstring.split("&"):
117 key, value = extendlist(param.split("=",1), 2, "")
118 params[key] = urllib.unquote(value)
120 accountname = params.get("account", "")
122 if command == "goim":
123 account = findaccount(accountname, protocol)
124 conversation = cpurple.PurpleConversationNew(1, account, params["screenname"])
125 if "message" in params:
126 im = cpurple.PurpleConversationGetImData(conversation)
127 purple.PurpleConvImSend(im, params["message"])
128 return None
130 elif command == "gochat":
131 account = findaccount(accountname, protocol)
132 connection = cpurple.PurpleAccountGetConnection(account)
133 return purple.ServJoinChat(connection, params)
135 elif command == "addbuddy":
136 account = findaccount(accountname, protocol)
137 return cpurple.PurpleBlistRequestAddBuddy(account, params["screenname"],
138 params.get("group", ""), "")
140 elif command == "setstatus":
141 current = purple.PurpleSavedstatusGetCurrent()
143 if "status" in params:
144 status_id = params["status"]
145 status_type = purple.PurplePrimitiveGetTypeFromId(status_id)
146 else:
147 status_type = purple.PurpleSavedstatusGetType(current)
148 status_id = purple.PurplePrimitiveGetIdFromType(status_type)
150 if "message" in params:
151 message = params["message"];
152 else:
153 message = purple.PurpleSavedstatusGetMessage(current)
155 if "account" in params:
156 accounts = [cpurple.PurpleAccountsFindAny(accountname, protocol)]
158 for account in accounts:
159 status = purple.PurpleAccountGetStatus(account, status_id)
160 type = purple.PurpleStatusGetType(status)
161 purple.PurpleSavedstatusSetSubstatus(current, account, type, message)
162 purple.PurpleSavedstatusActivateForAccount(current, account)
163 else:
164 saved = purple.PurpleSavedstatusNew("", status_type)
165 purple.PurpleSavedstatusSetMessage(saved, message)
166 purple.PurpleSavedstatusActivate(saved)
168 return None
170 elif command == "getstatus":
171 current = purple.PurpleSavedstatusGetCurrent()
172 status_type = purple.PurpleSavedstatusGetType(current)
173 status_id = purple.PurplePrimitiveGetIdFromType(status_type)
174 return status_id
176 elif command == "getstatusmessage":
177 current = purple.PurpleSavedstatusGetCurrent()
178 return purple.PurpleSavedstatusGetMessage(current)
180 elif command == "getinfo":
181 account = findaccount(accountname, protocol)
182 connection = cpurple.PurpleAccountGetConnection(account)
183 return purple.ServGetInfo(connection, params["screenname"])
185 elif command == "quit":
186 return purple.PurpleCoreQuit()
188 elif command == "uri":
189 return None
191 else:
192 match = re.match(r"(\w+)\s*\(([^)]*)\)", command)
193 if match is not None:
194 name = match.group(1)
195 argstr = match.group(2)
196 if argstr == "":
197 args = []
198 else:
199 args = argstr.split(",")
200 fargs = []
201 for arg in args:
202 fargs.append(convert(arg.strip()))
203 return purple.__getattr__(name)(*fargs)
204 else:
205 # introspect the object to get parameter names and types
206 # this is slow because the entire introspection info must be downloaded
207 data = dbus.Interface(obj, "org.freedesktop.DBus.Introspectable").\
208 Introspect()
209 introspect = xml.dom.minidom.parseString(data).documentElement
210 for method in introspect.all("method"):
211 if command == method.getAttribute("name"):
212 methodparams = []
213 for arg in method.all("arg"):
214 if arg.getAttribute("direction") == "in":
215 value = params[arg.getAttribute("name")]
216 type = arg.getAttribute("type")
217 if type == "s":
218 methodparams.append(value)
219 elif type == "i":
220 methodparams.append(int(value))
221 else:
222 raise "Don't know how to handle type \"%s\"" % type
223 return purple.__getattr__(command)(*methodparams)
224 show_help()
226 if len(sys.argv) == 1:
227 show_help()
228 elif (sys.argv[1] == "--help" or sys.argv[1] == "-h"):
229 show_help(True)
230 elif (obj == None):
231 print "No existing libpurple instance detected."
232 sys.exit(1);
234 for arg in sys.argv[1:]:
235 output = execute(arg)
237 if (output != None):
238 print output