Bot Framework で Slack の bot を構成する

Microsoft Bot Framework を利用した bot API を公開して、Slack をクライアントとして使えるように構成してみました。
その構築手順と注意点の簡単なメモを残しておきます。

基本的には、次の 2 つの記事をもとにしています。

(1) 環境設定

(2) bot を Web API として開発

  • テンプレートからプロジェクトを作成する
  • プロジェクトのプロパティで [アセンブリ名] を変更する
  • NuGet で Bot Framework を更新する

(3) Azure App Service に配置

  • Visual Studio から発行する

(4) Bot Framework サイトに登録

  • Web.config の appSettings にアカウント情報を設定するには、Azure Portal の [アプリケーション設定] を利用する
  • Web Chat を構成する
    • HTML に Web Chat を埋め込む
  • Slack bot を構成する
    • Slack の設定を追加するときに表示される手順の通りに進める

 

以下は注意点です。

(1) 開発環境における実行について

ローカルの開発環境においては、
Visual Studio で開始した bot API に Bot Framework Channel Emulator から接続することになりますが、
[デバッグなしで開始 (Ctrl+F5)] では 401 エラーとなります。
[デバッグの開始 (F5)] で実行すれば接続できます。

これは、Controller に BotAuthentication 属性が付けられていることによって、
デバッガーにアタッチされているときは認証不要になるためです。
したがって、開発環境では [デバッグの開始 (F5)] で実行しましょう。

(2) クライアント上でのテキストの表示について

テキストは既定で Markdown 形式です。したがって、記号などを使用するときは注意が必要です。
なお、reply.TextFormat を plain に設定しても、Web Chat では無効のようです。
また、reply.TextFormat を plain に設定しても、Slack ではなぜか * が _ と表示されます。

(3) Activity.Type について

Slack からは、activity.Type が ActivityTypes.Message でない要求が送られてくることがあります。
activity.Type の値により処理を分岐させないと、応答メッセージが重複して表示されてしまいます。

(4) URL の送信について

Slack から URL を送信すると、bot 側で受信するテキストでは、URL が < と > で括られます。

 

素因数分解 bot API のコードを示します。
全体のソースコードは、FactorizationBotApi (GitHub) にあります。

 

Slack で実行したときのスクリーン ショットです。

Factorization bot

 

表情分析 bot については、Bot Framework で Slack bot 構築メモ (Qiita)に書きました。

作成したサンプル
BotSample (GitHub)

バージョン情報
.NET Framework 4.6
Microsoft.Bot.Builder 3.3.0

参照
人工知能パーツ Microsoft Cognitive Services を使った表情分析アプリを作ろう! (Emotion API × Bot Framework 編)
Azure で Web 公開&お手軽 Web Chat を試す
Microsoft Cognitive Services & Bot Framework 概要
Bot Framework Overview

Bot Framework で Slack bot 構築メモ

カテゴリー: クラウド. タグ: , . Leave a Comment »

Azure Web ジョブでバッチを実行する

Azure Web ジョブでバッチを実行するための簡易的な作業手順と、タイムアウトなどの注意点について記述します。

まず、Azure Web ジョブを配置するまでの基本的な流れは次の通りです。

  • ストレージを作成する
  • Web App を作成する
  • Web ジョブを開発して配置する

これらについて、以下に詳細を書いていきます。

■ ストレージを作成する

Azure ポータルで、ストレージを 1 つ作成します。
厳密には、

  • ログを格納するためのストレージ (AzureWebJobsDashboard)
  • バッチが利用するストレージ (AzureWebJobsStorage)

の 2 種類なのですが、1 つのストレージに両方の役割を持たせてもかまいません。
また、後の手順で接続文字列を使うため、[キー] からコピーしておきます。

■ Web App を作成する

Azure のポータルで、Web App を作成します。
[アプリケーション設定] の [接続文字列] で、「AzureWebJobsDashboard」をキーとする設定を追加します。
これで、WebJobs ダッシュボードを利用できるようになります。

接続文字列

 

■ Web ジョブを開発して配置する

Visual Studio で、新規のプロジェクトを [Azure WebJob] のテンプレートから作成します。
App.config を開くと、接続文字列の設定が 2 種類あります。
この両方に、先ほどと同じ接続文字列を設定します。

接続文字列

以下、Web ジョブの開発の流れを簡単に書いておきます。
なお、今回作成したサンプルは TaskWebJob (GitHub) にあります。バッチ処理の題材として、素数を求めています

(1) 手動またはスケジュールで開始する場合
詳細は Web ジョブ SDK を使用して Azure テーブル ストレージを使用する方法などを参照。

  • メソッドに [NoAutomaticTrigger] を付ける
  • JobHost.Call メソッドで、そのメソッドを呼び出す
  • Azure WebJob として発行する
    • オンデマンド実行またはスケジュール実行を選択する
  • 実行するには、ポータルの Web App の [Web ジョブ] で実行する

(2) キューをトリガーとして開始する場合
詳細は Web ジョブ SDK を使用して Azure キュー ストレージを操作する方法などを参照。

  • メソッドの引数に [QueueTrigger] を付ける
  • JobHost.RunAndBlock メソッドを使う
  • Azure WebJob として発行する
    • 連続実行を選択する
  • 実行するには、指定したキューにメッセージを追加する
    • 引数を渡すこともできる

 

以上で、Azure Web ジョブにバッチを配置することができました。
さて、バッチを実際に実行してみると、タイムアウトしてしまうことがあります。
以下では、タイムアウトについて書いていきます。

■ 有料プランの場合

既定では Web App の [アプリケーション設定] の [常時接続] がオフに設定されており、
Web App (というより Kudu?) が 20 分ほどでタイムアウトしてしまいます。
[常時接続] をオンに設定すれば解決します。

■ 無料プランの場合

無料プランでは、[常時接続] をオンにできません。
バッチの実行がタイムアウトする原因は 2 つあります。

  • Web App のタイムアウト
    • タイムアウトは 20 分ほどです。
    • Kudu への要求が連続的にされていれば、タイムアウトは延長されます。
  • CPU 時間の制限
    • 実際の時間ではなく、CPU を使用した時間です。
    • 例えば、連続して 3 分使うと、Web App が停止します。

したがって、WebJobs ダッシュボードなどを表示したままにして、
かつ CPU 使用率の低いバッチであれば実行可能ということになります。

そこで、例えば Thread.Sleep メソッドをコードに含めるという方法があります。
Thread.Sleep などでスレッドを中断しながら実行すると、CPU 利用率を激減させることができます。

CPU 時間の使用量は [クォータ] で見ることができます。

クォータ

 

作成したサンプル
TaskWebJob (GitHub)

参照
Azure Web ジョブのリソース
Azure App Service に .NET Web ジョブを作成する
Web ジョブ SDK を使用して Azure キュー ストレージを操作する方法
Web ジョブ SDK を使用して Azure テーブル ストレージを使用する方法
Web ジョブでバックグラウンド タスクを実行する
Visual Studio を使用して Web ジョブを展開する

LINQ で素数を求める (C#)

カテゴリー: クラウド. タグ: , . Leave a Comment »

Azure Web App をファイル サーバーとして使う

Azure Web App を、単にファイルを置く場所として使う方法について書いていきます。
基本的には Web App を作成するだけですが、フォルダーやファイルの一覧を表示する機能についても紹介します。

Azure のダッシュボードで [App Service] の [Web App] を作成します。

image

Web App が作成されると、https://xxx.azurewebsites.net の形式の URL でサイトにアクセスできるようになります。

image

作成した Web App で [ツール] – [Visual Studio Online (プレビュー)] を表示し、[オン] に切り替えます。

image

[移動] をクリックすると、Visual Studio Online "Monaco" が表示されます。

image

基本的な設定はこれでもう終了で、
あとはこの画面の [wwwroot] の下にフォルダーやファイルを追加していくだけです。
PC 上のファイルをドラッグ アンド ドロップしても追加できます。
テキスト ファイルであれば直接編集できます。

例えば [wwwroot] の下に test.txt を置いたとすると、
https://xxx.azurewebsites.net/test.txt の URL でファイルにアクセスできます。

 

以下は、フォルダーやファイルの一覧を表示するための手順です。

まず、[wwwroot] の下の hostingstart.html を削除します。
次に [wwwroot] の下に [Web.config] という名前のファイルを追加して、次の内容をコピーします。

image

再びサイトにアクセスすれば、次のような画面になります。

image

フォルダーやファイルを追加してみます。

image

すると、一覧として表示されます。

image

 

ファイルを配置する方法としては、
上記のように Visual Studio Online "Monaco" を使うほか、FTP を使うことができます

ディスクの容量については、無料プランでは 1GB までです。
その他のプランの場合は、価格 – App Service を参照してください。

参照
ディレクトリの参照 <directoryBrowse>
Azure Web App に FTP でデプロイする

カテゴリー: クラウド. タグ: . Leave a Comment »

Azure Web App の仮想ディレクトリにサブドメインを設定する

前回は Azure の DNS ゾーンでカスタム ドメインを使うという記事を書きましたが、
今回はさらに、Azure Web App の仮想ディレクトリにサブドメインを対応させる方法について書きます。

つまり、1 つの独自ドメインと 1 つの Azure Web App (Shared 以上) があれば、
複数のサブドメインをホストできるということです。

方針としては、DNS ゾーンではワイルドカード ドメインを設定して、
Azure Web App で仮想ディレクトリとサブドメインの対応を設定します。
例えば abc.com が abccom.azurewebsites.net に対応しているとしたら、
app1.abc.com を abccom.azurewebsites.net/app1 に対応するようにします。

以下、設定手順です。

 

DNS ゾーンの設定

DNS ゾーンでワイルドカード ドメインを受け付けるように設定します。
[レコード セットの追加] で次の 3 つのレコードを登録します。

@ A xxx.xxx.xxx.xxx (IP アドレス)
awverify CNAME awverify.app-name.azurewebsites.net
* CNAME app-name.azurewebsites.net

前回のときに www としていた部分を * (ワイルドカード) に変更しただけです。

レコード セット

 

Web App の設定

Azure Web App の [アプリケーション設定] – [仮想アプリケーションとディレクトリ] で仮想ディレクトリを作成します。

仮想アプリケーションとディレクトリ

指定された仮想ディレクトリには、Web Deploy や FTP などを使って Web アプリケーションを配置しておきます。
(詳細不明ですが、Web アプリケーション プロジェクトに Application Insights を追加しておかないと、
配置後に実行時エラーになりました。)

Web を発行

 

次に [カスタム ドメインおよび SSL] で、利用可能にしたいサブドメインを追加します。
これで、サブドメインへのアクセスもこの Web App で受け付けられるようになります。
(ここでワイルドカード ドメインを登録する方法もあるでしょう。)

カスタム ドメインおよび SSL

 

このままだと、サブドメインへのアクセスがすべてルートのアプリケーションに流れてしまいます。
そこで www 以外のサブドメインと仮想ディレクトリを対応させるため、URL Rewrite を使います。
ルートの Web アプリケーションの Web.config に次の設定を追加します。

 

以上で、test1.saka-pon.net または saka-pon.net/test1 の URL で仮想アプリケーションにアクセスできるようになりました。

サブドメイン

 

前回: Azure の DNS ゾーンでカスタム ドメインを使う

参照
Creating Rewrite Rules for the URL Rewrite Module
URL Rewrite Module 2.0 Configuration Reference
URL 書き換えモジュール構成のリファレンス
Windows IIS/Azure WebサイトのURL Rewrite機能でURLを書き換える(基本編)

Azure Web App に FTP でデプロイする
Visual Studio から Windows Azure にデプロイする

Azure の DNS ゾーンでカスタム ドメインを使う

Microsoft Azure には DNS ゾーンの機能がありますが、管理ポータルの GUI で設定ができるようになりました。
(以前は PowerShell で設定していたようです)
以下では、DNS ゾーンを設定して、Azure Web App をカスタム ドメインで使うための手順を示します。

前提として、次のものを用意します。

  • Web サイトに設定したい独自ドメイン
  • Web サイトの実体となる Azure Web App
    • この時点では app-name.azurewebsites.net の形式でのみアクセスできる
    • 独自ドメインを利用するには、価格レベルは Shared 以上が必要

この Azure Web App に、abc.com および www.abc.com の形式のドメインでアクセスできることを目標とします。

 

Azure 管理ポータルの [DNS ゾーンの作成] で、[名前] にはドメインを入力します。

DNS ゾーンの作成

これで DNS ゾーンが作成されます。
次に [レコード セットの追加] で、次の 3 つを登録します。

@ A xxx.xxx.xxx.xxx (IP アドレス)
awverify CNAME awverify.app-name.azurewebsites.net
www CNAME app-name.azurewebsites.net

Azure Web App の IP アドレスは、後述する [外部ドメインの使用] を開くと表示されます。
また、awverify は Azure Web App を利用する場合の固有のもので、作業者が同一であるかを確認するために必要です。
この設定がないと、後述する [外部ドメインの使用] でエラーとなります。

[名前] を空欄にすれば、自動的に @ (ルート) になります。

レコード セットの追加

レコード セットを追加すると、次の画面のようになります。
SOA レコードと NS レコードは最初から登録されています。

レコード セット

 

上の画面には「ネーム サーバー」がいくつか表示されています。
これらをドメイン管理サービスの DNS サーバーとして設定します。
次に示すのはデータ・ジャパンの管理サイトです。

DNS サーバー

基本的にはすぐにネットワークに設定が反映されますが、かなり時間がかかることもあるようです。
設定が反映されているかどうかは、Dig web interface などで確認できます。

Dig web interface

 

最後に、Azure 管理ポータルに戻り、Azure Web App の [カスタム ドメインおよび SSL] – [外部ドメインの使用] で
利用したいドメインを割り当てれば完了です。
ここでは、ドメインのルートのほか、www 付きのドメインも指定しています。

カスタム ドメインおよび SSL

ちなみに、DNS ゾーンで www のレコードを

www CNAME saka-pon.net

と設定した場合は、この [外部ドメインの使用] で www 付きのドメインを割り当てようとしたときにエラーとなりました。
(おそらく awverify が理由)

 

次回: Azure Web App の仮想ディレクトリにサブドメインを設定する

参照
Azure DNS の使用を開始する
Azure App Service のカスタム ドメイン名の構成
Windows Azure Web サイトに独自ドメイン ( カスタムドメイン ) を設定し使用する
Dig web interface

Azure Web App に FTP でデプロイする

Azure Web App にアプリケーションをデプロイする方法については、
これまでは主に、Visual Studio Team Services との CIGitHub との CI など、
ソース管理システムから自動的にデプロイする方法について書いてきましたが、
ソース管理システムと連携させない方法としては主に FTP を利用することになります。

FTP を利用するためには、Azure の管理ポータルで、
作成済みの Web App に対して [設定] – [デプロイ資格情報] と進んで、ユーザー名とパスワードを入力して [保存] をクリックします。

image

注意点として、ユーザー名はグローバルに一意でなければなりません (他の開発者と同じ名前を使用できません)。
また、サブスクリプション内のすべての Web App にもこのアカウントが設定されます。

これで、FTP を使うための準備ができました。
FTP の URI とユーザー名は Web App のトップに表示されています。

image

 

[FTPS ホスト名] の部分をコピーして、エクスプローラーでアクセスします。
ユーザー名もコピーできます。

image

これで、FTPS でアクセスできました。

image

あとは、wwwroot にアプリケーションをコピーすればデプロイは完了です。

image

 

また、Web App の [設定] – [アプリケーション設定] – [仮想アプリケーションとディレクトリ] で仮想アプリケーションを設定できます。
つまり、wwwroot 以外の物理ディレクトリも URL に関連付けることができます。

image

FTP でデプロイ:

image

ブラウザーでアクセス:

image

ちなみに、Monaco にアクセスすると既定の URL は /dev/wwwroot/ ですが、
ここを書き換えると wwwroot 以外も編集できるようになります。

image

 

ディスクの容量については、Free プランでは 1GB までです。
その他のプランの場合は、価格 – App Service を参照してください。

カテゴリー: クラウド. タグ: , . 2 Comments »

Azure Table の検索条件を LINQ で指定する

Azure Storage の SDK (Windows Azure Storage) を利用して .NET のクライアントから Table のデータを取得する際に、
検索条件を指定しようとすると、通常の実装では次のようなコードになり少し複雑です。
この例では、フィルター条件を 2 つ指定しています。


var query = new TableQuery<Person>()
    .Where(TableQuery.CombineFilters(
        TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "2015"),
        TableOperators.And,
        TableQuery.GenerateFilterConditionForInt("Age", QueryComparisons.LessThan, 20)));

var result = PeopleTable.ExecuteQuery(query).ToArray();


ここで、Person  は TableEntity を継承したクラスで、PeopleTable は CloudTable 型のオブジェクトです。

結局、上記の Where メソッドに渡されるのは、

(PartitionKey eq ‘2015’) and (Age lt 20)

という文字列になります。
これなら string.Format メソッドでもよいのではないのかという気もしますが、
プログラミングのミスを防ぐためには、フィルターや射影などの検索条件は LINQ で指定したいところです。

検索条件を LINQ で指定する方法として TableServiceContext クラスを使う方法もあるようですが、
現在は Obsolete 属性が指定されており、非推奨となっています。

とはいえ、自力で IQueryable<T> を実装するのも骨が折れるので、
ここでは簡易的に、TableQuery<T> の拡張メソッドとして Select および Where メソッドを実装していきます。
ラムダ式で指定された検索条件を式ツリーとして受け取って解析し、動的にクエリを生成します。

このような TableHelper クラスを実装することで、Azure Table の検索条件を LINQ で指定できるようになります。
ただし、文字列の不等式については、String クラスの演算子として不等号が定義されていないため、

p.LastName >= "W"

と書くことができず、

p.LastName.CompareTo("W") >= 0

のようにせざるを得ませんでした。

 

作成したサンプル
ExpressionsConsole (GitHub)

バージョン情報
Windows Azure Storage 6.0.0

参照
Windows Azure Storage
Expression<TDelegate> クラス
TableQuery<TElement> Class

Windows Azure Storage Extensions
テーブル サービスに対する LINQ クエリの作成 (古い形式)
TableServiceContext Class (古い形式)