/// <summary>
 /// Constructor
 /// </summary>
 /// <param name="originalContentUrl">
 /// URL of audio file (Max: 1000 characters)
 /// HTTPS
 /// m4a
 /// Less than 1 minute
 /// Max 10 MB
 /// </param>
 /// <param name="duration">
 /// Length of audio file (milliseconds)
 /// </param>
 /// <param name="quickReply">
 /// QuickReply
 /// </param>
 /// <param name="sender">
 /// Sender
 /// </param>
 public AudioMessage(string originalContentUrl, long duration, QuickReply quickReply = null, Sender sender = null)
 {
     OriginalContentUrl = originalContentUrl;
     Duration           = duration;
     QuickReply         = quickReply;
     Sender             = sender;
 }
Exemplo n.º 2
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="packageId">
 /// Package ID for a set of stickers. For information on package IDs, see the Sticker list.
 /// </param>
 /// <param name="stickerId">
 /// Sticker ID. For a list of sticker IDs for stickers that can be sent with the Messaging API, see the Sticker list.
 /// </param>
 /// <param name="quickReply">
 /// QuickReply
 /// </param>
 /// <param name="sender">
 /// Sender
 /// </param>
 public StickerMessage(string packageId, string stickerId, QuickReply quickReply = null, Sender sender = null)
 {
     PackageId  = packageId;
     StickerId  = stickerId;
     QuickReply = quickReply;
     Sender     = sender;
 }
Exemplo n.º 3
0
        public async Task ExecuteAsync()
        {
            using (var context = new ToolsContext(AppConfig.ToolsOption.Options))
            {
                //実行中に更新
                var task = context.NotificationTasks.Where(t => t.TaskId == this.TaskId).SingleOrDefault();
                task.Status = Noobow.Commons.Constants.NotificationTaskStatusEnum.EXECUTING;
                context.SaveChanges();
                //待ち時間を計算
                int waitTime = Convert.ToInt32((task.NotificationTime - DateTime.Now).Value.TotalMilliseconds);
                //待つ
                Thread.Sleep(waitTime);
                //通知
                var quickReply = new QuickReply();
                quickReply.Items.Add(new QuickReplyButtonObject(new MessageTemplateAction("5分後", $"{CommandEum.PlanNotice.GetStringValue()} a5 {task.NotificationDetail}")));
                quickReply.Items.Add(new QuickReplyButtonObject(new MessageTemplateAction("10分後", $"{CommandEum.PlanNotice.GetStringValue()} a10 {task.NotificationDetail}")));
                quickReply.Items.Add(new QuickReplyButtonObject(new MessageTemplateAction("30分後", $"{CommandEum.PlanNotice.GetStringValue()} a30 {task.NotificationDetail}")));
                quickReply.Items.Add(new QuickReplyButtonObject(new MessageTemplateAction("1時間後", $"{CommandEum.PlanNotice.GetStringValue()} a60 {task.NotificationDetail}")));
                await LineMessagingClientManager.GetInstance().PushMessageAsync(task.NotificationTo, new List <ISendMessage> {
                    new TextMessage(task.NotificationDetail, quickReply)
                });

                //実行済みに更新
                task.Status = NotificationTaskStatusEnum.EXECUTED;
                context.SaveChanges();
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="originalContentUrl">
 /// Image URL (Max: 1000 characters)
 /// HTTPS
 /// JPEG
 /// Max: 1024 x 1024
 /// Max: 1 MB
 /// </param>
 /// <param name="previerImageUrl">
 /// Preview image URL (Max: 1000 characters)
 /// HTTPS
 /// JPEG
 /// Max: 240 x 240
 /// Max: 1 MB
 /// </param>
 /// <param name="quickReply">
 /// QuickReply
 /// </param>
 /// <param name="sender">
 /// Sender
 /// </param>
 public ImageMessage(string originalContentUrl, string previerImageUrl, QuickReply quickReply = null, Sender sender = null)
 {
     OriginalContentUrl = originalContentUrl;
     PreviewImageUrl    = previerImageUrl;
     QuickReply         = quickReply;
     Sender             = sender;
 }
Exemplo n.º 5
0
        private static async void Bot_OnMessage(MessageEventArgs e)
        {
            Console.WriteLine($"{e.Message.Sender}: {e.Message.Text}");

            if (e.Message.Sender != UserId)
            {
                QuickReply qr = null;

                if (e.Message.Text == "q")
                {
                    qr = new QuickReply();
                    qr.Options.Add(new QuickReplyOption()
                    {
                        Label = "1", Metadata = "#1#"
                    });
                    qr.Options.Add(new QuickReplyOption()
                    {
                        Label = "2", Metadata = "#2#"
                    });
                    qr.Options.Add(new QuickReplyOption()
                    {
                        Label = "3", Metadata = "#3#"
                    });
                }

                await bot.SendMessageAsync(e.Message.Sender, e.Message.Text, qr);
            }
        }
Exemplo n.º 6
0
        private QuickReply MergeQuickReply(QuickReply a, QuickReply b)
        {
            var items = new List <QuickReplyButtonObject>();

            items.AddRange(a.Items);
            items.AddRange(b.Items);
            return(new QuickReply(items));
        }
Exemplo n.º 7
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="originalContentUrl">
 /// URL of video file (Max: 1000 characters)
 /// HTTPS
 /// mp4
 /// Less than 1 minute
 /// Max: 10 MB
 /// </param>
 /// <param name="previerImageUrl">
 /// URL of preview image (Max: 1000 characters)
 /// HTTPS
 /// JPEG
 /// Max: 240 x 240
 /// Max: 1 MB
 /// </param>
 /// <param name="quickReply">
 /// QuickReply
 /// </param>
 public VideoMessage(string originalContentUrl, string previerImageUrl, string trackingId = null, QuickReply quickReply = null, MessageSender messageSender = null)
 {
     OriginalContentUrl = originalContentUrl;
     PreviewImageUrl    = previerImageUrl;
     QuickReply         = quickReply;
     Sender             = messageSender;
     TrackingId         = trackingId;
 }
Exemplo n.º 8
0
        public async Task ShouldBuildRequestToSendQuickRepliesCorrectly()
        {
            _http.RespondWithJson(_fixture.Create <SendMessageResponse>());

            await _apiClient.SendQuickRepliesAsync(
                "123",
                "message",
                new[]
            {
                QuickReply.Text("foo", "bar", "https://www.foo.com"),
                QuickReply.UserEmail(),
                QuickReply.UserPhoneNumber()
            }
                );

            _http
            .ShouldHaveMadeACall()
            .WithVerb(HttpMethod.Post)
            .WithRequestJson(new
            {
                messaging_type = "RESPONSE",
                recipient      = new
                {
                    id = "123"
                },
                message = new
                {
                    text          = "message",
                    quick_replies = new dynamic[]
                    {
                        new
                        {
                            content_type = "text",
                            title        = "foo",
                            payload      = "bar",
                            image_url    = "https://www.foo.com"
                        },
                        new
                        {
                            content_type = "user_email"
                        },
                        new
                        {
                            content_type = "user_phone_number"
                        }
                    }
                }
            });
        }
Exemplo n.º 9
0
        private async Task Messaging(MessageEvent ev)
        {
            if (!(ev.Message is TextEventMessage msg))
            {
                return;
            }

            if (msg.Text.Contains("ルール") && msg.Text.Contains("FAQ"))
            {
                var messages = new ISendMessage[]
                {
                    new FlexMessage("ルール", FlexMessageText.Flex_Rule(), null, sender_admin),
                    new FlexMessage("FAQ", FlexMessageText.Flex_Faq(), null, sender_admin)
                };
                await lineMessagingClient.ReplyMessageAsync(ev.ReplyToken, messages);
            }
            else if (msg.Text.Contains("ルール"))
            {
                var messages = new ISendMessage[]
                {
                    new FlexMessage("ルール", FlexMessageText.Flex_Rule(), null, sender_admin)
                };

                await lineMessagingClient.ReplyMessageAsync(ev.ReplyToken, messages);
            }
            else if (msg.Text.Contains("FAQ"))
            {
                var messages = new ISendMessage[]
                {
                    new FlexMessage("FAQ", FlexMessageText.Flex_Faq(), null, sender_admin)
                };

                await lineMessagingClient.ReplyMessageAsync(ev.ReplyToken, messages);
            }
            else if (msg.Text == "継続確認イベント" && Admin_Users.Contains(ev.Source.UserId))
            {
                var messages = new ISendMessage[]
                {
                    new FlexMessage("継続確認イベント", FlexMessageText.Flex_Check_Continue(), null, sender_admin)
                };
                await lineMessagingClient.ReplyMessageAsync(ev.ReplyToken, messages);
            }
            else if (msg.Text == "継続確認リセット" && Admin_Users.Contains(ev.Source.UserId))
            {
                await database.MemberCheckReset();

                await lineMessagingClient.ReplyTextAsync(ev.ReplyToken, "リセットしました", false, null, sender_admin);
            }
            else if (msg.Text == "継続希望メンバー" && Admin_Users.Contains(ev.Source.UserId))
            {
                var member_list = await database.GetMember("SELECT c.newername FROM c Where c.check != null and c.leavedDate = null ORDER BY c.joinedDate");

                string member = "希望済のメンバー";
                foreach (var item in member_list)
                {
                    member += "\n" + item.newername;
                }
                await lineMessagingClient.ReplyTextAsync(ev.ReplyToken, member, false, null, sender_admin);
            }
            else if (msg.Text == "継続希望旧メンバー" && Admin_Users.Contains(ev.Source.UserId))
            {
                var member_list = await database.GetMember("SELECT c.name FROM c Where c.check != null and c.leavedDate = null ORDER BY c.joinedDate");

                string member = "希望済のメンバー";
                foreach (var item in member_list)
                {
                    member += "\n" + item.name;
                }
                await lineMessagingClient.ReplyTextAsync(ev.ReplyToken, member, false, null, sender_admin);
            }
            else if (msg.Text == "継続未希望メンバー" && Admin_Users.Contains(ev.Source.UserId))
            {
                var member_list = await database.GetMember("SELECT c.newername FROM c Where c.check = null and c.leavedDate = null ORDER BY c.joinedDate");

                string member = "未希望のメンバー";
                foreach (var item in member_list)
                {
                    member += "\n" + item.newername;
                }
                await lineMessagingClient.ReplyTextAsync(ev.ReplyToken, member, false, null, sender_admin);
            }
            else if (msg.Text == "継続未希望旧メンバー" && Admin_Users.Contains(ev.Source.UserId))
            {
                var member_list = await database.GetMember("SELECT c.name FROM c Where c.check = null and c.leavedDate = null ORDER BY c.joinedDate");

                string member = "未希望のメンバー";
                foreach (var item in member_list)
                {
                    member += "\n" + item.name;
                }
                await lineMessagingClient.ReplyTextAsync(ev.ReplyToken, member, false, null, sender_admin);
            }
            else if (msg.Text.Contains("にゃ") || msg.Text.Contains("ニャ"))
            {
                var rand    = new Random();
                var catword = new string[] { "にゃฅ(。•ㅅ•。ฅ)", "(=゚-゚)ノニャーン♪", "(=´∇`=)にゃん", "ฅ(๑•̀ω•́๑)ฅニャンニャンガオー", "ミャー♪ヽ(∇⌒= )( =⌒∇)ノミャー♪", "=^∇^*= にゃお~ん♪" };
                await lineMessagingClient.ReplyTextAsync(ev.ReplyToken, catword[rand.Next(0, catword.Length)], false, null, sender_cat);
            }
            else if (msg.Text == "Google")
            {
                var action = new UriTemplateAction("google", "https://google.com");
                var qr     = new QuickReply()
                {
                    Items = new List <QuickReplyButtonObject>()
                    {
                        new QuickReplyButtonObject(action)
                    }
                };
                await lineMessagingClient.ReplyTextAsync(ev.ReplyToken, "hello", false, qr);
            }
        }
 /// <summary>
 /// Sets a QuickReply object to the FlexMessage object.
 /// </summary>
 /// <param name="quickReply"></param>
 /// <returns>Flex Message</returns>
 public CarouselContainerFlexMessage SetQuickReply(QuickReply quickReply)
 {
     QuickReply = quickReply;
     return(this);
 }
Exemplo n.º 11
0
 /// <summary>
 /// Sets a QuickReply object to the FlexMessage object.
 /// </summary>
 /// <param name="quickReply"></param>
 /// <returns>Flex Message</returns>
 public BubbleContainerFlexMessage SetQuickReply(QuickReply quickReply)
 {
     QuickReply = quickReply;
     return(this);
 }
Exemplo n.º 12
0
        public async Task <QuickReply> CreateQuickReply(QuickReply QuickReplyInfo)
        {
            QuickReplyInfo.Id = await _repository.InsertAndGetIdAsync(QuickReplyInfo);

            return(QuickReplyInfo);
        }
Exemplo n.º 13
0
        public async Task <WelcomeMessageRaw> CreateWelcomeMessageAsync(string name, string text, QuickReply quickReply)
        {
            WelcomeMessageRaw message = new WelcomeMessageRaw()
            {
                Name = name,
                Data = new MessageData()
                {
                    Text       = text,
                    QuickReply = quickReply
                }
            };

            WelcomeMessageContainerRaw container = new WelcomeMessageContainerRaw()
            {
                Data = message
            };

            return((await PostAsync <WelcomeMessageContainerRaw>(container, ApiUri + "new.json")).Data);
        }
 public QuickReply AddQuickReply(QuickReply qReply)
 {
     return(_quickReplyRepository.Add(qReply));
 }
Exemplo n.º 15
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="originalContentUrl">
 /// URL of video file (Max: 1000 characters)
 /// HTTPS
 /// mp4
 /// Less than 1 minute
 /// Max: 10 MB
 /// </param>
 /// <param name="previerImageUrl">
 /// URL of preview image (Max: 1000 characters)
 /// HTTPS
 /// JPEG
 /// Max: 240 x 240
 /// Max: 1 MB
 /// </param>
 public VideoMessage(string originalContentUrl, string previerImageUrl, QuickReply quickReply = null)
 {
     OriginalContentUrl = originalContentUrl;
     PreviewImageUrl    = previerImageUrl;
     QuickReply         = quickReply;
 }
Exemplo n.º 16
0
        public async Task <MessageCreateEvent> SendMessageAsync(long userId, string text, QuickReply quickReply)
        {
            MessageCreateEvent messageCreateEvent = new MessageCreateEvent()
            {
                Timestamp = DateTime.UtcNow,
                Data      = new MessageCreateData()
                {
                    Target = new Target()
                    {
                        RecipientId = userId
                    },

                    Data = new MessageData()
                    {
                        Text       = text,
                        QuickReply = quickReply
                    }
                }
            };

            Event <MessageCreateEvent> eventContainer = new Event <MessageCreateEvent>()
            {
                Data = messageCreateEvent
            };

            return((await PostAsync <Event <MessageCreateEvent> >(eventContainer, ApiUri + "events/new.json")).Data);
        }
Exemplo n.º 17
0
 public async Task <QuickReply> UpdateQuickReply(QuickReply QuickReplyInfo)
 {
     return(await _repository.UpdateAsync(QuickReplyInfo));
 }
Exemplo n.º 18
0
        private async Task HandleTextAsync(string replyToken, string userMessage, string userId)
        {
            userMessage = userMessage.ToLower().Replace(" ", "");
            ISendMessage replyMessage = null;

            if (userMessage == "buttons")
            {
                replyMessage = new TemplateMessage("Button Template",
                                                   new ButtonsTemplate(text: "ButtonsTemplate", title: "Click Buttons.",
                                                                       actions: new List <ITemplateAction> {
                    new MessageTemplateAction("Message Label", "sample data"),
                    new PostbackTemplateAction("Postback Label", "sample data", "sample data"),
                    new UriTemplateAction("Uri Label", "https://github.com/kenakamu")
                }));
            }
            else if (userMessage == "confirm")
            {
                replyMessage = new TemplateMessage("Confirm Template",
                                                   new ConfirmTemplate("ConfirmTemplate", new List <ITemplateAction> {
                    new MessageTemplateAction("Yes", "Yes"),
                    new MessageTemplateAction("No", "No")
                }));
            }
            else if (userMessage == "carousel")
            {
                List <ITemplateAction> actions1 = new List <ITemplateAction>();
                List <ITemplateAction> actions2 = new List <ITemplateAction>();

                // Add actions.
                actions1.Add(new MessageTemplateAction("Message Label", "sample data"));
                actions1.Add(new PostbackTemplateAction("Postback Label", "sample data", "sample data"));
                actions1.Add(new UriTemplateAction("Uri Label", "https://github.com/kenakamu"));

                // Add datetime picker actions
                actions2.Add(new DateTimePickerTemplateAction("DateTime Picker", "DateTime",
                                                              DateTimePickerMode.Datetime, "2017-07-21T13:00", null, null));
                actions2.Add(new DateTimePickerTemplateAction("Date Picker", "Date",
                                                              DateTimePickerMode.Date, "2017-07-21", null, null));
                actions2.Add(new DateTimePickerTemplateAction("Time Picker", "Time",
                                                              DateTimePickerMode.Time, "13:00", null, null));

                replyMessage = new TemplateMessage("Button Template",
                                                   new CarouselTemplate(new List <CarouselColumn> {
                    new CarouselColumn("Casousel 1 Text", "https://github.com/apple-touch-icon.png",
                                       "Casousel 1 Title", actions1),
                    new CarouselColumn("Casousel 1 Text", "https://github.com/apple-touch-icon.png",
                                       "Casousel 1 Title", actions2)
                }));
            }
            else if (userMessage == "imagecarousel")
            {
                UriTemplateAction action = new UriTemplateAction("Uri Label", "https://github.com/kenakamu");

                replyMessage = new TemplateMessage("ImageCarouselTemplate",
                                                   new ImageCarouselTemplate(new List <ImageCarouselColumn> {
                    new ImageCarouselColumn("https://github.com/apple-touch-icon.png", action),
                    new ImageCarouselColumn("https://github.com/apple-touch-icon.png", action),
                    new ImageCarouselColumn("https://github.com/apple-touch-icon.png", action),
                    new ImageCarouselColumn("https://github.com/apple-touch-icon.png", action),
                    new ImageCarouselColumn("https://github.com/apple-touch-icon.png", action)
                }));
            }
            else if (userMessage == "imagemap")
            {
                var url      = HttpContext.Current.Request.Url;
                var imageUrl = $"{url.Scheme}://{url.Host}:{url.Port}/images/githubicon";
                replyMessage = new ImagemapMessage(
                    imageUrl,
                    "GitHub",
                    new ImagemapSize(1040, 1040), new List <IImagemapAction>
                {
                    new UriImagemapAction(new ImagemapArea(0, 0, 520, 1040), "http://github.com"),
                    new MessageImagemapAction(new ImagemapArea(520, 0, 520, 1040), "I love LINE!")
                });
            }
            else if (userMessage == "addrichmenu")
            {
                // Create Rich Menu
                RichMenu richMenu = new RichMenu()
                {
                    Size        = ImagemapSize.RichMenuLong,
                    Selected    = false,
                    Name        = "nice richmenu",
                    ChatBarText = "touch me",
                    Areas       = new List <ActionArea>()
                    {
                        new ActionArea()
                        {
                            Bounds = new ImagemapArea(0, 0, ImagemapSize.RichMenuLong.Width, ImagemapSize.RichMenuLong.Height),
                            Action = new PostbackTemplateAction("ButtonA", "Menu A", "Menu A")
                        }
                    }
                };

                var richMenuId = await messagingClient.CreateRichMenuAsync(richMenu);

                var image = new MemoryStream(File.ReadAllBytes(HttpContext.Current.Server.MapPath(@"~\Images\richmenu.PNG")));
                // Upload Image
                await messagingClient.UploadRichMenuPngImageAsync(image, richMenuId);

                // Link to user
                await messagingClient.LinkRichMenuToUserAsync(userId, richMenuId);

                replyMessage = new TextMessage("Rich menu added");
            }
            else if (userMessage == "deleterichmenu")
            {
                // Get Rich Menu for the user
                var richMenuId = await messagingClient.GetRichMenuIdOfUserAsync(userId);

                await messagingClient.UnLinkRichMenuFromUserAsync(userId);

                await messagingClient.DeleteRichMenuAsync(richMenuId);

                replyMessage = new TextMessage("Rich menu deleted");
            }
            else if (userMessage == "deleteallrichmenu")
            {
                // Get Rich Menu for the user
                var richMenuList = await messagingClient.GetRichMenuListAsync();

                foreach (var richMenu in richMenuList)
                {
                    await messagingClient.DeleteRichMenuAsync(richMenu.RichMenuId);
                }
                replyMessage = new TextMessage("All rich menu added");
            }
            else if (userMessage == "quickreply")
            {
                var quickReply = new QuickReply();
                quickReply.Items.Add(new QuickReplyButtonObject(
                                         new PostbackTemplateAction("postback", "postback_data", "postback display", true), "https://github.com/apple-touch-icon.png"));
                quickReply.Items.Add(new QuickReplyButtonObject(
                                         new MessageTemplateAction("message", "message"), "https://github.com/apple-touch-icon.png"));
                quickReply.Items.Add(new QuickReplyButtonObject(
                                         new DateTimePickerTemplateAction("timepicker", "DATETIME", DateTimePickerMode.Datetime, DateTime.Now), "https://github.com/apple-touch-icon.png"));
                quickReply.Items.Add(new QuickReplyButtonObject(
                                         new CameraTemplateAction("Launch Camera")));
                quickReply.Items.Add(new QuickReplyButtonObject(
                                         new CameraRollTemplateAction("Launch Camera Roll")));
                quickReply.Items.Add(new QuickReplyButtonObject(
                                         new LocationTemplateAction("Launch Location")));
                replyMessage = new TextMessage("Select menu from Quick Reply", quickReply);
            }
            else
            {
                replyMessage = new TextMessage(userMessage);
            }

            await messagingClient.ReplyMessageAsync(replyToken, new List <ISendMessage> {
                replyMessage
            });
        }
Exemplo n.º 19
0
        /// <summary>
        /// 会話を終了し、保存されているコンテキスト情報は削除されます。
        /// 中断中のスキルがあればひとつ前の中断スキルに戻るためのクイックリプライを返します。
        /// </summary>
        /// <returns></returns>
        private async Task <QuickReply> FinishAndGetResumeQuickReplyAsync(Context context)
        {
            var entityId = new EntityId(nameof(ContextEntity), $"{context.SkillName}-{context.UserId}");
            await DurableClient.SignalEntityAsync <IContextEntity>(entityId, proxy => proxy.SetContext(null));

            QuickReply ret = null;

            // 中断スキルへのジャンプおよびバッチ実行の後続スキル呼び出し
            // ユーザーIDで継続中のコンテキストを検索
            var result = await DurableClient.ListEntitiesAsync(
                new EntityQuery { EntityName = nameof(ContextEntity) },
                new System.Threading.CancellationToken());

            var entityQuery = result.Entities
                              .Where(e => e.EntityId.EntityKey.EndsWith(context.UserId) &&
                                     !e.EntityId.EntityKey.StartsWith(context.SkillName) &&
                                     !e.EntityId.EntityKey.StartsWith(WaiterEntityPrefix))
                              .OrderByDescending(e => e.LastOperationTime);

            Context targetContext = null;

            foreach (var e in entityQuery)
            {
                var state = await DurableClient.ReadEntityStateAsync <ContextEntity>(e.EntityId);

                var target = state.EntityState;
                if (state.EntityState.Context != null)
                {
                    targetContext = state.EntityState.Context;
                    break;
                }
            }

            if (targetContext != null)
            {
                // 保存されているコンテキストがバッチ実行中のものかを確認
                var batchSkills = targetContext.UserQuery.SubSkills;

                // バッチ実行の場合
                if (batchSkills != null && batchSkills.Length != 0 &&
                    // 今回完了したスキルがバッチ内のものかを調べる
                    batchSkills.Where((s, idx) =>
                                      s.UserQuery.IntentName == context.UserQuery.IntentName && // 今回完了したスキルがバッチ実行定義に存在
                                      !s.IsFinished &&                                          // 完了していない
                                      (idx == 0 || batchSkills[idx - 1].IsFinished)).Any())     // 先頭スキル or 直前が完了
                {
                    var skill = batchSkills.First(s => s.UserQuery.IntentName == context.UserQuery.IntentName);
                    var index = Array.IndexOf(batchSkills, skill);

                    var targetEntityId = new EntityId(nameof(ContextEntity), $"{targetContext.UserQuery.IntentName}-{context.UserId}");

                    if (batchSkills.Length == index + 1)
                    {
                        // 最終スキルなので、バッチ実行コンテキストを削除
                        await DurableClient.SignalEntityAsync <IContextEntity>(targetEntityId, proxy => proxy.SetContext(null));
                    }
                    else
                    {
                        // 終了フラグを更新
                        batchSkills[index].IsFinished = true;
                        await DurableClient.SignalEntityAsync <IContextEntity>(targetEntityId, proxy => proxy.SetContext(targetContext));

                        // 後続へジャンプ
                        var next = batchSkills[index + 1];
                        next.UserQuery.IsSubSkill = true;

                        ret = new QuickReply(new List <QuickReplyButtonObject>
                        {
                            new QuickReplyButtonObject(new PostbackTemplateAction(
                                                           $"続けて{next.DisplayName}に進む",
                                                           JsonConvert.SerializeObject(next.UserQuery)))
                        });
                    }
                }
                else
                {
                    var userQuery = targetContext.UserQuery;

                    // 子スキル情報、フルフィルメントテキストは削除(Postbackデータに収まらないため)
                    userQuery.SubSkills       = null;
                    userQuery.FulfillmentText = string.Empty;

                    ret = new QuickReply(new List <QuickReplyButtonObject>
                    {
                        new QuickReplyButtonObject(new PostbackTemplateAction(
                                                       "ひとつ前の対話を再開する",
                                                       JsonConvert.SerializeObject(userQuery)))
                    });
                }
            }
            return(ret);
        }