ターミナルからSkype -- Skysh

最近ターミナルからSkypeをしたいなーと思うことがよくありました。検索してみるといくつかターミナルからSkypeを実行するものが見つかりますが、いまいち自分に合うものがなかったので、Skype4PyというSkypeAPIのPythonラッパーを使って、ターミナルからSkypeが出来るSkyshというものを作りました。Mac OS Xでしか動作確認してないですが,Skype4PyとPythonが使える環境なら使えると思います(ansi colorを使ってるのでwindowsだと厳しいかもしれませんが…,っていうかreadlineが使えないか?)。


ダウンロード

ソースはgithubにあります。
・GitHub - mmisono/Skysh: Skype in Terminal

必要な物:
・Skype4Py
・termcolor

以上の2つはダウンロードして、 % python setup.py install とすればインストールされます。また、SkypeAPIはあくまでも起動中のSkypeクライアントに対して操作をおこなうのでSkypeの起動が必要です。
実際にはSkype4PyにはSkypeを起動させる機能がありますが、これをMac OS Xで実行するとエラーになります。これは既知の問題のようで(http://forum.skype.com/topic/357681-skype4py-runtimeerror-with-patch/)、いずれは直るかもしれません。
(2010/4/10 追記)
上のフォーラムの最後に書いてあるとおり、

--- Skype4Py.orig/api/darwin.py 2009-09-25 06:13:41.000000000 -0400
+++ Skype4Py/api/darwin.py 2010-03-20 18:19:18.000000000 -0400
@@ -297,6 +297,7 @@
self.center = CFDistributedNotificationCenter()
self.is_available = False
self.client_id = -1
+ self.thread_started = False

def run(self):
self.logger.info('thread started')
@@ -363,6 +364,16 @@
time.sleep(1.0)
return self.is_available

+ def start(self):
+ """
+ Start the thread associated with this API object.
+ Ensure that the call is made no more than once,
+ to avoid raising a RuntimeError.
+ """
+ if not self.thread_started:
+ super(SkypeAPI, self).start()
+ self.thread_started = True
+
def startup(self, minimized, nosplash):
if not self.is_running():
from subprocess import Popen

として、skyshの開発版にすると(なんかエラーが出てしまいますが)一応skysh実行時にSkypeが起動してなければ起動できるようになりました。

実行方法

% python skysh.py

で実行できます。
プロンプトには、(開始していれば)現在のチャット名、自分のユーザー名が表示されます。

使い方

基本的に入力はチャットメッセージとして送信されます。しかし、以下の入力はコマンドとして処理されます。コマンドはタブで補完ができます。


add 現在のチャットにユーザーを追加します。
bookmark 現在のチャットをブックマークします。
bookmarks ブックマークの一覧を表示し、指定したチャットに切り替えます。
chat 指定したユーザー(複数指定可)とチャットを開始します。
exit 終了します。
friends コンタクトリストのメンバーを表示します。
kick 現在のチャットからユーザーを追放します。
ls アクティブチャットの一覧を表示します。
members 現在のチャットのメンバーを表示します。
mood [Message] ムードテキストを表示するか、指定されたメッセージに変更します。
open 最近のチャットメッセージの中のURLを表示し、指定されたURLを開きます。
profile ユーザーのプロファイルを表示します。
recent 最近のチャット一覧を表示し、指定したチャットに切り替えます。
search ユーザーを検索します。
status 現在のステータスの表示と変更をします。
unbookmark 現在のチャットをアンブックマークします。


あとhelpでこのメッセージが表示されます。
とりあえず主な使いかたは chat hoge としてhogeとチャットするをすることだと思います。ただし、たまにこのchatコマンドが上手くいかないことがあります。
個人的には、recent で最近のチャットの一覧を表示させてそこからチャットを切り替えるのがいいと思います。

注意点

Skype4Pyの問題なのかどうかは分かりませんがいくつかのコマンドは正しく動作せず例外を発生します。
・ls
lsコマンドは、実際にはSkype4PyのActiveChatsというものの一覧を表示します。自分はActiveChats = 現在チャットウィンドウで開いているチャット だと思っているのですが、このActiveChatsを参照しようとするとエラーになります。ということでこのコマンドは現在使えないようです(例外を捕獲して何もしません)。
(2010/4/11 追記)
v0.0.3にてlsをすればちゃんと現在チャットウィンドウにあるチャット一覧を表示し、切り替えられるようになりました。
...以下技術的な話
そもそもチャットウィンドウにいくつチャットがあってもActiveChats.Countが1なのはおかしいなと思っていましたが、よくよく調べてみるとActiveChats.Nameに全てのチャット名が含まれてることが分かりました。どう考えてもバグだと思います(もしかしてMacだけ?)が、ActiveChats.Name.split(' ')とすればアクティブチャットの名前のリストが取得できます。Skype4Py.skypeインスタンスにはChat(Name)メソッドがあるので、self.skype.Chat(ActiveChats.Name.split(' ')[0])とかやればアクティブチャットの一番目のチャットインスタンスが得られるはず…なんですが98%失敗してします。ソースを見ると分かりますが、チャットインスタンスを生成した後にそのチャットが正しいかチェックしているんですが、そこでエラーが起きています。ということなので、Chat()メソッドを使わずに、Skype4Py.chat.Chat(self.skype,ActiveChats.Name.split(' ')[0])と直接インスタンスを生成するようにしたら無事にインスタンスが得られ、lsコマンドが機能するようになりました。まぁ正しいかのチェック処理をしてない訳なんですが多分大丈夫だと思います。


・add,kick
これらのコマンドを実行すると、処理は完了するものの何故か例外を発生します。とりあえずskyshでは捕獲してpassしてます。


・コマンドのtypo
コマンドをtypoするとそのままチャットメッセージとして送信されてしまうので気をつけてください(タブで補完するといいと思います)。もしメッセージの先頭でコマンド名を送信したいのであれば \ でエスケープしてください。


また、Macではそのままだとsegmentation faultします。こちらを参考にして下さい。さらに、Macデフォルトのpythonだと日本語が上手く扱えないようなので、もしそうならばMacportsや本家サイトから別のをダウンロードしてみて下さい。

あとはたまに表示が崩れることがあります。まぁ仕様です(ぉ。というか相手のメッセージを受信した時に自分の現在の行の上に出力させる方法は、誰がどうみても邪道なやり方をしているので何かいい方法があったら教えてください…。

その他(感想など)

とりあえず普通にチャットできるレベルにはなっていると思います。とりあえず他に追加したい機能は、
・ユーザーをコンタクトリストに追加する
・ファイルを送受信する
・チャットタイトルを変更する
ですが、やり方がよく分かりません(できない?)。あと色がなんかいまいちだから256色にしたいなぁ。とはいうものの自分はSkypeのヘビーユーザーじゃないからこれでいいかな。あまり動作確認とかはしてないので多分おかしなところがいろいろあるかと思いますが、何かあったらメールかここにコメント頂けるとうれしいです。

作成にあったって参考にしたサイト

・http://blog.cohtan.org/2009/02/terminalskypeskypeshpy.html
これを見てSkype4Py × cmd.Cmd で作りました。
・Skype4Py
・http://74.125.153.132/search?q=cache:s0RyBuD20q8J:d.hatena.ne.jp/kakurasan/20090310/p1+python+url+%E9%96%8B%E3%81%8F&cd=1&hl=ja&ct=clnk&gl=jp
・Regex for URL extracting - Python