EC2+DockerでMS Teamsのbot基盤を作る

## 今回作ったもの
<img width="908" alt="image1.png" src="https://qiita-image-store.s3.amazonaws.com/0/237361/51b46496-a12f-9606-5836-e0a4a30a73b3.png">
botに対してメンションするとそれぞれのbotがメッセージを返してくれます。
これをEC2上のコンテナで動作させます。

そもそものTeams botの作り方は下記のリンクを参照してください。
https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-overview
今回はbotからユーザーに対してメンションを行いたいのでWebhookは使わずNode.jsでコーディングします。

## 構成
![構成.png](https://qiita-image-store.s3.amazonaws.com/0/237361/0637581c-e067-2a79-9aaa-d803bb2ec207.png)

コンテナへのアクセスの前座としてnginxを置き、それぞれのbotコンテナ用にvirtualhostの設定を行うようにします。

## 実際のソースコード
コードの内容について語れる程の知識はないので実際に見てみてください。
下記のコードはイメージ画像にも使っている新垣結衣botのソースコードです。

```javascript:app.js

'use strict';

var express = require('express')
var app     = express();
var util    = require("util");
var builder = require("botbuilder");
var teams   = require("botbuilder-teams");

var appName     = 'yui-bot';
var appId       = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx';
var appPassword = 'xxxxxxxxxxxxxxxxxxxxxxx';

var connector = new teams.TeamsChatConnector({
  appId: appId,
  appPassword: appPassword
});



var inMemoryBotStorage = new builder.MemoryBotStorage();

var bot = new builder.UniversalBot(connector, function(session){

  var stripBotAtMentions = new teams.StripBotAtMentions();
  bot.use(stripBotAtMentions);

  var mentioneduserId = session.message.user.name;
  var conversationId = session.message.address.conversation.id;
  connector.fetchMembers(session.message.address.serviceUrl, conversationId, function (err, result) {
    if (err) {
      console.log('There is some error');
    }
    else {
      let user = {
        id: session.message.user.id,
        name: session.message.user.name
      };

      var mention = new teams.UserMention(user);
      var str = 'my name is yui aragaki';
      var msg = new teams.TeamsMessage(session).addEntity(mention).text(mention.text + ' ' + str );

      session.send(msg);
    }
  });
}).set('storage', inMemoryBotStorage);

app.post('/api/messages', connector.listen());
module.exports.connector = connector;

// Start our nodejs app
app.listen(process.env.PORT || 50000, function() {
    console.log('port is 50000');
});

```
特にメンションをする部分はドキュメントがほとんどなく苦労しました。
メンションしてきた相手のIDへ対してメンションを返すように処理を書いています。
応用すればチャネル内の全ユーザに対してメンションをすることもできます。

```javascript:app.js

//let user = {
  //id: session.message.user.id,
  //name: session.message.user.name
//};

//※全員にメンションするまで止まらない危険処理
for(let i in result){
  let user = {
    id: result[i].id,
    name: result[i].name
};

```

## botをdocker上で動作させる
とりあえず下記のようなディレクトリ構成でやっていきます。
> yui-bot/
> ├Dockerfile
> └src/
> 　├app.js
> 　└package.json

Dockerfileの内容も特に触れる事がありませんね。。。
今回はとりあえずcentos7のイメージを使っていますが、
より軽量なnodeのイメージを使う方がいいと思います。

```dockerfile:Dockerfile
FROM    centos:centos7

RUN     yum install -y epel-release
RUN     yum install -y nodejs npm

COPY /src/package.json /src/package.json
RUN cd /src;npm install --production
RUN cd /src;npm install npm-install-missing

COPY ./src/app.js /src/

EXPOSE  50000
CMD ["node", "/src/app.js"]
```

package.jsonはわざわざ記述するほどの内容でもなさそうなので割愛します。
ここまでできればあとはbuildしてrunしてやるだけです。

## nginxのconfを追加する
```conf:/etc/nginx/comf.d/yui-bot.conf

upstream yui-bot {
　　　　　　　　server <コンテナのIPアドレス>:50000;
}

server {

    listen       <EC2側で割り当てるポート番号> ssl;
    server_name  bottest.shibuyalabo.com;

    ssl on;
    ssl_certificate      /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key  /etc/nginx/ssl/privkey.pem;

    access_log  /var/log/nginx/access.log  main;

    location / {
        proxy_redirect  off;
        proxy_set_header Host  $host;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-Host  $host;
        proxy_set_header X-Forwarded-Server  $host;
        proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;

        proxy_pass http://yui-bot/;
    }
}
```
ここは上記にコンテナのIPアドレスと割り当てるポート番号を当てはめてやるだけです。
コンテナIPの調べ方は
>$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' <コンテナ名>

です。

## まとめ
slackのbotと比べるとかなり作るのに苦労する印象がありました。
botの基盤としては今回の構成はなかなかいい感じですね。
現在、bot側からメッセージを送るように改造しようとしていますが苦労は尽きません。
Node.jsがわかる方はぜひ自分からメッセージを送れるbotを作ってみてください。