2011年10月30日

プログラムからSkypeにメッセージを投稿する


日頃からボイス通話やチャットで公私ともどもお世話になっているSkypeですが、電話の着信のようにすぐに気づける特性を他の事に生かせないか…と思い、Skype Desktop APIを使ってプログラムからSkypeにメッセージを投稿する事に挑戦してみました。

早速Skypeのデベロッパーサイトにアクセスして情報を収集したところ、Windows環境であればSkype4COMを使うようです。幸いWindows版PHPでは標準でCOM関数が用意されているので、今回はこちらを使う事にしました。

ダウンロードしたzipファイルを展開すると、Skype4COM.dll, Skype4COM.chm, Skype4COM.msmが出力されるので、コマンドプロンプトから
regsvr32 Skype4COM.dll
と入力してライブラリを登録します。

プログラムはサンプルとして以下を用意しました。やっている事としてはチャット一覧を取得してその中のメッセージを出力し、"hello"とメッセージを投稿します。初回実行時はSkypeにプログラムからアクセスしていいか?のダイアログが表示されるので、「アクセスを許可」を選択します。
<?php
$skype = new COM('Skype4COM.Skype');
if (!$skype->client->isRunning()) {
    $skype->client()->start(true, true);
}
$skype->attach(5, true);
$chats = $skype->chats;
foreach ($chats as $chat) {
    if ($chat->topic == '') continue;
    echo $chat->name . ' > ' . $chat->friendlyName . ' > ' . $chat->topic . PHP_EOL;
   
    $messages = $chat->recentMessages;
    foreach ($messages as $message) {
        print_r(array(
            'id' => $message->id,
            'timestamp' => variant_date_to_timestamp($message->timestamp),
            'fromHandle' => $message->fromHandle,
            'fromDisplayName' => $message->fromDisplayName,
            'body' => $message->body,
            'chatName' => $message->chatName,
        ));
    }
   
    echo 'send message' . PHP_EOL;
    $chat->sendMessage('hello');
}

こんな感じで意外と簡単にメッセージ投稿までは実装できたのですが、ハマった所もいくつかありました。

  • 最新バージョンのSkypeだとプログラムの許可/拒否設定が無くなっている
     (他の設定もまるごと削除されますが)C:\Users\<username>\AppData\Roaming\Skypeフォルダ以下にあるSkype名フォルダを削除すると、プログラム許可/拒否設定も初期化されます。ちなみにそのフォルダにあるmain.dbなどはSQLiteファイルなので、SQLiteクライアントで設定テーブルを操作すればプログラム設定のみ初期化できるかもしれません。
  • チャットグループの名称が取得できない
     「グループを作成」からチャットグループを作成するとそれに名前をつける事ができますが、Skype APIだとトピック名しか取得できないようです。確認したところAPIのバグで公式サイトにも報告が上がってました。そのためプログラムから特定のチャットグループに投稿する場合、別途工夫が必要になります。
  • 一部戻り値はPHPのvariant_*関数で変換が必要
     $message->timestampなど一部プロパティではvariant型の値が返ってくるため、本来の値を取得するためにPHPのvariant_*関数で適宜変換を行う必要があります。
ここまでくれば後は投稿したいメッセージを取得する処理を別途実装して、タスクなどで定期実行すれば完成です。メッセージはテキストに加えてファイルも投稿できますし、イベント処理を実装すれば特定の応答に対して処理を行う…といった事も可能なようです。