如何使用python通过D-Bus从Skype接收活动?

时间:2013-05-26 00:08:19

标签: python skype dbus pygobject

(我知道这类似于Python and d-bus: How to set up main loop?,但是在“答案”中没有完整的代码,我无法弄清楚我出错的地方。它可能只是Skype的变化)

这是我的计划:

import gobject
import dbus
import dbus.mainloop.glib
dbus_gmainloop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
sessbus = dbus.SessionBus()
skype = sessbus.get_object('com.Skype.API', '/com/Skype')
skypec = sessbus.get_object('com.Skype.API', '/com/Skype/Client')
skype_iface = dbus.Interface(skype, dbus_interface='com.Skype.API')
skype_iface.Invoke("NAME py1")
# ... waits for user click in Skype ...
#==> dbus.String(u'OK')
skype_iface.Invoke("PROTOCOL 7")
#==> dbus.String(u'PROTOCOL 7')
def got_signal(sender, destination, member, interface, path):
  print "got_signal(sender=%s, dest=%s, member=%s, iface=%s, path=%s)" \
    % (sender, destination, member, interface, path)

skypec.connect_to_signal('Notify', got_signal, sender_keyword='sender', \
  destination_keyword='destination', member_keyword='member', \
  interface_keyword='interface', path_keyword='path')

mainloop = gobject.MainLoop()
mainloop.run()

运行时(例如python skype-call.py),它会在将NAME py1命令发送到Skype并等待Skype UI中的交互式确认后暂停,然后继续。因此,skype_iface对象显然至少在一定程度上起作用。

但是,python会发出以下错误:

ERROR:dbus.proxies:Introspect error on :1.152:/com/Skype/Client: dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownObject: No such object path '/com/Skype/Client'

我也尝试了以下(而不是connect_to_signal,就在最后开始gobject mainloop之前):

def receiver(x, **kwargs):
  print "receiver(%s)" % (x,)

sessbus.add_signal_receiver(receiver, signal_name='Notify', \
  dbus_interface='com.Skype.API', bus_name='com.Skype.API', path='/com/Skype/Client')

虽然没有抱怨,但它永远不会被召唤。我尝试向Skype用户发送消息。什么样的事件应该引发它?

https://dev.skype.com/desktop-api-reference#DBUSUsage上的文档并不是非常有用。

这是Debian 7.0 multiarch上的Skype for Linux 4.2.0.11(amd64 / i386)。

2 个答案:

答案 0 :(得分:3)

回顾http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#exporting-methods-with-dbus-service-method,我尝试了他们的榜样:

import gobject
import dbus
from dbus.decorators import method
import dbus.mainloop.glib
import dbus.service

dbus_gmainloop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
sessbus = dbus.SessionBus()

class Example(dbus.service.Object):
    def __init__(self, bus):
        dbus.service.Object.__init__(self, bus, '/com/Skype/Client')

    @method(dbus_interface='com.Skype.API.Client', in_signature='s', \
            sender_keyword='sender', destination_keyword='dest', \
            rel_path_keyword='rel_path', path_keyword='path', \
            message_keyword='message', connection_keyword='conn')
    def Notify(self, s, sender=None, dest=None, rel_path=None, path=None, \
               message=None, conn=None):
        print "Notify(%s, sender=%s, dest=%s, rel_path=%s, path=%s, message=%s, conn=%s)" \
              % (s, sender, path, dest, message, rel_path, conn,)

# make one:
ex = Example(sessbus)

skype = sessbus.get_object('com.Skype.API', '/com/Skype')
skype_iface = dbus.Interface(skype, dbus_interface='com.Skype.API')
skype_iface.Invoke("NAME py1")
##=> dbus.String(u'OK')
skype_iface.Invoke("PROTOCOL 7")
##=> dbus.String(u'PROTOCOL 7')

mainloop = gobject.MainLoop()
mainloop.run()

然后我看到Notify来电:

Notify(CONNSTATUS ONLINE, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

Notify(CURRENTUSERHANDLE ******, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

Notify(USERSTATUS ONLINE, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

显然,这不是一个结构良好的程序的一个很好的例子,但d-bus位似乎确实连接。

答案 1 :(得分:2)

我正在尝试调试同样的事情,也许我们可以一起排序(我也在使用wheezy amd64,顺便说一下)......

根据我的理解,看起来com.Skype.API没有公开名为/com/Skype/Client的对象(并且d-feet确认了这一点)。

我在向Skype帐号发送消息时使用dbus-monitor监控总线。在其他输出中,我得到了这个:

method call sender=:1.43 -> dest=:1.132 serial=324 path=/com/Skype/Client; interface=com.Skype.API.Client; member=Notify
   string "CHAT #rshk-testuser1/$myusername;<hex-code-here> ACTIVITY_TIMESTAMP 1370647479"
error sender=:1.132 -> dest=:1.43 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=324
   string "Method "Notify" with signature "s" on interface "com.Skype.API.Client" doesn't exist
"
method call sender=:1.43 -> dest=:1.132 serial=325 path=/com/Skype/Client; interface=com.Skype.API.Client; member=Notify
   string "CHATMESSAGE 1538281 STATUS RECEIVED"
error sender=:1.132 -> dest=:1.43 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=325
   string "Method "Notify" with signature "s" on interface "com.Skype.API.Client" doesn't exist
"

所以,看起来有另一个名为com.Skype.API.Client的接口暴露了/com/Skype/Client对象,但由于某种原因接口无法访问..

我查看了/etc/dbus-1/system.d/skype.conf,其中只列出了com.Skype.API

我对dbus不是很有经验,但我正在努力深入挖掘并理解错误是什么......