SiriっぽいTeamsアプリを作ってみる


はじめに

仕事にしても何にしても使えるものは使っておくに限る。
最近はリモートワークの影響でteamsを使い始めたので、これも使っておきたい。
どうせなら勤怠とかの自動化に使おうとも思ったが、敷居が高そうなので途中から計画変更してSiriにした。
だって、Siriっぽいもの作った事ありますって言っておけば何かしら仕事もらえるんじゃなかろうか。

結果


何も分からない俺のSiri

Teams API

TeamsにはTeamsに蓄えられた情報を扱うためのRest APIが用意されている。

これらのRestAPIを使ってタブやボットなどのアプリを作成する。
尚、APIで使用可能なリソースは下記種類がある。

リソース メソッド
team 各自のチームの一覧表示、すべてのチームの一覧表示、作成、読み取り、更新、削除、複製、アーカイブ、アーカイブ解除
group メンバーの追加、 メンバーの削除、所有者の追加、 所有者の削除、ファイルの取得、ノートブックの取得、プランの取得、予定表の取得
channel 一覧表示、作成、読み取り、更新、削除
teamsTab 一覧表示、作成、読み取り、更新、削除
teamsApp 一覧表示、公開、更新、削除
teamsAppInstallation 一覧表示、インストール、アップグレード、削除
chatMessage 送信
call 応答、拒否、リダイレクト、ミュート、ミュート解除、画面共有ロールの変更、参加者の一覧表示、参加者の招待
schedule 作成または置換、取得、共有
schedulingGroup 作成、一覧表示、取得、置換、削除
shift 作成、一覧表示、取得、置換、削除
timeOff 作成、一覧表示、取得、置換、削除
timeOffReason 作成、一覧表示、取得、置換、削除

2020-06-27現在では.NET, JS, Pythonでサンプルが用意されている。

参考になるサンプルを探す

サンプルを眺めていると、nodejs配下に50.teams-messaging-extensions-searchなるジャストなものがある。
このサンプルはなにをするものかと言うと、アプリケーションコマンドにnodeのパッケージ名を入力すると詳細を教えてくれる。と言うもの。
アプリケーションコマンドが何かと言うと、


ココ

これを元にsiriを作っていきたい。まずはREADMEに沿って環境を整える。

必要なパッケージを入れる。

nodejsのサンプルなので、必要なのはnodejs。特にバージョンの指定がないのでstableで良いと思う。
自分の端末にはもともと入っていたので特に変えてない。

nodejs入れたらinstall

npm install

ngrokの導入

READMEを読むとngrokを利用するらしいので、早速本家から落としてインストールする。尚ngrokに関しては有志の強い方が記事を書いてくださっているので、そちらを参照してほしい。
この記事でngrokに関する有用な情報はない。だって今回初めて触った。

インストール方法はngrokに登録してソフトをダウンロードして展開するだけ。
展開したらexeが出てくるのでパス通す。特に困る事はないハズ。

公式サイトの指示通りngrokをアカウントに接続させたら完了。


とりあえずヘルプ出してみた

あとは実行するだけ

ngrok http -host-header=rewrite 3978

Azureの準備

teamsを使う以上、Azureを使う。で、Azureの準備。

Bot Framework registration resourceの手順通りに進める。
Azure Portalを開き、リソースを作成する。

botと打つとBot Channel Registrationの候補が現れるのでこれを選ぶ。(公式手順ではWeb App Botでもできるらしい)

一礼して作成

下記設定で作成ボタンをクリック。するとデプロイまで進んでくれる。Azure賢い。

項目 設定値
ボットハンドル miyatama-worksheet-hater
サブスクリプション 従量課金(デフォルト)
リソース miyatama-teams-learning(新規作成)
場所 米国西部(かっこいいから)
価格レベル S1
メッセージングエンドポイント
ApplicationInsight オン
ApplicationInsightの場所 East US
MicrosoftアプリIDとパスワード 自動生成

で、しばらく放っておくと完了の通知が来る。


や っ た ぜ

すべてのリソースを開くと2つリソースが追加されている(botとApplication Insight)。Botの方をクリック。

設定をクリック

右側ペインを下にスクロースるとMicrosoft App IDの項目があるので、管理のリンクをクリック

新しいクライアントシークレットをクリック

説明を入力して追加をクリック

ちゃんと追加される。この時にキーをコピーしてファイルに保存しておく。大事な事なのでもう一回書いておく。
シークレットをコピーしてファイルに保存しておく


ちゃんと追加出来ててえらい。

Azureでteams使える様にする。

Azure Portalで発行したAppIDとパスワードを.envファイルに追記する。

項目 設定値
MicrosoftAppId 後述
MicrosoftAppPassword 前述のシークレット発行時にコピーした文字列 

AppIDはbotの設定に記載されている

これで準備ができたので早速動かす。

npm start

teams用の設定を行う

teamsAppManifest/manifest.jsonを編集する。

  • idへMicrosoft App IDを設定
  • composeExtensions.botIdへMicrosoft App IDを設定

その後、teamsAppManifest内のファイルをZipに固める(ファイル名はmanifest.zip)。
大事な事なのでもう一度書こう。
teamsAppManifest内のファイルをZipに固める

teamsからカスタムアプリのアップロードを行う。アプリのアイコンをクリックし、ペインをスクロールするとカスタムアプリをアップロードの項目が出てくるのでクリック。

アップロードで先ほど作成したzipファイルを選択する。成功した場合はアプリが画面上に表示される。


アイコン変だけど気にしない

アプリをクリックして追加を行う

早速よびだす


だめでした。

これはなぜかと言うと下記図で言う所のAzureとngrokが連携できていないから。

と言うわけでngrokで用意したendpointをAzureに教えてあげないといけない。
まずはココを参考にchannelを作成する。
次に、ngrokeのendpointをAzureに教える。ngrokのendpointはngrok http -host-header-rewrite 3978で実行した時の結果を参照してほしい。
万が一gitbashで実行してしまった場合はwinptyを使うなりコマンドプロンプトで実行するなりなんなりで対処してほしい。


上記例だとhttps://0a3496160a1a.ngrok.io/api/messages

Azure PortalからBotのリソースを開き、設定を表示する。すると、メッセージングのエンドポイントなる項目があるので、ここにngrokのendpointを張り付ける。

もう一回試す


や っ た ぜ

Siriっぽくする

サンプル実行できただけでもかなりお腹いっぱいなのだが、元来の目的であるSiriの作成に入る。
Siriと言えば、すみません。よくわかりません。だ。異論もあるだろうか、私のイメージではそうだ。

botのコードを見てもらうと分かる通り、検索した結果を返すだけだ。これをSiri化するのは簡単だ。
固定ですみません。よくわかりません。を返せばよいだけだ。

中の仕様がよく分からない方はここを見てほしい。めちゃくちゃ親切に書いてある。
書き変えた(?)後のコードは以下の通り。

const axios = require('axios');
const { TeamsActivityHandler, CardFactory } = require('botbuilder');

class TeamsMessagingExtensionsSearchBot extends TeamsActivityHandler {
    async handleTeamsMessagingExtensionQuery(context, query) {
        const attachments = [];
        const heroCard = CardFactory.heroCard("result");
        const preview = CardFactory.heroCard("すみません。よくわかりませんでした。");
        const attachment = { ...heroCard, preview };
        attachments.push(attachment);

        return {
            composeExtension: {
                type: 'result',
                attachmentLayout: 'list',
                attachments: attachments
            }
        };
    }
}

module.exports.TeamsMessagingExtensionsSearchBot = TeamsMessagingExtensionsSearchBot;

早速試す


や っ た ぜ

ふりかえり

冒頭にも記載した通り、最初は勤怠の自動化をやろうかと思って色んなサンプルを眺めたりしていた。
が、途中でめんどくさくなって、何でもいいからアウトプットしておく運びとなった。
まぁ、ここまでやっておけば後は自然言語処理でも賢さ演出するぐらい誰でもできるし、何とかなるだろう。
teamsの記事を何個か書く予定なので無駄にはならないハズだ。

何よりも、勉強の方法を議論する位なら勉強した方が早い。