かずきのBlog@hatena

日本マイクロソフトに勤めています。このブログは個人ブログなので、ここに書いている内容は個人的な意見で会社の公式見解ではない点にご注意ください。好きなものは XAML と C# 。苦手なものは型の無い言語です。

Google アシスタントのエージェントを Azure Functions + C# で作る

Dialogflow v2 に対応した C# の SDK が実はこっそりあります。 1.0.0-beta2 (2018/1104 現在) なので正式版ではないですが、きっと近いうちに出ると思う!!

以下のパッケージを入れましょう。

www.nuget.org

Visual Studio で追加するときはプレリリースパッケージのチェックを入れてから検索しましょう。

入れたらあとは JSON をパースしたりするだけです。ただ、JSON.NET ではなく Google の提供している JSON のパーサーを使います。Google.Protobuf の名前空間にあります。

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Google.Cloud.Dialogflow.V2;
using Google.Protobuf;
using static Google.Cloud.Dialogflow.V2.Intent.Types.Message.Types;
using static Google.Cloud.Dialogflow.V2.Intent.Types;
using Microsoft.Azure.WebJobs.Hosting;

namespace HogeHoge
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequest req,
            ILogger log)
        {
            var parser = new JsonParser(JsonParser.Settings.Default.WithIgnoreUnknownFields(true)); // パーサーを作る
            var webhookRequest = parser.Parse<WebhookRequest>(await req.ReadAsStringAsync()); // パースする

            // 例えば Webhook がすべてのパラメータがそろった状態で呼び出されたかを確認したり
            if (!webhookRequest.QueryResult.AllRequiredParamsPresent)
            {
                log.LogInformation("This request does not have all required parameters");
                return new OkResult();
            }
            // パラメーターをとって色々したり
            var requestedParameters = webhookRequest.QueryResult.Parameters;

            // 戻りは、WebhookResponse を返せば OK
            var webhookResponse = new WebhookResponse();
            webhookResponse.FulfillmentText = $"応答内容";
            // 結果の JSON も Google.Protobuf を使ってシリアライズ
            return new ProtcolBufJsonResult(webhookResponse, JsonFormatter.Default);
        }
    }

    // Google.Protobuf を使ってシリアライズする IActionResult の実装
    public class ProtcolBufJsonResult : IActionResult
    {
        private readonly object _obj;
        private readonly JsonFormatter _formatter;

        public ProtcolBufJsonResult(object obj, JsonFormatter formatter)
        {
            _obj = obj;
            _formatter = formatter;
        }

        public async Task ExecuteResultAsync(ActionContext context)
        {
            context.HttpContext.Response.Headers.Add("Content-Type", new Microsoft.Extensions.Primitives.StringValues("application/json; charset=utf-8"));
            var stringWriter = new StringWriter();
            _formatter.WriteValue(stringWriter, _obj);
            await context.HttpContext.Response.WriteAsync(stringWriter.ToString());
        }
    }
}

あとはデプロイして関数のエンドポイントを Dialogflow のフルフィルメントに設定して完了。

早く正式版でないかなぁ。