Help - Search - Members - Calendar
Full Version: How to catch incoming calls using script ?
Skype Community > English > Skype for Linux
doublehp_
I would like:
- incoming calls to launch bash scripts
- script to start calls (both dial number, and accept incoming)
- finishing calls to launch scripts
- script to terminate calls.

I expect 1st and 3rd problem to require loads of hacking ... maybe not feasable at all.

Maybe it is just a matter of DBUS scripting ...

Any one got experience in that ? web pages ? scripts ?

my deal is to:
incoming call -> X pop up
OK button -> stop XMMS, shutdown ESD and Arts, stop mplayer, THEN accept call
end of calls -> automatically restart esd and arts

For pop ups, I usually use Xdialogs, then heavy BASH.

If 1st step is too much difficult, I hope 2nd is easy, and would really help me.
huomenta_
[quote=doublehp]I would like:
- incoming calls to launch bash scripts
- script to start calls (both dial number, and accept incoming)
- finishing calls to launch scripts
- script to terminate calls.

I expect 1st and 3rd problem to require loads of hacking ... maybe not feasable at all.

Maybe it is just a matter of DBUS scripting ...

Any one got experience in that ? web pages ? scripts ?
[/quote]

1,3,4 can be easily done with Python script running along with skype application. Not completely sure about 2.

I have script that does some actions in python using notifications mechanism of skype dbus api.
doublehp_
could you publish your scipts on the web, give me URLs, or otherwise email me them ? my email is on http://www.demaine.info/contact.png
huomenta_
Here you are.

The following script is very basic cli client for skype. Nothing fancy, just proof of concept. In fact, it is my first python program ;) I use it occasionally to skype-chat from ssh console. You still need skype application running in background, though.

To get it running you will need dbus 0.23 (0.22 is known to work too) with glib and python bindings and pygtk 2 (tested with pygtk 2.2).

Look at cb_call() function to get an idea of how to catch incoming call notification.

CODE


#!/usr/bin/env python

""" GPL """

import sys

import signal

import locale

import time

import dbus

import gobject





SKYPE_SERVICE = 'com.Skype.API'

CLIENT_NAME = 'SkypeApiPythonShell'



USER_PROPS = ('FULLNAME', 'SEX', 'LANGUAGE', 'COUNTRY', 'CITY', 'ABOUT',

             'ISAUTHORIZED', 'BUDDYSTATUS')





local_encoding = locale.getdefaultlocale()[1]

need_conv = (local_encoding != 'utf-8')



def utf8_decode(utf8_str):

   if need_conv:

       return utf8_str.decode('utf-8').encode(local_encoding, 'replace')

   else:

       return utf8_str



def utf8_encode(local_str):

   if need_conv:

       return local_str.decode(local_encoding).encode('utf-8')

   else:

       return local_str



def ts():

   return time.strftime('[%H:%M:%S]')





def sig_handler(signum, frame):

   print '### caught signal %d, exiting' % signum

   mainloop.quit()

   #sys.exit()





def excepthook(type, value, traceback):

   mainloop.quit()

   return sys.__excepthook__(type, value, traceback)





def input_handler(fd, io_condition):

   #print '### fd=%d cond=%d' % (fd.fileno(), io_condition)

   input = fd.readline()

   if len(input) == 0:     # EOF

       mainloop.quit()

       return 0

   return do_command(input)





def do_command(input):

   line = input.strip()

   argv = line.split(None, 1)

   if len(argv) == 0:      # empty command

       return 1

   #print '###', argv



   cmd = argv[0]

   if cmd == 'q':

       mainloop.quit()

       return 0

   elif commands.has_key(cmd):

       commands[cmd](argv)

   else:

       # send as-is

       print skype.send(line)

   return 1





def cmd_help(argv):

   """help"""

   print 'q - quit'

   for cmd, handler in commands.items():

       if handler.__doc__:

           print cmd, '-', handler.__doc__

   print '<cmd> - send API <cmd> to skype'





def cmd_list_users(argv):

   """list user status"""

   reply = skype.send('SEARCH FRIENDS')

   if reply.startswith('USERS '):

       user_list = reply[6:].split(', ')

       online = {}

       for user in user_list:

           reply = skype.send('GET USER %s ONLINESTATUS' % user)

           status = reply.split()[3]

           if status != 'SKYPEOUT':

               online[user] = status;

       for user, status in online.items():

           print '%-16s [%s]' % (user, status)

   else:

       print reply





def cmd_who(argv):

   """list who's online"""

   reply = skype.send('SEARCH FRIENDS')

   if reply.startswith('USERS '):

       user_list = reply[6:].split(', ')

       who = {}

       for user in user_list:

           reply = skype.send('GET USER %s ONLINESTATUS' % user)

           status = reply.split()[3]

           if status != 'SKYPEOUT' and status != 'OFFLINE':

               who[user] = status;

       for user, status in who.items():

           print '%-16s [%s]' % (user, status)

   else:

       print reply





def cmd_message(argv):

   """send message"""

   if len(argv) < 2 or argv[1].find(' ') == -1:

       print 'usage: m user text...'

   else:

       (user, text) = argv[1].split(None, 1)

       print skype.send(' '.join((skype.msg_cmd, user, text)))





def cmd_userinfo(argv):

   """show user info"""

   if len(argv) == 1:

       print 'usage: i user'

   else:

       user = argv[1]

       for prop in USER_PROPS:

           reply = skype.send('GET USER %s %s' % (user, prop))

           if reply.startswith('USER '):

               res = reply.split(None, 3)

               if len(res) > 3:

                   print '%-13s: %s' % (prop.title(), res[3])

           else:

               print reply





def cmd_test(argv):

   """test"""

   print skype.send("MESSAGE echo123 one two three")





def cb_message(argv):

   args = argv[1].split(None, 3)

   msg_cmd = argv[0]

   msg_id = args[0]

   if args[1] == 'STATUS' and args[2] == 'READ':

       reply = skype.send('GET %s %s PARTNER_HANDLE' % (msg_cmd, msg_id))

       user = reply.split(None, 3)[3]

       reply = skype.send('GET %s %s BODY' % (msg_cmd, msg_id))

       res = reply.split(None, 3)

       print ts(), user, '>', res[3]





def cb_call(argv):

   args = argv[1].split(None, 3)

   call_id = args[0]

   if args[1] == 'STATUS':

       if args[2] == 'RINGING':

           reply = skype.send('GET CALL %s PARTNER_HANDLE' % call_id)

           user = reply.split()[3]

           reply = skype.send('GET CALL %s TYPE' % call_id)

           call_type = reply.split()[3]

           call_media = call_type.split('_')[1]

           if call_type.startswith('INCOMING'):

               print ts(), '*** Incoming', call_media, 'call from', user

           elif call_type.startswith('OUTGOING'):

               print ts(), '*** Outgoing', call_media, 'call to', user

       elif args[2] == 'MISSED':

           reply = skype.send('GET CALL %s PARTNER_HANDLE' % call_id)

           user = reply.split()[3]

           print ts(), '*** missed call from', user





def cb_user(argv):

   args = argv[1].split(None, 2)

   user = args[0]

   if args[1] == 'ONLINESTATUS' and args[2] != 'SKYPEOUT':

       print ts(), '***', user, 'is', args[2]





class SkypeApi(dbus.Object):

   def __init__(self):

       bus = dbus.SystemBus()

       if not bus.get_service('org.freedesktop.DBus').get_object('/org/freedesktop/DBus', 'org.freedesktop.DBus').ServiceExists(SKYPE_SERVICE):

               #TODO: launch skype process

               sys.exit('No running API-capable Skype found')



       skype_service = bus.get_service(SKYPE_SERVICE)

       self.skype_api = skype_service.get_object('/com/Skype', SKYPE_SERVICE)



       reply = self.send('NAME ' + CLIENT_NAME)

       if reply != 'OK':

           sys.exit('Could not bind to Skype client')



       reply = self.send('PROTOCOL 1')

       #if reply != 'PROTOCOL 1':

       #    sys.exit('This test program only supports Skype API protocol version 1')

       self.msg_cmd = 'MESSAGE'



       self.callbacks = {'MESSAGE' : cb_message,

                         'CHATMESSAGE' : cb_message,

                         'USER' : cb_user,

                         'CALL' : cb_call}

       

       dbus.Object.__init__(self, "/com/Skype/Client", skype_service, [self.Notify])





   # skype -> client (async)

   def Notify(self, msg, msg_text):

       text = utf8_decode(msg_text)

       print ts(), '<<<', text

       argv = text.split(None, 1)

       if self.callbacks.has_key(argv[0]):

           self.callbacks[argv[0]](argv)



   # client -> skype (sync, 5 sec timeout)

   def send(self, msg_text):

       print '>> ', msg_text

       reply = utf8_decode(self.skype_api.Invoke(utf8_encode(msg_text)))

       print '<< ', reply

       return reply





commands = {'?' : cmd_help,

           'l' : cmd_list_users,

           'w' : cmd_who,

           'm' : cmd_message,

           'i' : cmd_userinfo,

           't' : cmd_test}



skype = SkypeApi()



print skype.send('GET SKYPEVERSION')

#print skype.send('GET USERSTATUS')



mainloop = gobject.MainLoop()

signal.signal(signal.SIGINT, sig_handler)

gobject.io_add_watch(sys.stdin,

                    gobject.IO_IN | gobject.IO_ERR | gobject.IO_HUP,

                    input_handler)

cmd_help(None)



sys.excepthook = excepthook

mainloop.run()

doublehp_
[quote=huomenta] I use it occasionally to skype-chat from ssh console. You still need skype application running in background, though. [/quote]

When you forget to start X or Skype itself locally, there are nice alternatives to VNC and X11_forward:
- xmove server (blind virtual X server, which still allow to attach the view after launch)
- Xvfb
huomenta_
[quote=doublehp]- xmove server (blind virtual X server, which still allow to attach the view after launch)
[/quote]
Thanks for info, I was not aware of this one.
huomenta_
So have you succeed with the script? I wonder if it works with different system/skype version (mine is quite antiquated 1.1.0.13, but the last which doesn't have that stupid sound blocking problem)
csant_
I tried running it, as I have been looking for a console way as well to get to skype - but the it fails with

CODE
No running API-capable Skype found


I am running skype 1.2.0.18, and have added manually the skype.conf file as described at http://share.skype.com/developer_zone/docu..._api_for_linux/ - it was not created by the .rpm I ran to install skype.

/c
doublehp_
I wont have time to try before several weeks. I thinkI will encontour the DBUS version problem mentionned in 'many' threads.
huomenta_
QUOTE(csant)
I tried running it, as I have been looking for a console way as well to get to skype - but the it fails with

QUOTE
No running API-capable Skype found


Are you sure you have skype running in the same session under the same user and you have dbus-0.23 installed?
huomenta_
to csant: Also, don't forget to restart skype and messagebus daemon after adding skype configuration.
csant_
QUOTE(huomenta)
Are you sure you have skype running in the same session under the same user and you have dbus-0.23 installed?


dbus 0.23.4 installed and running, and both skype, dbus-daemon and the python script run in the same session under the same user.

QUOTE(huomenta)
Also, don't forget to restart skype and messagebus daemon after adding skype configuration.


Done, and done.

QUOTE
API is supported in version 1.1.0.3 or greater.


As we are now at 1.2.0.18, did the API maybe change again? I have not looked through the API, and would not know if there were any changes at some time.

/c
huomenta_
QUOTE(csant)
I am running skype 1.2.0.18, and have added manually the skype.conf file as described at http://share.skype.com/developer_zone/docu..._api_for_linux/ - it was not created by the .rpm I ran to install skype.


It's strange that your rpm doesn't have skype.conf inside. IIRC, some rpm builds (suse?) are not API enabled. You can as well try tar.gz version.

QUOTE(csant)
As we are now at 1.2.0.18, did the API maybe change again? I have not looked through the API, and would not know if there were any changes at some time.


API did change, but this has nothing to do with the error you got. It means that script can't find skype via dbus interface...
csant_
Yes, this would have been the SuSE rpm. I grabbed the .tar.bz2 and copied over the skype.conf (which, btw was, except for some whitelines, identical to mine), restarted dbus-daemon, restarted skype - still no go :?
huomenta_
From skype changelog:
QUOTE
* feature: Skype API (not available on SuSE build)


You definitely should use binary from tar.bz2.
csant_
[quote=huomenta]From skype changelog:
[quote]* feature: Skype API (not available on SuSE build)[/quote]

You definitely should use binary from tar.bz2.[/quote]

Thanks for the hint. Yes, indeed - I replaced binaries, and it works smile.png Anybody knows the reason for the SuSE binary to be different from the others?

Now that I got it working, I'll take some time to fiddle a bit with the script wink.png As one of the goals to have a text-mode API was to get the skype IM in an IRC client (X-Chat in my case).

Thanks!
/c smile.png
csant_
One thing I couldn't quite figure out was whether on your bare CLI there is a way for having a conversation with somebody without the need to constantly enter `m <nick> <message>', but just `<message>' instead. It seemed to work as a reply to something, but then not consistently.

/c
huomenta_
If you enter something on command line which is not recognized as an internal command it will be passed to skype as is. This way you can learn how raw skype API works :) So, we still need some command character to mark continuation of the conversation. Micq, for instance, has "a <message>" command which sends message to the last person you sent message to. You may easily add similar thing to this script.
varunsound_
can anyone tell me if its possible to replace the text that was typed in the skype chat window after enter key is pressed, but before hte message is sent to the other end?.
Let me tell you for what purpose i plan to use the plugin:
I plan to use it for a south indian language called tamil , for which transliteration is available. Whenever the user types a text in english ,it can be converted to tamil.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.