3 from __future__
import absolute_import
, division
, print_function
9 from urllib
.parse
import unquote
11 from urllib
import unquote
12 import xml
.dom
.minidom
17 sys
.stdin
= codecs
.getwriter('utf-8')(sys
.stdin
)
18 sys
.stdout
= codecs
.getwriter('utf-8')(sys
.stdout
)
20 xml
.dom
.minidom
.Element
.all
= xml
.dom
.minidom
.Element
.getElementsByTagName
24 obj
= dbus
.SessionBus().get_object("im.pidgin.purple.PurpleService",
25 "/im/pidgin/purple/PurpleObject")
29 purple
= dbus
.Interface(obj
, "im.pidgin.purple.PurpleInterface")
32 class CheckedObject(object):
33 def __init__(self
, obj
):
36 def __getattr__(self
, attr
):
37 return CheckedAttribute(self
, attr
)
40 class CheckedAttribute(object):
41 def __init__(self
, cobj
, attr
):
45 def __call__(self
, *args
):
46 result
= self
.cobj
.obj
.__getattr
__(self
.attr
)(*args
)
48 raise Exception("Error: %s %s returned %s" %
49 (self
.attr
, args
, result
))
53 def show_help(requested
=False):
54 print("""This program uses D-Bus to communicate with purple.
58 %s "command1" "command2" ...
60 Each command is of one of the three types:
62 [protocol:]commandname?param1=value1¶m2=value2&...
63 FunctionName?param1=value1¶m2=value2&...
64 FunctionName(value1,value2,...)
66 The second and third form are provided for completeness but their use
67 is not recommended; use purple-send or purple-send-async instead. The
68 second form uses introspection to find out the parameter names and
69 their types, therefore it is rather slow.
73 jabber:goim?screenname=testone@localhost&message=hi
74 jabber:gochat?room=TestRoom&server=conference.localhost
75 jabber:getinfo?screenname=testone@localhost
76 jabber:addbuddy?screenname=my friend
78 setstatus?status=away&message=don't disturb
83 PurpleAccountsFindConnected?name=&protocol=jabber
84 PurpleAccountsFindConnected(,jabber)
85 """ % (sys
.argv
[0], ))
92 cpurple
= CheckedObject(purple
)
94 urlregexp
= r
"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?"
97 def extendlist(list, length
, fill
):
98 if len(list) < length
:
99 return list + [fill
] * (length
- len(list))
111 def findaccount(accountname
, protocolname
):
113 # prefer connected accounts
114 account
= cpurple
.PurpleAccountsFindConnected(accountname
,
118 # try to get any account and connect it
119 account
= cpurple
.PurpleAccountsFindAny(accountname
, protocolname
)
120 purple
.PurpleAccountSetStatusVargs(account
, "online", 1)
121 purple
.PurpleAccountConnect(account
)
126 match
= re
.match(urlregexp
, uri
)
127 protocol
= match
.group(2)
128 if protocol
== "xmpp":
130 if protocol
is not None:
131 protocol
= "prpl-" + protocol
132 command
= match
.group(5)
133 paramstring
= match
.group(7)
135 if paramstring
is not None:
136 for param
in paramstring
.split("&"):
137 key
, value
= extendlist(param
.split("=", 1), 2, "")
138 params
[key
] = unquote(value
)
140 accountname
= params
.get("account", "")
142 if command
== "goim":
143 account
= findaccount(accountname
, protocol
)
144 conversation
= cpurple
.PurpleConversationNew(1, account
,
145 params
["screenname"])
146 if "message" in params
:
147 im
= cpurple
.PurpleConversationGetImData(conversation
)
148 purple
.PurpleConvImSend(im
, params
["message"])
151 elif command
== "gochat":
152 account
= findaccount(accountname
, protocol
)
153 connection
= cpurple
.PurpleAccountGetConnection(account
)
154 return purple
.PurpleServJoinChat(connection
, params
)
156 elif command
== "addbuddy":
157 account
= findaccount(accountname
, protocol
)
158 return cpurple
.PurpleBlistRequestAddBuddy(account
,
159 params
["screenname"],
160 params
.get("group", ""),
163 elif command
== "setstatus":
164 current
= purple
.PurpleSavedstatusGetCurrent()
166 if "status" in params
:
167 status_id
= params
["status"]
168 status_type
= purple
.PurplePrimitiveGetTypeFromId(status_id
)
170 status_type
= purple
.PurpleSavedstatusGetType(current
)
171 status_id
= purple
.PurplePrimitiveGetIdFromType(status_type
)
173 if "message" in params
:
174 message
= params
["message"]
176 message
= purple
.PurpleSavedstatusGetMessage(current
)
178 if "account" in params
:
179 accounts
= [cpurple
.PurpleAccountsFindAny(accountname
, protocol
)]
181 for account
in accounts
:
182 status
= purple
.PurpleAccountGetStatus(account
, status_id
)
183 type = purple
.PurpleStatusGetType(status
)
184 purple
.PurpleSavedstatusSetSubstatus(current
, account
, type,
186 purple
.PurpleSavedstatusActivateForAccount(current
, account
)
188 saved
= purple
.PurpleSavedstatusNew("", status_type
)
189 purple
.PurpleSavedstatusSetMessage(saved
, message
)
190 purple
.PurpleSavedstatusActivate(saved
)
194 elif command
== "getstatus":
195 current
= purple
.PurpleSavedstatusGetCurrent()
196 status_type
= purple
.PurpleSavedstatusGetType(current
)
197 status_id
= purple
.PurplePrimitiveGetIdFromType(status_type
)
200 elif command
== "getstatusmessage":
201 current
= purple
.PurpleSavedstatusGetCurrent()
202 return purple
.PurpleSavedstatusGetMessage(current
)
204 elif command
== "getinfo":
205 account
= findaccount(accountname
, protocol
)
206 connection
= cpurple
.PurpleAccountGetConnection(account
)
207 return purple
.ServGetInfo(connection
, params
["screenname"])
209 elif command
== "quit":
210 return purple
.PurpleCoreQuit()
212 elif command
== "uri":
216 match
= re
.match(r
"(\w+)\s*\(([^)]*)\)", command
)
217 if match
is not None:
218 name
= match
.group(1)
219 argstr
= match
.group(2)
223 args
= argstr
.split(",")
226 fargs
.append(convert(arg
.strip()))
227 return purple
.__getattr
__(name
)(*fargs
)
229 # Introspect the object to get parameter names and types. This is
230 # slow because the entire introspection info must be downloaded.
231 interface
= dbus
.Interface(obj
,
232 "org.freedesktop.DBus.Introspectable")
233 data
= interface
.Introspect()
234 introspect
= xml
.dom
.minidom
.parseString(data
).documentElement
235 for method
in introspect
.all("method"):
236 if command
== method
.getAttribute("name"):
238 for arg
in method
.all("arg"):
239 if arg
.getAttribute("direction") == "in":
240 value
= params
[arg
.getAttribute("name")]
241 type = arg
.getAttribute("type")
243 methodparams
.append(value
)
245 methodparams
.append(int(value
))
248 "Don't know how to handle type \"%s\"" % (
250 return purple
.__getattr
__(command
)(*methodparams
)
254 if len(sys
.argv
) == 1:
256 elif sys
.argv
[1] == "--help" or sys
.argv
[1] == "-h":
259 print("No existing libpurple instance detected.")
262 for arg
in sys
.argv
[1:]:
263 output
= execute(arg
)
265 if output
is not None: