private static async Task OnMessageEventAsync(IDurableOrchestrationClient client, MessageEvent messageEvent) { if (messageEvent.Message is TextEventMessage message) { var str = message.Text.Replace("\r\n", "\n").Replace("\n", "。"); // テンプレート入力中であればテンプレートにメッセージを追加 var tmplStatus = await client.GetStatusAsync("tmpl_" + messageEvent.Source.UserId); if (tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew || tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.Pending || tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.Running) { // Durable Functionsの外部イベントとして送信メッセージを投げる await client.RaiseEventAsync("tmpl_" + messageEvent.Source.UserId, Consts.DurableEventNameAddToTemplate, str); await lineMessagingClient.ReplyMessageAsync(messageEvent.ReplyToken, new List <ISendMessage> { new TextMessage("テンプレートに追加しました。", new QuickReply { Items = { new QuickReplyButtonObject(new PostbackTemplateAction("作成を終了する", "action=endTemplateSetting")) } }) }); } else { // 待機中になるまで待つ while (true) { // ひとつ前のイベントを処理している最中は無視されるので注意 var ventStatus = await client.GetStatusAsync(messageEvent.Source.UserId); if (ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Pending || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Running) { // Durable Functionsの外部イベントとして送信メッセージを投げる await client.RaiseEventAsync(messageEvent.Source.UserId, Consts.DurableEventNameLineVentriloquismInput, str); break; } else if (ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Terminated || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Canceled || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Failed) { // キャンセル、失敗時はスキル起動していない状態のため、スキル起動を促す await lineMessagingClient.ReplyMessageAsync(messageEvent.ReplyToken, new List <ISendMessage> { new TextMessage("Clovaで「テキスト腹話術」のスキルを起動してください。") }); break; } } } } }
protected override async Task OnMessageAsync(MessageEvent ev) { var result = null as List <ISendMessage>; switch (ev.Message) { //文字訊息 case TextEventMessage textMessage: { //頻道Id var channelId = ev.Source.Id; //使用者Id var userId = ev.Source.UserId; //回傳 hellow result = new List <ISendMessage> { new TextMessage("yes") }; } break; } if (result != null) { await _messagingClient.ReplyMessageAsync(ev.ReplyToken, result); } }
private async Task HandleTextAsync(string replyToken, string userMessage, string userId) { userMessage = userMessage.ToLower().Replace(" ", ""); if (userMessage == "チョコレート") { var reserve = new Reserve() { ProductName = "チョコレート", Amount = 1, Currency = Currency.JPY, OrderId = Guid.NewGuid().ToString(), ConfirmUrl = $"{appsettings.ServerUri}/api/linebot/confirm", ConfirmUrlType = ConfirmUrlType.SERVER }; var response = await payClient.ReserveAsync(reserve); // ユーザーの情報を設定 reserve.Mid = userId; CacheService.Cache.Add(response.Info.TransactionId, reserve); var replyMessage = new TemplateMessage( "Button Template", new ButtonsTemplate( text: $"{reserve.ProductName}を購入するには下記のボタンで決済に進んでください", actions: new List <ITemplateAction> { new UriTemplateAction("LINE Pay で決済", response.Info.PaymentUrl.Web) })); await messagingClient.ReplyMessageAsync(replyToken, new List <ISendMessage> { replyMessage }); } }
protected override async Task OnFollowAsync(FollowEvent ev) { await _messagingClient.ReplyMessageAsync(ev.ReplyToken, new List <ISendMessage> { new TextMessage("機器人可查詢附近口罩庫存數量"), new TextMessage("查詢方式: 傳送 LINE 定位"), new TextMessage("資料來源: 健康保險資料開放服務"), new ImageMessage( "https://fysh711426.github.io/iMaskMap/image/mask_info.jpg", "https://fysh711426.github.io/iMaskMap/image/mask_info_preview.jpg", new QuickReply { Items = new List <QuickReplyButtonObject> { new QuickReplyButtonObject( new LocationTemplateAction("查詢")) } }) }); }
protected override async Task OnMessageAsync(MessageEvent ev) { var result = null as List <ISendMessage>; switch (ev.Message) { //文字訊息 case TextEventMessage textMessage: { //頻道Id var channelId = ev.Source.Id; //使用者Id var userId = ev.Source.UserId; var Msg = ""; //回傳 hellow if (textMessage.Text.Contains("鴻銡")) { Msg = textMessage.Text + "看來是死定了"; } else if (textMessage.Text.Contains("和和")) { Msg = textMessage.Text + "對方還在測試"; } else if (textMessage.Text.Contains("威鉅")) { Msg = textMessage.Text + "不明不白的就簽收了"; } else if (textMessage.Text.Contains("今天")) { Msg = textMessage.Text + "哈哈哈,今天是TPS和Angular 分享"; } else if (textMessage.Text.Contains("開會")) { Msg = textMessage.Text + "我的人生又少了一個小時"; } else { Msg = "我老闆什麼都不會"; } result = new List <ISendMessage> { new TextMessage(Msg) }; if (result != null) { await _messagingClient.ReplyMessageAsync(ev.ReplyToken, result); } break; } } }
private async Task StartBatchSubSkills(string replyToken, Context context) { // 子コンテキスト var childQuery = context.UserQuery.SubSkills[0].UserQuery; childQuery.Timestamp = DateTime.UtcNow.Ticks; var childEntityId = new EntityId(nameof(ContextEntity), $"{childQuery.IntentName}-{context.UserId}"); var childContext = new Context { UserId = context.UserId, SkillName = childQuery.IntentName, UserQuery = childQuery }; await DurableClient.SignalEntityAsync <IContextEntity>(childEntityId, proxy => proxy.SetContext(childContext)); // 先頭スキルの実行 var childMessages = await Skills.First(s => s.IntentName == context.UserQuery.SubSkills[0].UserQuery.IntentName).GetReplyMessagesAsync(childContext); await LineMessagingClient.ReplyMessageAsync(replyToken, childMessages); }
/// <summary> /// Send LINE messages to LINE Channel. If reply fails, try push instead. /// </summary> /// <param name="messages">LINE messages</param> /// <param name="replyToken">ReplyToken</param> /// <param name="userId">UserId</param> /// <returns></returns> public async Task SendAsync(List <ISendMessage> messages, string userId, string replyToken) { try { // If messages contain more than 5 items, then do reply for first 5, then push the rest. for (int i = 0; i < (double)messages.Count / 5; i++) { if (i == 0) { await messagingClient.ReplyMessageAsync(replyToken, messages.Take(5).ToList()); } else { await messagingClient.PushMessageAsync(replyToken, messages.Skip(i * 5).Take(5).ToList()); } } } catch (LineResponseException ex) { if (ex.Message == "Invalid reply token") { try { for (int i = 0; i < (double)messages.Count / 5; i++) { await messagingClient.PushMessageAsync(userId, messages.Skip(i * 5).Take(5).ToList()); } } catch (LineResponseException innerEx) { await messagingClient.PushMessageAsync(userId, innerEx.Message); } } } catch (Exception ex) { await messagingClient.PushMessageAsync(userId, ex.Message); } }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req, [OrchestrationClient] DurableOrchestrationClient client, ILogger log) { try { var ev = (await req.GetWebhookEventsAsync(Consts.LineMessagingApiChannelSecret)).FirstOrDefault(); if (ev is MessageEvent messageEvent) { if (messageEvent.Message is TextEventMessage message) { // テンプレート入力中であればテンプレートにメッセージを追加 var tmplStatus = await client.GetStatusAsync("tmpl_" + messageEvent.Source.UserId); if (tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew || tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.Pending || tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.Running) { // Durable Functionsの外部イベントとして送信メッセージを投げる await client.RaiseEventAsync("tmpl_" + messageEvent.Source.UserId, Consts.DurableEventNameAddToTemplate, message.Text); await lineMessagingClient.ReplyMessageAsync(messageEvent.ReplyToken, new List <ISendMessage> { new TextMessage("テンプレートに追加しました。", new QuickReply { Items = { new QuickReplyButtonObject(new PostbackTemplateAction("作成を終了する", "action=endTemplateSetting")) } }) }); } else { // 待機中になるまで待つ while (true) { // ひとつ前のイベントを処理している最中は無視されるので注意 var ventStatus = await client.GetStatusAsync(messageEvent.Source.UserId); if (ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Pending || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Running) { // Durable Functionsの外部イベントとして送信メッセージを投げる await client.RaiseEventAsync(messageEvent.Source.UserId, Consts.DurableEventNameLineVentriloquismInput, message.Text); break; } else if (ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Terminated || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Canceled || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Failed) { // キャンセル、失敗時はスキル起動していない状態のため、スキル起動を促す await lineMessagingClient.ReplyMessageAsync(messageEvent.ReplyToken, new List <ISendMessage> { new TextMessage("Clovaで「腹話術」のスキルを起動してください。") }); break; } } } } } else if (ev is PostbackEvent postbackEvent) { switch (postbackEvent?.Postback?.Data) { // テンプレート作成開始 case "action=startTemplateSetting": await lineMessagingClient.ReplyMessageAsync(postbackEvent.ReplyToken, new List <ISendMessage> { new TextMessage("テンプレートに追加したいセリフを送ってください。") }); await client.StartNewAsync(nameof(MakeTemplate), "tmpl_" + ev.Source.UserId, null); break; // テンプレート作成終了 case "action=endTemplateSetting": // Durable Functionsの外部イベントとして送信メッセージを投げる await client.RaiseEventAsync("tmpl_" + ev.Source.UserId, Consts.DurableEventNameAddToTemplate, $"{Consts.FinishMakingTemplate}_{postbackEvent.ReplyToken}"); break; // 無限セッション終了 case "action=terminateDurableSession": // Durable Functionsの外部イベントとして送信メッセージを投げる await client.TerminateAsync(ev.Source.UserId, "User Canceled"); break; } } } catch (Exception ex) { log.LogError(ex.Message); log.LogError(ex.StackTrace); } return(new OkObjectResult("OK")); }
protected override async Task OnMessageAsync(MessageEvent ev) { var textMessage = (ev.Message as TextEventMessage); if (textMessage == null) { return; } if (textMessage.Text == "RegisterMenu") { var debugUser = ConfigurationManager.AppSettings["DebugUser"]; if (debugUser != null && debugUser == ev.Source.UserId) { var menuManager = new BingoMenuManager(_messagingClient); await menuManager.RegisterBingoMenuAsync(); await _messagingClient.ReplyMessageAsync(ev.ReplyToken, "Registerd Bingo Menus."); return; } } var user = await _messagingClient.GetUserProfileAsync(ev.Source.UserId); await TalkAsync(ev.ReplyToken, user, textMessage.Text); }
protected override async Task OnMessageAsync(MessageEvent ev) { await OnBeforeMessageAsync(ev); if (ShouldEnd) { return; } UserQuery query = null; switch (ev.Message.Type) { case EventMessageType.Text: var text = ((TextEventMessage)ev.Message).Text; // テキスト・インテント待ちを確認 var waiterId = new EntityId(nameof(ContextEntity), $"{WaiterEntityPrefix}_{ev.Source.UserId}"); var waiterState = await DurableClient.ReadEntityStateAsync <ContextEntity>(waiterId); var isWaitingForIntents = false; var isWaitingForText = false; Context waitingContext = null; if (waiterState.EntityExists && waiterState.EntityState.Context != null) { waitingContext = waiterState.EntityState.Context; if (waitingContext.ExpectedIntentNames != null) { isWaitingForIntents = true; } else { isWaitingForText = true; } } if (isWaitingForIntents || !isWaitingForText) { // detect intent query = await NluClient.DetectIntent(text, ev.Source.UserId); Logger.LogInformation(query.IntentName); } if (isWaitingForIntents) { Logger.LogInformation(waitingContext.SkillName); } // 実行スキルを選択 var targetSkill = (isWaitingForIntents && waitingContext.ExpectedIntentNames.Contains(query.IntentName)) || isWaitingForText ? waitingContext.SkillName // 待機スキル : query.IntentName; // 解析スキル if (isWaitingForText) { query = new UserQuery { IntentName = targetSkill, }; } // テキストをセット query.Text = text; var skill = Skills.FirstOrDefault(s => s.IntentName == targetSkill); if (skill != null) { // コンテキスト確認を行う var entityId = new EntityId(nameof(ContextEntity), $"{targetSkill}-{ev.Source.UserId}"); var state = await DurableClient.ReadEntityStateAsync <ContextEntity>(entityId); Context context = null; if (state.EntityExists && state.EntityState.Context != null) { context = state.EntityState.Context; var savedTimestamp = context.UserQuery.Timestamp; // Execute incomplete sub-skills when restarting from a pause between sub-skills of a batch execution skill var resume = context.UserQuery.SubSkills?.Where((s, idx) => idx != 0 && !s.IsFinished).FirstOrDefault(); if (resume != null) { context = new Context { UserId = ev.Source.UserId, SkillName = resume.UserQuery.IntentName, UserQuery = resume.UserQuery }; } else { context.UserQuery = query; } } else { context = new Context { UserId = ev.Source.UserId, IsNew = true }; query.Timestamp = DateTime.UtcNow.Ticks; context.UserQuery = query; } context.SkillName = targetSkill; var messages = await skill.GetReplyMessagesAsync(context); // Save context await DurableClient.SignalEntityAsync <IContextEntity>(entityId, proxy => proxy.SetContext(context)); // Waiter if (context.IsWaiting) { await DurableClient.SignalEntityAsync <IContextEntity>(waiterId, proxy => proxy.SetContext(context)); } if (messages != null) { if (!skill.IsContinued) { var quickReply = await FinishAndGetResumeQuickReplyAsync(context); if (messages.Last().QuickReply != null && messages.Last().QuickReply.Items.Count > 0) { messages.Last().QuickReply = MergeQuickReply(messages.Last().QuickReply, quickReply); } else { messages.Last().QuickReply = quickReply; } } await LineMessagingClient.ReplyMessageAsync(ev.ReplyToken, messages); } // Batch execution skill else if (context.UserQuery.SubSkills != null) { await StartBatchSubSkills(ev.ReplyToken, context); } } else if (query.IsFallback) { Logger.LogError("Fallback"); // TODO connect to knowledge base await LineMessagingClient.ReplyMessageAsync(ev.ReplyToken, query.FulfillmentText ?? "すみません、よくわかりませんでした。"); } else { Logger.LogError("Intentに対応するスキル定義がありません。"); await LineMessagingClient.ReplyMessageAsync(ev.ReplyToken, query.FulfillmentText ?? "すみません、よくわかりませんでした。"); } break; case EventMessageType.Sticker: case EventMessageType.Image: case EventMessageType.Video: case EventMessageType.Location: case EventMessageType.Audio: case EventMessageType.File: default: break; } await OnAfterMessageAsync(ev, query); }
protected override async Task OnPostbackAsync(PostbackEvent ev) { var query = JsonConvert.DeserializeObject <UserQuery>(ev.Postback.Data); await OnBeforePostbackAsync(ev, query); if (ShouldEnd) { return; } // テキスト・インテント待ちを確認 var waiterId = new EntityId(nameof(ContextEntity), $"{WaiterEntityPrefix}_{ev.Source.UserId}"); var waiterState = await DurableClient.ReadEntityStateAsync <ContextEntity>(waiterId); var isWaitingForIntents = false; var isWaitingForText = false; Context waitingContext = null; if (waiterState.EntityExists && waiterState.EntityState.Context != null) { waitingContext = waiterState.EntityState.Context; if (waitingContext.ExpectedIntentNames != null) { isWaitingForIntents = true; } else { isWaitingForText = true; } } // 実行スキルを選択 var targetSkill = (isWaitingForIntents && waitingContext.ExpectedIntentNames.Contains(query.IntentName)) || isWaitingForText ? waitingContext.SkillName // 待機スキル : query.IntentName; // 解析スキル if (isWaitingForText) { query = new UserQuery { IntentName = targetSkill, }; } var skill = Skills.FirstOrDefault(s => s.IntentName == targetSkill); if (skill != null) { var requestedTimestamp = query.Timestamp; // コンテキスト確認を行う var entityId = new EntityId(nameof(ContextEntity), $"{targetSkill}-{ev.Source.UserId}"); var state = await DurableClient.ReadEntityStateAsync <ContextEntity>(entityId); Context context = null; if (state.EntityExists && state.EntityState.Context != null) { context = state.EntityState.Context; } else { context = new Context { UserId = ev.Source.UserId, IsNew = true }; query.Timestamp = DateTime.UtcNow.Ticks; } context.UserQuery = query; if (!context.UserQuery.IsSubSkill && !context.UserQuery.AllowExternalCalls && (context.IsNew || context.UserQuery.Timestamp > requestedTimestamp)) { await LineMessagingClient.ReplyMessageAsync(ev.ReplyToken, "その操作は現在できません。"); return; } // スキル再確認 var subSkill = Skills.FirstOrDefault(s => s.IntentName == context.UserQuery.IntentName); var execSkill = subSkill ?? skill; var messages = await execSkill.GetReplyMessagesAsync(context); // 状態を保存 await DurableClient.SignalEntityAsync <IContextEntity>(entityId, proxy => proxy.SetContext(context)); // Waiter if (context.IsWaiting) { await DurableClient.SignalEntityAsync <IContextEntity>(waiterId, proxy => proxy.SetContext(context)); } if (messages != null) { if (!execSkill.IsContinued) { var quickReply = await FinishAndGetResumeQuickReplyAsync(context); if (messages.Last().QuickReply != null && messages.Last().QuickReply.Items.Count > 0) { messages.Last().QuickReply = MergeQuickReply(messages.Last().QuickReply, quickReply); } else { messages.Last().QuickReply = quickReply; } } await LineMessagingClient.ReplyMessageAsync(ev.ReplyToken, messages); } // バッチ実行スキル else if (context.UserQuery.SubSkills != null) { await StartBatchSubSkills(ev.ReplyToken, context); } } await OnAfterPostbackAsync(ev, query); }
public async Task <IActionResult> Webhook() { HttpContext httpContext = HttpContext; LineMessagingClient client = new LineMessagingClient(accessToken); ReceiveEventModel model = await WebhookRequestMessage.GetWebhookEvent(httpContext, channelSecret); if (model == null) { return(BadRequest()); } if (model.events == null) { return(BadRequest()); } foreach (EventModel q in model.events) { string senderId = ""; switch (q.source.type) { case SourceType.user: senderId = q.source.userId; break; case SourceType.room: senderId = q.source.roomId; break; case SourceType.group: senderId = q.source.groupId; break; } if (q.type == EventType.message) { MessageEventTypeUtility messageEventTypeUtility = new MessageEventTypeUtility(accessToken); #region ReplyMessage /*ReplyMessageModel replyMessageBody = new ReplyMessageModel() * { * replyToken = q.replyToken, * messages = await messageEventTypeUtility.AutoProcessMessageType(q.message) * }; * * await client.ReplyMessageAsync(replyMessageBody);*/ #endregion #region ReplyMessageWithJson await client.ReplyMessageWithJsonAsync(q.replyToken, await messageEventTypeUtility.AutoProcessMessageTypeWithJson(q.message)); #endregion //await client.ReplyMessageWithJsonAsync(q.replyToken, new ApparelFlexMessage().Create2()); #region push message /*PushMessageModel pushMessageBody = new PushMessageModel() * { * to = "someone's UID", * messages = messageEventTypeUtility.PushMessageType() * }; * await client.PushMessageAsync(pushMessageBody);*/ #endregion #region broadcast message /*BroadcastModel broadcast = new BroadcastModel() * { * messages = messageEventTypeUtility.BroadcastMessageType() * }; * await client.BroadcastMessageAsync(broadcast);*/ #endregion Console.WriteLine("Sender: " + senderId); Console.WriteLine("Message: " + q.message.text); } else if (q.type == EventType.follow) { MessageEventTypeUtility messageEventTypeUtility = new MessageEventTypeUtility(accessToken); FollowEventTypeUtility followEventTypeProcessor = new FollowEventTypeUtility(accessToken); UserProfileResponseModel profileModel = await followEventTypeProcessor.GetProfileAsync(q.source.userId); string text = $"Welcome, {profileModel.displayName}"; ReplyMessageModel replyMessageBody = new ReplyMessageModel() { replyToken = q.replyToken, messages = messageEventTypeUtility.CreateTextMessage(text) }; await client.ReplyMessageAsync(replyMessageBody); } } return(Ok()); }
public static async Task <IActionResult> RunAsync([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage req, TraceWriter log) { string requestContent = await req.Content.ReadAsStringAsync(); if (string.IsNullOrWhiteSpace(requestContent)) { return(new BadRequestObjectResult("Empty content is given")); } var eventGridSubscriber = new TraceableEventGridSubscriber(); eventGridSubscriber.AddOrUpdateCustomEventMapping(typeof(MessagesEventReply).FullName, typeof(MessagesEventReply)); var eventGridEvents = eventGridSubscriber.DeserializeEventGridEvents(requestContent).ToList(); var subscriptionValidationEvent = eventGridEvents.FirstOrDefault(x => x.Data is SubscriptionValidationEventData); if (subscriptionValidationEvent != null) { var eventData = (SubscriptionValidationEventData)subscriptionValidationEvent.Data; log.Info($"Got SubscriptionValidation event data, validationCode: {eventData.ValidationCode}, validationUrl: {eventData.ValidationUrl}, topic: {subscriptionValidationEvent.Topic}"); return(new OkObjectResult(new SubscriptionValidationResponse { ValidationResponse = eventData.ValidationCode })); } var eventGridEndpoint = Environment.GetEnvironmentVariable("EventGridTopicEndpoint", EnvironmentVariableTarget.Process); var eventGridKey = Environment.GetEnvironmentVariable("EventGridTopicKey", EnvironmentVariableTarget.Process); var redisConnectionString = Environment.GetEnvironmentVariable("RedisConnectionString", EnvironmentVariableTarget.Process); if (string.IsNullOrWhiteSpace(eventGridEndpoint) || string.IsNullOrWhiteSpace(eventGridKey) || string.IsNullOrWhiteSpace(redisConnectionString)) { throw new Exception( "Lacks of Environment Variable: 'EventGridTopicEndpoint' or 'EventGridTopicKey' or 'RedisConnectionString'"); } Parallel.ForEach(eventGridEvents, eventGridEvent => { try { var traceableEventData = (TraceableEventData)eventGridEvent.Data; if (traceableEventData.Data is MessagesEventReply messagesEventReply) { var redisHelper = new AzureRedisHelper(redisConnectionString); var configString = redisHelper.GetRedis(traceableEventData.TraceToken) ?? throw new Exception($"Get empty serialized LineMessagingApiConfig string with key '{traceableEventData.TraceToken}'"); var config = JsonConvert.DeserializeObject <LineMessagingApiConfig>(configString) ?? throw new Exception($"Failed to deserialize LineMessagingApiConfig string with '{configString}'"); Parallel.ForEach(messagesEventReply.MessageReplys.GroupBy(x => x.ReplyToken), messageReplyGroupByReplyToken => { var sendMessages = messageReplyGroupByReplyToken.Select(messageReply => SendMessageConverter.ConvertToISendMessages(messageReply, log)).ToList(); var lineId = messageReplyGroupByReplyToken.First().LineId; var lineClient = new LineMessagingClient(config.ChannelAccessToken); try { lineClient.ReplyMessageAsync( messageReplyGroupByReplyToken.Key, sendMessages ).GetAwaiter().GetResult(); } catch (LineResponseException ex) { log.Warning(ex.ToString()); try { lineClient.PushMessageAsync( lineId, sendMessages ).GetAwaiter().GetResult(); } catch (Exception exi) { log.Warning(exi.ToString()); } } catch (Exception ex) { log.Warning(ex.ToString()); } }); } } catch (Exception ex) { log.Error(ex.ToString()); } }); return(new OkObjectResult("Ok")); }