AnsibleでVagrant上にHubot+Skype botな環境を作成

============================================

## 環境

- Vagrant
- Ansible
- CentOS 6.5
- Skype for Linux >= 4.3 (4.1, 4.2はSkypeのDesktop API廃止の仕様変更により正常動作しない可能性が高いです)
- Skype4Py 
- Python >= 2.6

## Overview

![skype-logo-feb_2012_rgb_500.png](https://qiita-image-store.s3.amazonaws.com/0/47983/da7bb850-ee61-5f22-a3c3-9e73a39ea28f.png "skype-logo-feb_2012_rgb_500.png")

AnsibleでVagrant上にHubot+Skype botな環境を作成します。
Slackが流行ってますが、まだSkypeがメインの環境もあると思うので...
Skype Desktop API廃止による制限についても触れてあります。


## Install

### with Ansible

構築手順はplaybookとして公開してあります。

https://github.com/shufo/ansible-skype-hubot

- インストール

```
git clone git@github.com:shufo/ansible-skype-hubot.git
cd ansible-skype-hubot
vim vars/main.yml
```

vars/main.ymlにbot化させたいSkypeユーザ名とパスワード、あと立ち上げ時に一時的にVNC接続を使うのでx11vncのパスワードを設定し

```vars/main.yml
skype_username: Skypeユーザ名 
skype_password: パスワード
x11vnc_password: password
```

```
vagrant up
```

でansible provisionerが走り、Vagrant仮想マシン上にSkype+Hubotな環境が出来ます。
※ インストールの最後にVNC接続してSkype APIアクセスを許可する箇所のみ手動になります。

```
Install Finished! Please connect your VNC viewer to port 5900 on target host, and accept Skype public API access(check remember).
```

とメッセージが出たらMacなら[Chicken VNC](http://sourceforge.net/projects/cotvnc/)等のVNCビューワで`192.168.50.11`にVNC接続し、Skype APIの利用許可ダイアログで「記憶する」にチェックを入れHubotからのAPI使用を許可します。接続する際のパスワードは`x11vnc_password`に設定した値です。

- 確認

チャット上で

```
hubot ping
```

と発言し、正常動作していれば

```
> PONG
```

とbotが反応します。

- botが反応しない場合

Skypeが利用しているdbusが死んでいるかSkypeプロセスがハング、もしくはHubot自体が死んでいるので

```
service skype restart
supervisorctl restart hubot
```

で、SkypeやHubotを再起動してください。


- リモートに構築する場合

`ansible_hosts`を編集し

```
default ansible_ssh_host=127.0.0.1 ansible_ssh_port=22
```

任意のホストのIPアドレスとportに置き換え、playbookを実行してください。

```
ansible-playbook site.yml -i ansible_hosts 
```

構築の際にi686用パッケージとか色々入れてるので、まっさらな環境じゃない場合一応playbookを確認の上実行してください。

### 手動

以下手動でのインストール手順です。

- Skype for Linuxのダウンロード&インストール

```bash
cd /opt
curl -L -O http://download.skype.com/linux/skype-4.3.0.37.tar.bz2
tar jxvf skype-4.3.0.37.tar.bz2
ln -s skype-4.3.0.37 skype
```

- 依存パッケージのインストール

```bash
$ yum install glibc.i686 nss-softokn-freebl.i686 alsa-lib.i686 libXv.i686 \
 libXScrnSaver.i686 libtiff.i686 glib2.i686 libSM.i686 libXrender.i686 fontconfig.i686 \
 pulseaudio-libs.i686 alsa-plugins-pulseaudio.i686 libQtDBus.so.4 libQtWebKit.so.4 \
 Xvfb python-devel python-setuptools x11vnc ipa-gothic-fonts

$ easy_install pip
$ pip install Skype4Py
```

- 起動スクリプトの作成

```bash
curl -L -o /etc/init.d/skype https://gist.githubusercontent.com/shufo/70d8ca05305f8848196b/raw/144870dda3a3fe320563c732d4b846c5e17297cb/skype
useradd skype -s /sbin/nologin
mkdir /var/db/skype /var/run/skype/ /var/log/skype/
chown skype:skype /var/db/skype /var/run/skype/ /var/log/skype/
chmod +x /etc/init.d/skype

vi /etc/init.d/skype # 以下をbot化するアカウントのUSERNAME/PASSWORDに書き換える
    USERNAME=<username>
    PASSWORD=<password>

```

- SELinuxの無効化

```
setenforce 0
```

- machine-idの生成

```bash
dbus-uuidgen > /var/lib/dbus/machine-id
```

- フォントのインストール

```bash
yum install ipa-gothic-fonts
```

- 起動

```
service skype start
chkconfig skype --add
chkconfig skype on
```

###  Hubot

- Hubotのインストール

```bash
yum install npm redis
```

```
npm install -g hubot coffee-script yo generator-hubot
```

```bash
$ mkdir -p /opt/hubot
$ cd /opt/hubot
$ yo hubot

[?] ==========================================================================
We're constantly looking for ways to make yo better! 
May we anonymously report usage statistics to improve the tool over time? 
More info: https://github.com/yeoman/insight & http://yeoman.io
==========================================================================: Yes
                     _____________________________  
                    /                             \ 
   //\              |      Extracting input for    |
  ////\    _____    |   self-replication process   |
 //////\  /_____\   \                             / 
 ======= |[^_/\_]|   /----------------------------  
  |   | _|___@@__|__                                
  +===+/  ///     \_\                               
   | |_\ /// HUBOT/\\                             
   |___/\//      /  \\                            
         \      /   +---+                            
          \____/    |   |                            
           | //|    +===+                            
            \//      |xx|                            

[?] Owner:  <>
[?] Bot name: hubot
[?] Description: A simple helpful robot for your Company
[?] Bot adapter: (campfire) skype
```

- 動作確認

```bash
service redis start
export DISPLAY=:20
export XAUTHORITY=/var/run/skype/Xauthority
./bin/hubot -a skype
```

チャットで`hubot ping`と打てば死活確認が出来ます。

```
日付： 2014/11/02 時刻： 21:51 送信者： ****
> hubot ping

日付： 2014/11/02 時刻： 21:51 送信者： shufo
> PONG
```

- 永続化

```
pip install supervisor
echo_supervisord_conf > /etc/supervisord.conf
```

```/etc/supervisord.conf
〜中略〜
[program:hubot]
directory=/opt/hubot
command= /opt/hubot/bin/hubot -a skype
```

- supervisord起動

```
supervisord -n
```

- x11vncを起動

```
/usr/bin/x11vnc -display :20 -xauth /var/run/skype/Xauthority
```

- VNC接続する

Windowsなら[UltraVNC](http://www.uvnc.com/)、Macなら[Chicken VNC](http://sourceforge.net/projects/cotvnc/)があります。これらのソフトで上で起動したx11vncに5900番ポートで接続します。

- SkypeのAPIリクエストを許可する

```
env DISPLAY=:20 XAUTHORITY=/var/run/skype/Xauthority python
>>>import Skype4Py
>>>skype = Skype4Py.Skype(Transport='x11')
>>>skype.Attach() # ここで許可を求めるポップアップが先ほど開いたVNCに出るので「記憶する」にチェックを入れ許可する。
>>>chat = skype.CreateChatWith('skypeID')
>>>chat.SendMessage('test')
```

## Bot運用時の注意点

- Skypeが頻繁に死ぬ

負荷が高くなると結構な頻度でdbusが死んでレスポンスが返らなくなります。
というか負荷が高まらなくてもハングします...定期的にcron等で再起動してあげましょう。

```
0 4 * * * /etc/init.d/skype restart
```

- Botも死ぬ

Botも長い間起動してると突然死んだり反応が悪くなるので定期的に再起動しましょう。

```
0 4 * * * /usr/bin/supervisord restart hubot
```

## Skype Desktop APIの廃止

2013年12月にSkype Desktop APIが廃止されたため、2014以降新規に作成されたグループで一部Skype APIを使うことが出来ません。
つまり **Desktop API廃止以降に作成されたグループでは実質Hubotが使えません** 。
いつのアップデートからデフォルトのグループがクラウド対応グループになったかは分かりませんが、以下の方法でAPIを使えるかどうか確認出来ます。

- Skype APIを使えるかどうかの確認方法。

`/get name`をSkypeのグループチャットで叩き

```
/get name
name=#shufo/$fa4e0c236b3c0e7a
```

のようなフォーマットの場合P2PベースのグループなのでAPIは使えます。

```
/get name
name=19:f14000bfa456406abdf2f245b22eb5bb@thread.skype
```

このようなフォーマットの場合クラウドベースのグループなので残念ながらAPIは使えません。

参照: [skype4py doesnt play well with API from skype version skype-ubuntu-lucid_4.3.0.37-1_i386.deb · Issue #34 · awahlig/skype4py](https://github.com/awahlig/skype4py/issues/34)