public void Dispatch <T>(IList <T> webhookEvents, LineMessagingApiConfig config) where T : WebhookEvent { var messageList = webhookEvents.OfType <MessageEvent>().Where(x => x.Message.Type == EventMessageType.Text) .Select(x => new Message { Type = MessageType.Text, Text = (x.Message as TextEventMessage)?.Text, Source = x.Source.Type == MessagingEventSourceType.User ? new EventSource { Type = WebHookModelEventSourceType.User, UserId = x.Source.UserId } : x.Source.Type == MessagingEventSourceType.Group ? new EventSource { Type = WebHookModelEventSourceType.Group, UserId = x.Source.UserId, GroupId = x.Source.Id } : x.Source.Type == MessagingEventSourceType.Room ? new EventSource { Type = WebHookModelEventSourceType.Room, UserId = x.Source.UserId, RoomId = x.Source.Id } : default(EventSource), ReplyToken = x.ReplyToken, Timestamp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(x.Timestamp) }).ToList(); 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'"); } var traceToken = $"line-message-{Guid.NewGuid()}"; var redisHelper = new AzureRedisHelper(redisConnectionString); redisHelper.SetRedis(traceToken, JsonConvert.SerializeObject(config), (int)new TimeSpan(days: 0, hours: 1, minutes: 0, seconds: 0).TotalSeconds); var publishHelper = new EventGridPublishHelper(new Uri(eventGridEndpoint), eventGridKey); publishHelper.PublishEventAsync( new List <EventGridEvent> { EventGridUtility.CreateTraceableEventGridEvent($"/line/webhook/message/", new MessagesEvent { ChannelId = config.ChannelId, Messages = messageList }, traceToken) } ).GetAwaiter().GetResult(); }
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")); }