コード例 #1
0
        public static async Task <IActionResult> LongTimeFunction(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            [OrchestrationClient] DurableOrchestrationClient client,
            Microsoft.Azure.WebJobs.ExecutionContext context,
            ILogger log)
        {
            var cekResponse = new CEKResponse();
            var clovaClient = new ClovaClient();
            var cekRequest  = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);

            switch (cekRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
            {
                // UserId をインスタンス ID として新しい関数を実行
                await client.StartNewAsync(nameof(LongTimeOrchestrationFunction), cekRequest.Session.User.UserId, context.FunctionAppDirectory);

                cekResponse.AddText("時間のかかる処理を実行しました。結果はLINEでお知らせします。");
                break;
            }

            case RequestType.IntentRequest:
            default:
            {
                // インテントリクエスト他は特に用意しない
                cekResponse.AddText("すみません。よくわかりませんでした。");
                break;
            }
            }

            return(new OkObjectResult(cekResponse));
        }
コード例 #2
0
        private static async Task <IActionResult> ExecuteLaunchRequestAsync(CEKRequest request, CloudTable locationLogs, AppConfiguration config)
        {
            var response = new CEKResponse();

            response.AddText("こんにちは。私の持ち主のいる場所を確認するね。");

            var tableResult = await locationLogs.ExecuteAsync(TableOperation.Retrieve <LocationLog>(nameof(LocationLog), request.Session.User.UserId));

            if (tableResult == null || tableResult.HttpStatusCode != 200)
            {
                response.AddText($"ごめんなさい。場所がわかりませんでした。持ち主にLINEで聞いてみるから、また後で聞いてね。");
                await AskCurrentLocationAsync(request, config);

                return(new OkObjectResult(response));
            }

            var locationLog = (LocationLog)tableResult.Result;
            var isOldLog    = locationLog.Timestamp <= DateTimeOffset.UtcNow - TimeSpan.FromHours(2);

            if (isOldLog)
            {
                await AskCurrentLocationAsync(request, config);
            }
            response.AddText($"{locationLog.Name ?? locationLog.Address}にいます。{(isOldLog ? "でも少し前の場所みたいだね。もう一度聞いてみるから、また後で聞いてね。。" : "")}");
            return(new OkObjectResult(response));
        }
コード例 #3
0
        private static async Task <CEKResponse> HandleRequestAsync(CEKRequest request)
        {
            var response = new CEKResponse();

            switch (request.Request.Type)
            {
            case RequestType.LaunchRequest:
                await HandleLaunchRequestAsync(request, response);

                break;

            case RequestType.IntentRequest:
                await HandleIntentRequestAsync(request, response);

                break;

            case RequestType.SessionEndedRequest:
                await HandleSessionEndedRequestAsync(request, response);

                break;

            default:
                break;
            }
            return(response);
        }
        /// <summary>
        /// Handle request and respond to client device.
        /// </summary>
        /// <param name="signatureCEK"></param>
        /// <param name="body"></param>
        /// <param name="skipValidation"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task <CEKResponse> RespondAsync(string signatureCEK, Stream body, bool skipValidation = false, CancellationToken cancellationToken = default)
        {
            Request = await GetRequest(signatureCEK, body, skipValidation);

            Response = new CEKResponse(defaultLang: DefaultLang);

            switch (Request.Request.Type)
            {
            case RequestType.LaunchRequest:
                await OnLaunchRequestAsync(Request.Session, cancellationToken);

                break;

            case RequestType.IntentRequest:
                await OnIntentRequestAsync(Request.Request.Intent, Request.Session, cancellationToken);

                break;

            case RequestType.EventRequest:
                await OnEventRequestAsync(Request.Request.Event, Request.Session, cancellationToken);

                break;

            case RequestType.SessionEndedRequest:
                await OnSessionEndedRequestAsync(Request.Session, cancellationToken);

                break;

            default:
                await OnUnrecognizedRequestAsync(Request, cancellationToken);

                break;
            }
            return(Response);
        }
コード例 #5
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            CEKResponse response = null;;

            if (req.Headers.TryGetValue("SignatureCEK", out var signature))
            {
                var client  = new ClovaClient();
                var request = await client.GetRequest(signature, req.Body);

                // IntentRequestのみここにくる
                if (request.Request.Type == RequestType.IntentRequest)
                {
                    // メイン処理
                    var result = IntentHandler.Handle(request.Request.Intent.Name);
                    response = result.GetClovaResponse();
                }
                else
                {
                    // エラー
                    response = new CEKResponse();
                    response.AddText("よくわかりませんでしたが、たぶんラッキーな1日になると思いますよ。");
                    response.ShouldEndSession = true;
                }
            }
            else
            {
                // エラー
                response = new CEKResponse();
                response.AddText("よくわかりませんでしたが、きっと大丈夫ですよ。");
                response.ShouldEndSession = true;
            }
            return(new OkObjectResult(response));
        }
コード例 #6
0
        public async Task <IActionResult> Post()
        {
            var request = await client.GetRequest(Request.Headers["SignatureCEK"], Request.Body, true);

            var response = new CEKResponse();

            // get session information by specifying default value in case no session information
            var mySessionValue = request.GetSessionAttribute("mySessionKey", "defaultValue");

            // adding session information
            response.AddSession("mySessionKey", "mySessionValue");

            switch (request.Request.Type)
            {
            case RequestType.LaunchRequest:
                // Single Text Reply
                response.AddText("Welcome to CEK", Lang.En);
                response.ShouldEndSession = false;
                break;

            case RequestType.SessionEndedRequest:
                response.AddText("Good bye!", Lang.En);
                response.ShouldEndSession = true;
                break;

            case RequestType.IntentRequest:
                switch (request.Request.Intent.Name)
                {
                case "Clova.YesIntent":
                    // Add single URL Response and Text Reprompt
                    response.AddUrl("https://clova-common.line-scdn.net/dice/rolling_dice_sound.mp3");
                    response.AddRepromptText("Tell me something, please", Lang.En);
                    response.ShouldEndSession = false;
                    break;

                case "Clova.NoIntent":
                    // Add Brief and Verbose as SpeechSet
                    response.AddBriefText("Brief explain.", Lang.En);
                    response.AddVerboseText("Detail explain 1.", Lang.En);
                    response.AddVerboseText("Detail explain 2.", Lang.En);
                    response.AddVerboseUrl("https://clova-common.line-scdn.net/dice/rolling_dice_sound.mp3");
                    response.ShouldEndSession = false;
                    break;

                case "Clova.GuideIntent":
                    // Add multiple Reposonses and Reprompts
                    response.AddText("Sure!", Lang.En);
                    response.AddUrl("https://clova-common.line-scdn.net/dice/rolling_dice_sound.mp3");
                    response.AddText("Let me explain how to use it!", Lang.En);
                    response.AddRepromptText("Did you understand?", Lang.En);
                    response.AddRepromptText("Now tell me what you want.", Lang.En);
                    response.AddRepromptUrl("https://clova-common.line-scdn.net/dice/rolling_dice_sound.mp3");
                    response.ShouldEndSession = false;
                    break;
                }
                break;
            }
            return(new OkObjectResult(response));
        }
コード例 #7
0
        private static async Task <IActionResult> ExecuteLaunchRequestAsync(CEKRequest request, CloudTable locationLogs, AppConfiguration config)
        {
            var response           = new CEKResponse();
            var taskForSettings    = MessagingChatSettings.GetSettingsByUserIdAsync(locationLogs, request.Session.User.UserId);
            var taskForLocationLog = LocationLog.GetLocationLogByUserIdAsync(locationLogs, request.Session.User.UserId);
            await Task.WhenAll(taskForSettings, taskForLocationLog);

            var settings = taskForSettings.Result ?? new MessagingChatSettings {
                RowKey = request.Session.User.UserId
            };
            var locationLog = taskForLocationLog.Result;

            try
            {
                if (!settings.IsLineFrend)
                {
                    response.AddText(ClovaMessages.GetAddingLineFrendMessage());
                    return(new OkObjectResult(response));
                }

                AddHistory(settings);
                response.AddText(ClovaMessages.GetGuideMessage(settings.YourName));
                if (locationLog == null || !DateTimeOffsetUtils.IsToday(locationLog.Timestamp))
                {
                    // データが無い
                    response.AddText(ClovaMessages.GetNoLogMessage(settings.YourName));
                    await AskCurrentLocationAsync(request, config, settings);

                    return(new OkObjectResult(response));
                }

                if (DateTimeOffsetUtils.IsBefore(locationLog.Timestamp, TimeSpan.Parse(config.Cek.IsBeforeThreshold ?? Clova.IsBeforeThresholdDefaultValue)))
                {
                    // 古いデータ
                    response.AddText(ClovaMessages.GetOldLocationMessage(settings.YourName, locationLog));
                    await AskCurrentLocationAsync(request, config, settings);

                    return(new OkObjectResult(response));
                }

                // データがある
                response.AddText(ClovaMessages.GetLocationMessage(settings.YourName, locationLog));
                if (!string.IsNullOrEmpty(locationLog.Comment))
                {
                    response.AddText(ClovaMessages.GetCommentMessage(settings.YourName, locationLog));
                }
                else if (!string.IsNullOrEmpty(locationLog.AudioCommentUrl))
                {
                    response.AddText(ClovaMessages.GetVoiceMessagePrefixMessage(settings.YourName));
                    response.AddUrl(locationLog.AudioCommentUrl);
                }

                return(new OkObjectResult(response));
            }
            finally
            {
                await locationLogs.ExecuteAsync(TableOperation.InsertOrReplace(settings));
            }
        }
コード例 #8
0
        public void TypeSafeSessionAttributeSetNullTest()
        {
            var response = new CEKResponse();

            response.AddSession("dummy", "dummy");
            response.SetSessionAttributesFrom(null);
            Assert.Empty(response.SessionAttributes);
        }
コード例 #9
0
ファイル: Clova.cs プロジェクト: runceel/mangaclovalab
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            // リクエストのボディの JSON を検証して C# のクラスに変換。
            var clovaClient  = new ClovaClient();
            var clovaRequest = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);

            // 返事を作成
            var clovaResponse = new CEKResponse();

            switch (clovaRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
                // 起動時の処理
                clovaResponse.AddText("こんにちは。何を占ってほしいですか?");
                clovaResponse.AddText("健康運と恋愛運と金運を占えるよ。");
                clovaResponse.AddText("例えば健康運を占ってって聞いてみてね。");
                clovaResponse.ShouldEndSession = false;     // スキルを終わらせないように設定する
                break;

            case RequestType.SessionEndedRequest:
                // 終了時の処理。今回は無し。case 自体不要だけど説明用に今回は追加してる
                break;

            case RequestType.IntentRequest:
                // インテントの処理
                switch (clovaRequest.Request.Intent.Name)
                {
                case "FortuneTellingIntent":
                    // 占いのインテント
                    // 占い対象がスロットに無い場合は総合運勢を占う
                    var fortune = "総合運勢";
                    if (clovaRequest.Request.Intent.Slots.TryGetValue("FortuneSlot", out var fortuneSlot))
                    {
                        // 占いの対象がある場合は、それをスロットから取得する
                        fortune = fortuneSlot.Value;
                    }

                    // 占いの結果を返す
                    var result = new[] { "大吉", "中吉", "小吉", "末吉" }[new Random().Next(4)];
                    clovaResponse.AddText($"{fortune} は {result} です。");
                    break;

                default:
                    // 認識できなかったインテント
                    clovaResponse.AddText("こめんなさい。よくわかりませんでした。例えば健康運を占ってと言うと健康運を占います。");
                    clovaResponse.ShouldEndSession = false;         // スキルを終わらせないように設定する
                    break;
                }
                break;
            }

            // レスポンスとして作成した返事の内容を返す
            return(new OkObjectResult(clovaResponse));
        }
コード例 #10
0
        public CEKResponse GetClovaResponse()
        {
            var res = new CEKResponse()
            {
                ShouldEndSession = ShouldEndSession
            };

            messages.ForEach(m => res.AddText(m));
            return(res);
        }
コード例 #11
0
        public async Task <IActionResult> Post()
        {
            CEKRequest request = await client.GetRequest(
                Request.Headers["SignatureCEK"],
                Request.Body
                );

            var response = new CEKResponse();

            switch (request.Request.Type)
            {
            case RequestType.LaunchRequest:
            {
                response.AddText("こんにちは!これ食べれるニャンボットです。人間の食べ物を入力すると、これは猫が食べて大丈夫かどうかを答えるよ");
                response.ShouldEndSession = false;
                break;
            }

            case RequestType.SessionEndedRequest:
            {
                response.AddText("またね~");
                break;
            }

            case RequestType.IntentRequest:
            {
                switch (request.Request.Intent.Name)
                {
                case "CatIntent":             // "パン"
                {
                    // 食べれるものが渡ってくるので何か処理をする TODO!
                    response.ShouldEndSession = false;
                    break;
                }

                case "ChomadoIntent":             // "ちょまど"
                {
                    response.AddText("ちょまどさん、さすがオトナです!素敵!すばらしい!松屋!");
                    response.ShouldEndSession = false;
                    break;
                }

                case "Clova.GuideIntent":
                {
                    response.AddText("パン、と言ってみてください。");
                    response.ShouldEndSession = false;
                    break;
                }
                }
                break;
            }
            }
            return(new OkObjectResult(true));
        }
コード例 #12
0
        public void TypeSafeSessionAttributeSetTest()
        {
            var sessionValue = new OrderInfo
            {
                MenuName   = "Pizza",
                OrderCount = 10,
            };
            var response = new CEKResponse();

            response.SetSessionAttributesFrom(sessionValue);
            Assert.Equal("Pizza", (string)response.SessionAttributes["MenuName"]);
            Assert.Equal(10, (long)response.SessionAttributes["OrderCount"]);
        }
        public static async Task <IActionResult> Line([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ExecutionContext context, ILogger log)
        {
            var client     = new ClovaClient();
            var cekRequest = await client.GetRequest(req.Headers["SignatureCEK"], req.Body);

            var cekResponse = new CEKResponse();

            switch (cekRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
                cekResponse.AddText(IntroductionMessage);
                cekResponse.ShouldEndSession = false;
                break;

            case RequestType.IntentRequest:
            {
                var r = await HandleIntentAsync(cekRequest.Request.Intent.Name);

                cekResponse.AddText(r.ResponseMessage);

                // 最新記事が見つかったので LINE にプッシュ通知する
                if (r.Blog != null)
                {
                    var config = new ConfigurationBuilder()
                                 .SetBasePath(context.FunctionAppDirectory)
                                 .AddJsonFile("local.settings.json", true)
                                 .AddEnvironmentVariables()
                                 .Build();

                    var secret = config.GetValue <string>("LineMessagingApiSecret");

                    var messagingClient = new LineMessagingClient(secret);
                    await messagingClient.PushMessageAsync(
                        to : cekRequest.Session.User.UserId,
                        messages : new List <ISendMessage>
                        {
                            new TextMessage($"ちょまどさんの最新記事はこちら!"),
                            new TextMessage($@"タイトル『{r.Blog.Title}』
{r.Blog.Url}"),
                        });
                }
            }
            break;
            }

            return(new OkObjectResult(cekResponse));
        }
コード例 #14
0
        public async Task <IActionResult> Post()
        {
            var client     = new ClovaClient();
            var cekRequest = await client.GetRequest(
                Request.Headers["SignatureCEK"],
                Request.Body);

            var cekResponse = new CEKResponse();

            switch (cekRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
            {
                cekResponse.AddText("スキル設定画面で設定したパソコンのアプリケーションを起動します。");
                cekResponse.ShouldEndSession = false;
                break;
            }

            case RequestType.IntentRequest:
            {
                switch (cekRequest.Request.Intent.Name)
                {
                case "LaunchAppIntent":
                    var name = cekRequest.Request.Intent.Slots["name"];
                    if (SchemeMap.ContainsKey(name.Value))
                    {
                        var ignore = InvokeAppAsync(cekRequest.Session.User.AccessToken, SchemeMap[name.Value]);
                        cekResponse.AddText($"{name.Value}を起動しました。");
                    }
                    break;
                }
                break;
            }

            case RequestType.SessionEndedRequest:
            {
                break;
            }
            }

            return(new OkObjectResult(cekResponse));
        }
コード例 #15
0
 /// <summary>
 /// Clovaを無音再生で待機させます。
 /// </summary>
 /// <param name="cekResponse"></param>
 private static void KeepClovaWaiting(CEKResponse cekResponse)
 {
     // 無音mp3の再生指示
     cekResponse.Response.Directives.Add(new Directive()
     {
         Header = new DirectiveHeader()
         {
             Namespace = DirectiveHeaderNamespace.AudioPlayer,
             Name      = DirectiveHeaderName.Play
         },
         Payload = new AudioPlayPayload
         {
             AudioItem = new AudioItem
             {
                 AudioItemId   = "silent-audio",
                 TitleText     = "Durable Session",
                 TitleSubText1 = "Azure Functions",
                 TitleSubText2 = "Durable Functions",
                 Stream        = new AudioStreamInfoObject
                 {
                     BeginAtInMilliseconds = 0,
                     ProgressReport        = new ProgressReport
                     {
                         ProgressReportDelayInMilliseconds    = null,
                         ProgressReportIntervalInMilliseconds = null,
                         ProgressReportPositionInMilliseconds = null
                     },
                     Url         = Consts.SilentAudioFileUri,
                     UrlPlayable = true
                 }
             },
             PlayBehavior = AudioPlayBehavior.REPLACE_ALL,
             Source       = new Source
             {
                 Name = "Microsoft Azure"
             }
         }
     });
     //cekResponse.ShouldEndSession = false;
 }
コード例 #16
0
        public async Task <IActionResult> Post()
        {
            CEKRequest request = await _client.GetRequest(
                Request.Headers["SignatureCEK"],
                Request.Body
                );

            var response = new CEKResponse();

            try
            {
                switch (request.Request.Type)
                {
                case RequestType.LaunchRequest:
                {
                    response.AddText("こんにちは!これ食べれるニャンボットです。人間の食べ物を入力すると、これは猫が食べて大丈夫かどうかを答えるよ");
                    response.ShouldEndSession = false;
                    break;
                }

                case RequestType.SessionEndedRequest:
                {
                    response.AddText("またね~");
                    break;
                }

                case RequestType.IntentRequest:
                {
                    switch (request.Request.Intent.Name)
                    {
                    case "HelloIntent":
                    {
                        response.AddText("こんにちは!これ食べれるニャンボットだよ!");
                        response.ShouldEndSession = false;
                        break;
                    }

                    case "ChomadoIntent":             // "ちょまど"
                    {
                        response.AddText("ちょまどさん、さすがオトナです!素敵!すばらしい!松屋!");
                        response.ShouldEndSession = false;
                        break;
                    }

                    case "Clova.GuideIntent":
                    {
                        response.AddText("パン、と言ってみてください。");
                        response.ShouldEndSession = false;
                        break;
                    }

                    case "CatIntent":             // "パン"
                    {
                        var food = request.Request.Intent.Slots.FirstOrDefault().Value.Value;
                        // 食べれるものが渡ってくるので何か処理をする TODO!
                        response.AddText(text: $"{food}の話ですね?");

                        // QnA から答えを取り出す
                        var client = _httpClientFactory.CreateClient();
                        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("EndpointKey", _configuration.GetValue <string>("EndpointKey"));
                        var content          = new StringContent(JsonConvert.SerializeObject(new { question = food }), Encoding.UTF8, "application/json");
                        var qnaMakerResponse = await client.PostAsync(
                            $"{_configuration.GetValue<string>("Hostname")}/knowledgebases/{_configuration.GetValue<string>("KbId")}/generateAnswer",
                            content);

                        qnaMakerResponse.EnsureSuccessStatusCode();
                        var answers = await qnaMakerResponse.Content.ReadAsAsync <QnAMakerResponse>();

                        // LINE messaging に push
                        string accessToken = _configuration.GetValue <string>("LINEMessaginAPIKey");
                        string myUserId    = _configuration.GetValue <string>("myUserID");

                        var answer = answers.Answers?.FirstOrDefault()?.AnswerText;
                        if (!string.IsNullOrEmpty(answer))
                        {
                            response.AddText(answer.Contains("OK") ? $"{food}は食べられます。詳細を LINE に送ります。" : $"{food}は食べられません。");
                            var messagingClient = new LineMessagingClient(channelAccessToken: accessToken);
                            await messagingClient.PushMessageAsync(
                                // to: request.Session.User.UserId,
                                to : myUserId,
                                messages : new List <ISendMessage>
                                    {
                                        new TextMessage($"{food}"),
                                        new TextMessage($"解説はこれだよ"),
                                        new TextMessage(answer),
                                    }
                                );
                        }
                        else
                        {
                            response.AddText($"{food}が見つかりませんでした。");
                        }
                        break;
                    }
                    }
                    break;
                }
                }
            }
            catch (Exception ex)
            {
                response.AddText(ex.ToString());
            }

            return(new OkObjectResult(response));
        }
コード例 #17
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ExecutionContext context, ILogger log)
        {
            //リクエストボディのJSONを検証してC#のクラスに変換
            var clovaRequest = await new ClovaClient().GetRequest(req.Headers["SignatureCEK"], req.Body);
            //返事を作成
            var clovaResponse = new CEKResponse();

            switch (clovaRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
                //起動時の処理
                clovaResponse.AddText(IntroductionMessage);
                clovaResponse.ShouldEndSession = false;
                break;

            case RequestType.SessionEndedRequest:
                //終了時の処理
                clovaResponse.AddText(SessionEndedMessege);
                break;

            case RequestType.IntentRequest:
                // インテントの処理
                switch (clovaRequest.Request.Intent.Name)
                {
                case MenuIntent:
                    // インテント
                    var timeZone = "";
                    if (clovaRequest.Request.Intent.Slots != null && clovaRequest.Request.Intent.Slots.TryGetValue(SlotTimeZone, out var timeZoneSlot))
                    {
                        // 対象がある場合は、スロットから取得する
                        timeZone = timeZoneSlot.Value;
                    }
                    var menu = "ごはん";
                    // メニューを朝、昼、夜、で分けてランダムで取得しています。
                    if (timeZone.Equals("朝"))
                    {
                        menu = new[] { "卵焼き", "目玉焼き", "おにぎり", "ホットドッグ", "ヨーグルト" }[new Random().Next(5)];
                    }
                    else if (timeZone.Equals("昼"))
                    {
                        menu = new[] { "ラーメン", "ざるそば", "たこ焼き", "豚ヒレカツでふわふわカツ丼", "焼きそばナポリタン" }[new Random().Next(5)];
                    }
                    else if (timeZone.Equals("夜"))
                    {
                        menu = new[] { "オムライス", "山椒たっぷりの讃岐うどん", "ドライカレー", "じゃがいもステーキのタルタルソースがけ", "チキン南蛮弁当" }[new Random().Next(5)];
                    }
                    else
                    {
                        clovaResponse.AddText(NoSlotMessege);
                        clovaResponse.ShouldEndSession = false;
                        break;
                    }
                    // LINE にプッシュ通知する
                    var config = new ConfigurationBuilder()
                                 .SetBasePath(context.FunctionAppDirectory)
                                 .AddJsonFile("local.settings.json", true)
                                 .AddEnvironmentVariables()
                                 .Build();

                    var secret          = config.GetValue <string>("LineMessagingApiSecret");
                    var messagingClient = new LineMessagingClient(secret);

                    await messagingClient.PushMessageAsync(
                        to : clovaRequest.Session.User.UserId,
                        messages : new List <ISendMessage>
                    {
                        new TextMessage($"今日あなたが食べたい{timeZone}ご飯は {menu} です。"),
                    });

                    clovaResponse.AddText($"今日あなたが食べたい{timeZone}ご飯は {menu} です。");


                    break;

                default:
                    // 認識できなかったインテント
                    clovaResponse.AddText(NoSlotMessege);
                    clovaResponse.ShouldEndSession = false;     // スキルを終わらせないように設定する
                    break;
                }
                break;
            }
            // レスポンスとして作成した返事の内容を返す
            return(new OkObjectResult(clovaResponse));
        }
コード例 #18
0
 private static Task HandleSessionEndedRequestAsync(CEKRequest request, CEKResponse response)
 {
     response.AddText(Messages.GoodbayMessage);
     return(Task.CompletedTask);
 }
コード例 #19
0
 private static Task HandleLaunchRequestAsync(CEKRequest request, CEKResponse response)
 {
     response.ShouldEndSession = false;
     response.AddText(Messages.WelcomeMessage);
     return(Task.CompletedTask);
 }
コード例 #20
0
        private static async Task <Task> HandleIntentRequestAsync(CEKRequest request, CEKResponse response)
        {
            void fillSlotIfExist(string slotName, ref string word)
            {
                if (request.Request.Intent.Slots?.ContainsKey(slotName) ?? false)
                {
                    word = request.Request.Intent.Slots[slotName].Value;
                }
            }

            switch (request.Request.Intent.Name)
            {
            case IntentNames.DefaultIntent:
            {
                string word = null;
                fillSlotIfExist(SlotNames.NamamugiNamagomeNamatamago, ref word);
                fillSlotIfExist(SlotNames.SyusyaSentaku, ref word);

                // 滑舌オーケー
                if (!string.IsNullOrEmpty(word))
                {
                    // LINE messaging に投げる
                    var messagingClient = new LineMessagingClient(channelAccessToken: Keys.token);
                    await messagingClient.PushMessageAsync(
                        to : Keys.userId,
                        messages : new List <ISendMessage>
                        {
                            new TextMessage(string.Format(Messages.LineCongratsMessage, word)),
                        }
                        );

                    // Clova に喋らせる
                    response.ShouldEndSession = true;
                    response.AddText(Messages.GenerateCongratsMessage(word));
                }
                // 滑舌ダメです
                else
                {
                    var messagingClient = new LineMessagingClient(channelAccessToken: Keys.token);
                    await messagingClient.PushMessageAsync(
                        to : Keys.userId,
                        messages : new List <ISendMessage>
                        {
                            new TextMessage(Messages.LineWrongMessage),
                        }
                        );

                    response.ShouldEndSession = false;
                    response.AddText(Messages.WrongPronunciationMessage);
                }

                break;
            }

            default:
                // noop
                break;
            }

            return(Task.CompletedTask);
        }
コード例 #21
0
        public async Task <IActionResult> Post()
        {
            CEKRequest request = await _client.GetRequest(
                Request.Headers["SignatureCEK"],
                Request.Body
                );

            var response = new CEKResponse();

            switch (request.Request.Type)
            {
            case RequestType.LaunchRequest:
            {
                response.AddText("こんにちは!これ食べれるニャンボットです。人間の食べ物を入力すると、これは猫が食べて大丈夫かどうかを答えるよ");
                response.ShouldEndSession = false;
                break;
            }

            case RequestType.SessionEndedRequest:
            {
                response.AddText("またね~");
                break;
            }

            case RequestType.IntentRequest:
            {
                switch (request.Request.Intent.Name)
                {
                case "CatIntent":             // "パン"
                {
                    var food = request.Request.Intent.Slots.FirstOrDefault().Value.Value;
                    // 食べれるものが渡ってくるので何か処理をする TODO!
                    response.AddText(text: $"{food}の話ですか?");

                    // LINE messaging に push
                    string accessToken = _configuration.GetValue <string>("LINEMessaginAPIKey");

                    var messagingClient = new LineMessagingClient(channelAccessToken: accessToken);
                    await messagingClient.PushMessageAsync(
                        to : request.Session.User.UserId,
                        messages : new List <ISendMessage>
                            {
                                new TextMessage($"{food}"),
                            }
                        );

                    response.ShouldEndSession = false;
                    break;
                }

                case "ChomadoIntent":             // "ちょまど"
                {
                    response.AddText("ちょまどさん、さすがオトナです!素敵!すばらしい!松屋!");
                    response.ShouldEndSession = false;
                    break;
                }

                case "Clova.GuideIntent":
                {
                    response.AddText("パン、と言ってみてください。");
                    response.ShouldEndSession = false;
                    break;
                }
                }
                break;
            }
            }
            return(new OkObjectResult(response));
        }
コード例 #22
0
        public static async Task <IActionResult> CEKEndpoint(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            [OrchestrationClient] DurableOrchestrationClient client,
            ExecutionContext context,
            ILogger log)
        {
            var cekResponse = new CEKResponse();
            var clovaClient = new ClovaClient();
            var cekRequest  = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);

            var userId = cekRequest.Session.User.UserId;

            log.LogInformation(cekRequest.Request.Type.ToString());

            switch (cekRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
            {
                cekResponse.AddText("腹話術を開始します。準備はいいですか?");
                cekResponse.ShouldEndSession = false;
                break;
            }

            case RequestType.IntentRequest:
            {
                switch (cekRequest.Request.Intent.Name)
                {
                case "Clova.GuideIntent":
                    cekResponse.AddText("LINEに入力をした内容をしゃべります。。。" +
                                        "LINEでセリフを事前にテンプレートとして登録したり、" +
                                        "英語や韓国語への翻訳モードに変更することもできます。" +
                                        "準備はいいですか?");
                    cekResponse.ShouldEndSession = false;
                    break;

                case "Clova.YesIntent":
                case "ReadyIntent":
                    // 友だち追加チェック
                    try
                    {
                        await messagingClient.GetUserProfileAsync(userId);
                    }
                    catch
                    {
                        cekResponse.AddText("連携するLINEアカウントが友だち追加されていません。" +
                                            "Clovaアプリの本スキルのページから、連携するLINEアカウントを友だち追加してください。");
                        break;
                    }

                    await client.StartNewAsync(nameof(WaitForLineInput), userId, null);

                    cekResponse.AddText("LINEに入力をした内容をしゃべります。好きな内容をLINEから送ってね。");

                    // 無音無限ループに入る
                    KeepClovaWaiting(cekResponse);
                    break;

                case "Clova.PauseIntent":
                case "PauseIntent":
                    // 無限ループ中の一時停止指示に対し、スキル終了をする
                    await client.TerminateAsync(userId, "intent");

                    cekResponse.AddText("腹話術を終了します。");
                    break;

                case "Clova.NoIntent":
                case "Clova.CancelIntent":
                case "NotReadyIntent":
                    // オーケストレーターが起動していないなら終了
                {
                    var status = await client.GetStatusAsync(userId);

                    if (status?.RuntimeStatus != OrchestrationRuntimeStatus.ContinuedAsNew &&
                        status?.RuntimeStatus != OrchestrationRuntimeStatus.Pending &&
                        status?.RuntimeStatus != OrchestrationRuntimeStatus.Running)
                    {
                        cekResponse.AddText("腹話術を終了します。");
                    }
                    else
                    {
                        KeepClovaWaiting(cekResponse);
                    }
                    break;
                }

                case "Clova.FallbackIntent":
                case "NoActionIntent":              // 「ね」が準備OKのインテントに振り分けられてしまったので別途インテントに定義しておく
                default:
                    // オーケストレーター起動中なら無音無限ループ
                    // これを行わないとClovaが通常の返しをしてしまう
                {
                    var status = await client.GetStatusAsync(userId);

                    if (status?.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew ||
                        status?.RuntimeStatus == OrchestrationRuntimeStatus.Pending ||
                        status?.RuntimeStatus == OrchestrationRuntimeStatus.Running)
                    {
                        KeepClovaWaiting(cekResponse);
                    }
                    break;
                }
                }
                break;
            }

            case RequestType.EventRequest:
            {
                // オーディオイベントの制御
                // Clovaでのオーディオ再生が終わった際に呼び出される
                if (cekRequest.Request.Event.Namespace == "AudioPlayer")
                {
                    if (cekRequest.Request.Event.Name == "PlayFinished")
                    {
                        // 終わっていなければ無音再生リクエストを繰り返す
                        var status = await client.GetStatusAsync(userId);

                        if (status.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew ||
                            status.RuntimeStatus == OrchestrationRuntimeStatus.Pending ||
                            status.RuntimeStatus == OrchestrationRuntimeStatus.Running)
                        {
                            KeepClovaWaiting(cekResponse);
                        }
                        else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Completed)
                        {
                            // 完了していた場合(=LINEからの外部イベント処理が実行された場合)
                            // 再度セッション継続
                            KeepClovaWaiting(cekResponse);

                            var translationStatus = await client.GetStatusAsync("translation_" + userId);

                            if (translationStatus?.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew ||
                                translationStatus?.RuntimeStatus == OrchestrationRuntimeStatus.Running ||
                                translationStatus?.RuntimeStatus == OrchestrationRuntimeStatus.Pending)
                            {
                                var lang = translationStatus.CustomStatus.ToString();

                                // ユーザー入力
                                var body        = new object[] { new { Text = status.Output.ToObject <string>() } };
                                var requestBody = JsonConvert.SerializeObject(body);

                                // 翻訳
                                using (var request = new HttpRequestMessage())
                                {
                                    request.Method     = HttpMethod.Post;
                                    request.RequestUri = new Uri(Consts.AzureCognitiveTranslatorEndpoint + lang);
                                    request.Content    = new StringContent(requestBody, Encoding.UTF8, "application/json");
                                    request.Headers.Add("Ocp-Apim-Subscription-Key", Consts.AzureCognitiveTranslatorKey);
                                    var response = await httpClient.SendAsync(request);

                                    // 結果の取得とデシリアライズ
                                    var jsonResponse = await response.Content.ReadAsStringAsync();

                                    var result = JsonConvert.DeserializeObject <List <TranslatorResult> >(jsonResponse);

                                    // 入力内容を話させる
                                    cekResponse.AddText(result[0].Translations[0].Text,
                                                        lang switch
                                        {
                                            "en" => Lang.En,
                                            "ko" => Lang.Ko,
                                            "ja" => Lang.Ja,
                                            _ => throw new InvalidOperationException()
                                        });
                                }
コード例 #23
0
        public static async Task <IActionResult> Line(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ExecutionContext context,
            ILogger log)
        {
            var client     = new ClovaClient();
            var cekRequest = await client.GetRequest(req.Headers["SignatureCEK"], req.Body);

            var cekResponse = new CEKResponse();

            switch (cekRequest.Request.Type)
            {
            // 起動時に飛んでくる intent
            case RequestType.LaunchRequest:
                cekResponse.AddText(IntroductionMessage[0]);
                cekResponse.ShouldEndSession = false;
                break;

            // ユーザ定義の intent
            case RequestType.IntentRequest:
            {
                // slot を抜き出す
                CEK.CSharp.Models.Slot when = null;
                cekRequest.Request.Intent.Slots?.TryGetValue(key: "when", value: out when);
                // intent ごとに処理を振り分け
                var texts = await HandleIntentAsync(cekRequest.Request.Intent.Name, when?.Value ?? "今日", Platforms.Clova);

                if (texts.Any())
                {
                    foreach (var text in texts)
                    {
                        cekResponse.AddText(text);
                    }
                }
                else
                {
                    cekResponse.AddText("予定はありません。");
                }

                // 予定があったら LINE にプッシュ通知する
                if (texts.Any())
                {
                    var config = Models.AuthenticationConfigModel.ReadFromJsonFile("appsettings.json");
                    var secret = config.LineMessagingApiSecret;

                    var textMessages = new List <ISendMessage>();

                    textMessages.Add(new TextMessage("ちょまどさんの予定はこちら!"));
                    foreach (var text in texts)
                    {
                        textMessages.Add(new TextMessage(text));
                    }

                    var messagingClient = new LineMessagingClient(secret);
                    await messagingClient.PushMessageAsync(
                        //to: cekRequest.Session.User.UserId,
                        to : config.MessagingUserId,
                        messages : textMessages
                        );
                }
            }
            break;
            }
            return(new OkObjectResult(cekResponse));
        }
コード例 #24
0
        public CEKResponse ToClovaResponse()
        {
            var response = new CEKResponse();

            // normal
            foreach (var output in OutputObjects
                     .Where(output => output.TargetPlatform == Platform.All || output.TargetPlatform == Platform.Clova))
            {
                if (output.Type == OutputType.Text)
                {
                    response.AddText(output.Value);
                }
                else if (output.Type == OutputType.Url)
                {
                    response.AddUrl(output.Value);
                }
                else if (output.Type == OutputType.Break)
                {
                    if (output.BreakTime <= 5)
                    {
                        response.AddUrl($"https://himanago.github.io/silent-mp3/silent_{output.BreakTime}s.mp3");
                    }
                    else
                    {
                        response.AddUrl($"https://himanago.github.io/silent-mp3/silent_5s.mp3");
                        response.AddUrl($"https://himanago.github.io/silent-mp3/silent_{output.BreakTime - 5}s.mp3");
                    }
                }
            }

            // AudioPlayer
            foreach (var audio in AudioItemObjects
                     .Where(audio => audio.TargetPlatform == Platform.All || audio.TargetPlatform == Platform.Clova))
            {
                response.Response.Directives.Add(new Directive()
                {
                    Header = new DirectiveHeader()
                    {
                        Namespace = DirectiveHeaderNamespace.AudioPlayer,
                        Name      = DirectiveHeaderName.Play
                    },
                    Payload = new AudioPlayPayload
                    {
                        AudioItem = new LineDC.CEK.Models.AudioItem
                        {
                            AudioItemId   = audio.AudioItemId,
                            HeaderText    = audio.Title,
                            TitleText     = audio.Title,
                            TitleSubText1 = audio.SubTitle,
                            ArtImageUrl   = audio.ImageUrl,
                            Stream        = new AudioStreamInfoObject
                            {
                                BeginAtInMilliseconds = 0,
                                Url         = audio.Url,
                                UrlPlayable = true
                            }
                        },
                        PlayBehavior = audio.AudioPlayBehavior == AudioPlayBehavior.Enqueue
                            ? LineDC.CEK.Models.AudioPlayBehavior.ENQUEUE
                            : LineDC.CEK.Models.AudioPlayBehavior.REPLACE_ALL,

                        Source = new Source {
                            Name = audio.Title
                        }
                    }
                });
            }

            if (!ShouldEndSession)
            {
                response.KeepListening();
            }

            return(response);
        }
コード例 #25
0
        public static async Task <IActionResult> CEKEndpoint(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            [OrchestrationClient] DurableOrchestrationClient client,
            ExecutionContext context,
            ILogger log)
        {
            var cekResponse = new CEKResponse();
            var clovaClient = new ClovaClient();
            var cekRequest  = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);

            var userId = cekRequest.Session.User.UserId;

            log.LogInformation(cekRequest.Request.Type.ToString());

            switch (cekRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
            {
                await client.StartNewAsync(nameof(WaitForLineInput), userId, null);

                cekResponse.AddText("LINEに入力をした内容をしゃべります。");

                // 無音無限ループに入る
                KeepClovaWaiting(cekResponse);
                break;
            }

            case RequestType.IntentRequest:
            {
                // インテントリクエストは特に用意しない
                break;
            }

            case RequestType.EventRequest:
            {
                // オーディオイベントの制御
                // Clovaでのオーディオ再生が終わった際に呼び出される
                if (cekRequest.Request.Event.Namespace == "AudioPlayer")
                {
                    if (cekRequest.Request.Event.Name == "PlayFinished")
                    {
                        // 終わっていなければ無音再生リクエストを繰り返す
                        var status = await client.GetStatusAsync(userId);

                        if (status.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew ||
                            status.RuntimeStatus == OrchestrationRuntimeStatus.Pending ||
                            status.RuntimeStatus == OrchestrationRuntimeStatus.Running)
                        {
                            KeepClovaWaiting(cekResponse);
                        }
                        else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Completed)
                        {
                            // 完了していた場合(=LINEからの外部イベント処理が実行された場合)
                            // 再度セッション継続
                            KeepClovaWaiting(cekResponse);
                            // 入力内容を話させる
                            cekResponse.AddText(status.Output.ToObject <string>());
                            // オーケストレーターを再実行
                            await client.StartNewAsync(nameof(WaitForLineInput), userId, null);
                        }
                        else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Failed)
                        {
                            // 失敗していたら結果をしゃべって終了
                            cekResponse.AddText("失敗しました。");
                        }
                        else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
                        {
                            // Botからのスキル停止指示
                            cekResponse.AddText("腹話術を終了します。");
                        }
                    }
                    else if (cekRequest.Request.Event.Name == "PlayPaused")
                    {
                        await client.TerminateAsync(userId, "PlayPaused");
                    }
                }
                break;
            }

            case RequestType.SessionEndedRequest:
            {
                // スキル終了の場合は処理もキャンセル
                await client.TerminateAsync(userId, "SessionEndedRequest");

                cekResponse.AddText("終了します。");
                break;
            }
            }

            return(new OkObjectResult(cekResponse));
        }
コード例 #26
0
        public static async Task <IActionResult> LongTimeFunction(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            [OrchestrationClient] DurableOrchestrationClient client,
            ExecutionContext context,
            ILogger log)
        {
            var cekResponse = new CEKResponse();
            var clovaClient = new ClovaClient();
            var cekRequest  = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);

            var userId = cekRequest.Session.User.UserId;

            switch (cekRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
            {
                // sessionId をインスタンス ID として新しい関数を実行
                await client.StartNewAsync(nameof(LongTimeOrchestrationFunction), userId, null);

                cekResponse.AddText("時間のかかる処理を実行しました。少々お待ちください。");

                // 無音無限ループに入る
                KeepClovaWaiting(cekResponse);
                break;
            }

            case RequestType.IntentRequest:
            {
                // インテントリクエストは特に用意しない
                cekResponse.AddText("すみません。よくわかりませんでした。");
                break;
            }

            case RequestType.EventRequest:
            {
                // オーディオイベントの制御
                // Clovaでのオーディオ再生が終わった際に呼び出される
                if (cekRequest.Request.Event.Namespace == "AudioPlayer")
                {
                    if (cekRequest.Request.Event.Name == "PlayFinished")
                    {
                        var status = await client.GetStatusAsync(userId);

                        log.LogInformation(status.RuntimeStatus.ToString());

                        // 終わっていなければ無音再生リクエストを繰り返す
                        if (status.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew ||
                            status.RuntimeStatus == OrchestrationRuntimeStatus.Pending ||
                            status.RuntimeStatus == OrchestrationRuntimeStatus.Running)
                        {
                            KeepClovaWaiting(cekResponse);
                            cekResponse.ShouldEndSession = false;
                        }
                        else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Completed)
                        {
                            // 終了していたら結果をしゃべって終了
                            cekResponse.AddText($"終わりました。結果は{status.Output.ToObject<string>()}です。");
                        }
                        else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Failed)
                        {
                            // 失敗していたら結果をしゃべって終了
                            cekResponse.AddText("失敗しました。");
                        }
                    }
                    else if (cekRequest.Request.Event.Name == "PlayStopped")
                    {
                        await client.TerminateAsync(userId, "Cancel");
                    }
                }
                break;
            }

            case RequestType.SessionEndedRequest:
            {
                // スキル終了の場合は処理もキャンセル
                await client.TerminateAsync(userId, "Cancel");

                break;
            }
            }

            return(new OkObjectResult(cekResponse));
        }
        public static async Task <IActionResult> Lab(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            [OrchestrationClient] DurableOrchestrationClient client,
            ExecutionContext context,
            ILogger log)
        {
            var config      = ConfigurationManager.GetConfiguration(context);
            var clovaClient = new ClovaClient();
            var cekRequest  = await clovaClient.GetRequest(
                req.Headers["SignatureCEK"],
                req.Body,
                config.IsSkipRequestValidation
                );

            var cekResponse = new CEKResponse();

            switch (cekRequest.Request.Type)
            {
            case RequestType.LaunchRequest:
            {
                // UserId をインスタンス ID として新しい関数を実行
                await client.StartNewAsync(nameof(LongTimeOrchestrationFunction), cekRequest.Session.User.UserId, null);

                cekResponse.AddText("時間のかかる処理を実行しました。結果を教えてと聞くと結果を答えます。");
                cekResponse.ShouldEndSession = false;
                break;
            }

            case RequestType.IntentRequest:
            {
                switch (cekRequest.Request.Intent.Name)
                {
                case "GetResultIntent":
                    // インスタンス ID が UserId の状態を取得
                    var status = await client.GetStatusAsync(cekRequest.Session.User.UserId);

                    // 状態に応じて応答を設定
                    switch (status.RuntimeStatus)
                    {
                    case OrchestrationRuntimeStatus.Canceled:
                        cekResponse.AddText("キャンセルされてます");
                        break;

                    case OrchestrationRuntimeStatus.Completed:
                        cekResponse.AddText($"終わりました。結果は{status.Output.ToObject<string>()}です。");
                        break;

                    case OrchestrationRuntimeStatus.ContinuedAsNew:
                        cekResponse.AddText("やり直してます。もうちょっと待ってね。進捗どうですかと聞いてください。");
                        cekResponse.ShouldEndSession = false;
                        break;

                    case OrchestrationRuntimeStatus.Failed:
                        cekResponse.AddText("失敗しました。");
                        break;

                    case OrchestrationRuntimeStatus.Pending:
                        cekResponse.AddText("もうちょっと待ってね。進捗どうですかと聞いてください。");
                        cekResponse.ShouldEndSession = false;
                        break;

                    case OrchestrationRuntimeStatus.Running:
                        cekResponse.AddText("もうちょっと待ってね。進捗どうですかと聞いてください。");
                        cekResponse.ShouldEndSession = false;
                        break;

                    case OrchestrationRuntimeStatus.Terminated:
                        cekResponse.AddText("失敗しました。");
                        break;
                    }
                    break;

                default:
                    cekResponse.AddText("すみません。よくわかりませんでした。");
                    break;
                }
                break;
            }

            case RequestType.SessionEndedRequest:
            {
                // 途中で終了されたら終わらせておく
                await client.TerminateAsync(cekRequest.Session.User.UserId, "User canceled");

                break;
            }
            }

            return(new OkObjectResult(cekResponse));
        }