public async Task ProcessStreamQueueMessage( [QueueTrigger(Constants.FX_CONFIG_STREAM_QUEUE_NAME_VALUE)] string message, ILogger logger) { var json = JObject.Parse(message); var entity = new ChannelActivityEntity(); if (json["data"].HasValues) { var updates = json["data"].ToObject <List <TwitchWebhookStreamResponse> >(); foreach (var update in updates) { entity.Activity = StreamActivity.StreamStarted.ToString(); entity.PartitionKey = update.UserName; entity.RowKey = update.StartedAt.ToString(Constants.DATETIME_FORMAT).Replace(":", string.Empty).Replace("-", string.Empty); entity.Viewer = string.Empty; } } else { entity.Activity = StreamActivity.StreamStopped.ToString(); entity.PartitionKey = json["channel"].ToString(); entity.RowKey = DateTime.Parse(json["timestamp"].ToString()).ToString(Constants.DATETIME_FORMAT).Replace(":", string.Empty).Replace("-", string.Empty); entity.Viewer = string.Empty; } await _storageService.AddDataToStorage(entity); await DispatchSignalRMessage(entity); }
public static async Task <ChannelActivityEntity> InsertOrMergeEntityAsync(CloudTable table, ChannelActivityEntity entity) { if (entity == null) { throw new ArgumentNullException("entity"); } try { // Create the InsertOrReplace table operation var insertOrMergeOperation = TableOperation.InsertOrMerge(entity); // Execute the operation. Console.WriteLine($"{DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)}: Adding entity {entity} to the table {table.Name}"); var result = await table.ExecuteAsync(insertOrMergeOperation); var insertedActivity = result.Result as ChannelActivityEntity; // Get the request units consumed by the current operation. RequestCharge of a TableResult is only applied to Azure Cosmos DB if (result.RequestCharge.HasValue) { Console.WriteLine($"{DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)}: Request Charge of InsertOrMerge Operation: {result.RequestCharge}"); Console.WriteLine($"{DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)}: Added entity {entity} to the table {table.Name}"); } return(insertedActivity); } catch (StorageException e) { Console.WriteLine($"{DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)}: An exception has occured", e); throw; } }
public async Task <HttpStatusCode> AddChannelEvent(string eventType, ChannelActivityEntity entity) { if (string.IsNullOrEmpty(eventType)) { throw new ArgumentNullException(nameof(eventType)); } if (!_urlDictionary.ContainsKey(eventType)) { throw new ArgumentException($"The url for {eventType} is not available. Please update your appsettings and try again", nameof(eventType)); } var postData = new FormUrlEncodedContent(new[] { new KeyValuePair <string, string>("viewer", entity.Viewer), new KeyValuePair <string, string>("activity", entity.Activity), new KeyValuePair <string, string>("channel", entity.PartitionKey), new KeyValuePair <string, string>("timestamp", entity.Timestamp.DateTime.ToRowKeyString()) }); var uri = _urlDictionary[eventType]; var response = await _httpClient.PostAsync(uri, postData); response.EnsureSuccessStatusCode(); return(response.StatusCode); }
public static async Task <ChannelActivityEntity> InsertOrMergeEntityAsync(CloudTable table, ChannelActivityEntity entity) { if (entity == null) { throw new ArgumentNullException("entity"); } try { // Create the InsertOrReplace table operation TableOperation insertOrMergeOperation = TableOperation.InsertOrMerge(entity); // Execute the operation. TableResult result = await table.ExecuteAsync(insertOrMergeOperation); ChannelActivityEntity insertedActivity = result.Result as ChannelActivityEntity; // Get the request units consumed by the current operation. RequestCharge of a TableResult is only applied to Azure Cosmos DB if (result.RequestCharge.HasValue) { Console.WriteLine("Request Charge of InsertOrMerge Operation: " + result.RequestCharge); } return(insertedActivity); } catch (StorageException e) { Console.WriteLine(e.Message); Console.ReadLine(); throw; } }
private async Task Client_OnNewSubscriber(object sender, OnNewSubscriberArgs e) { Console.WriteLine($"{DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)}: New Subscriber Posted"); var entity = new ChannelActivityEntity { PartitionKey = e.Channel, RowKey = DateTime.UtcNow.ToString(Constants.DATETIME_FORMAT).Replace(":", string.Empty).Replace("-", string.Empty).Replace(".", string.Empty), Activity = StreamActivity.UserSubscribed.ToString(), Viewer = e.Subscriber.Id }; await AddEntityToStorage(entity); }
private async Task DispatchSignalRMessage(ChannelActivityEntity entity) { try { await _hubConnection.StartAsync(); await _hubConnection.InvokeAsync("StreamUpdate", entity); } finally { await _hubConnection.StopAsync(); } }
private async Task Client_OnUserLeft(object sender, OnUserLeftArgs e) { Console.WriteLine( $"{DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)}: {e.Username} left the channel {e.Channel}"); var entity = new ChannelActivityEntity { PartitionKey = e.Channel, RowKey = DateTime.UtcNow.ToString(Constants.DATETIME_FORMAT).Replace(":", string.Empty).Replace("-", string.Empty).Replace(".", string.Empty), Activity = StreamActivity.UserLeft.ToString(), Viewer = e.Username }; await AddEntityToStorage(entity); }
private async Task Client_OnNewSubscriber(object sender, OnNewSubscriberArgs e) { var date = DateTime.UtcNow; _logger.LogInformation($"{date.ToRowKeyString()}: New Subscriber Posted"); var entity = new ChannelActivityEntity { PartitionKey = e.Channel, RowKey = date.ToRowKeyString(), Activity = StreamActivity.UserSubscribed.ToString(), Viewer = e.Subscriber.Id }; await Common.AddEntityToStorage(_tableClient, entity, _streamingTable).ConfigureAwait(false); await _zapierClient.AddChannelEvent(Constants.ZAPIER_EVENTTYPE_MESSAGE, entity).ConfigureAwait(false); }
private async Task Client_OnExisingUsersDetected(object sender, OnExistingUsersDetectedArgs e) { var date = DateTime.UtcNow; Console.WriteLine($"{date.ToString(CultureInfo.InvariantCulture)}: Existing users detected in {e.Channel}: {string.Join(", ",e.Users)}"); foreach (var user in e.Users) { var entity = new ChannelActivityEntity { PartitionKey = user, RowKey = date.ToString(Constants.DATETIME_FORMAT).Replace(":", string.Empty).Replace("-", string.Empty).Replace(".", string.Empty), Activity = StreamActivity.UserJoined.ToString(), Viewer = e.Channel }; await AddEntityToStorage(entity); } }
public async Task <IActionResult> ProcessStreamEvent(string channel) { _logger.LogFormattedMessage($"Processing Twitch webhook for event on channel: {channel}"); using var reader = new StreamReader(Request.Body); var messageText = await reader.ReadToEndAsync(); if (string.IsNullOrEmpty(messageText)) { _logger.LogError("The message body is empty"); return(new NoContentResult()); } // Check if the json["data"] has values. If so, join the Channel. If not, leave the channel var json = JObject.Parse(messageText); ChannelActivityEntity entity; if (json["data"].HasValues) { var startedAt = json["data"][0]["started_at"].ToString(); var result = DateTime.TryParse(startedAt, out DateTime date); entity = new ChannelActivityEntity { Activity = StreamActivity.StreamStarted.ToString(), PartitionKey = channel, RowKey = date.ToRowKeyString() }; } else { entity = new ChannelActivityEntity { Activity = StreamActivity.StreamStopped.ToString(), PartitionKey = channel, RowKey = DateTime.UtcNow.ToRowKeyString() }; } await _hubContext.Clients.All.SendAsync(SIGNALR_UPDATECHANNEL, entity); await _storageService.AddDataToStorage(entity, TABLE_STREAMING); _logger.LogFormattedMessage($"Completed processing Twitch webhook for event on channel: {channel}"); return(await Task.FromResult(NoContent())); }
public async Task ProcessFollowersQueueMessage( [QueueTrigger("followers-data")] string message, ILogger logger) { var json = JObject.Parse(message); var updates = json["data"].ToObject <List <TwitchWebhookFollowersResponse> >(); foreach (var update in updates) { var entity = new ChannelActivityEntity { Activity = StreamActivity.UserFollowed.ToString(), PartitionKey = update.ToName, RowKey = update.FollowedAt.ToString(Constants.DATETIME_FORMAT).Replace(":", string.Empty).Replace("-", string.Empty), Viewer = update.FromName }; await _storageService.AddDataToStorage(entity); } }
public async Task <IActionResult> PostFollowerUpdate([FromBody] object data, string channel) { var json = JObject.Parse(data.ToString()); var updates = json["data"].ToObject <List <TwitchWebhookFollowersResponse> >(); foreach (var update in updates) { var entity = new ChannelActivityEntity { Activity = StreamActivity.UserFollowed.ToString(), PartitionKey = channel, RowKey = update.FollowedAt.ToString("s").Replace(":", string.Empty).Replace("-", string.Empty), Viewer = update.FromName }; await _storageService.AddDataToStorage(entity); } return(NoContent()); }
public async Task AddDataToStorage(ChannelActivityEntity entity) { try { if (_tableClient == null) { CreateTableClient(_connectionString ?? _configuration[Constants.FX_CONFIG_CONNSTRING_STORAGE_NAME]); } var insertOperation = TableOperation.InsertOrMerge(entity); var table = _tableClient.GetTableReference(Constants.FX_CONFIG_TABLE_NAME_VALUE); await table.CreateIfNotExistsAsync(); var result = await table.ExecuteAsync(insertOperation); } catch (StorageException ex) { _logger.LogError($"{DateTime.UtcNow}: An exception has occurred: {ex.Message}", ex); throw; } }
private async Task AddEntityToStorage(ChannelActivityEntity entity) { //await Common.AddMessageToQueue(_queueClient, entity); await Common.InsertOrMergeEntityAsync(_tableClient, entity); }
public static async Task AddMessageToQueue(QueueClient queue, ChannelActivityEntity entity) { var json = JsonSerializer.Serialize(entity, typeof(ChannelActivityEntity), options: new JsonSerializerOptions { }); await queue.SendMessageAsync(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(json))); }
public async Task StreamUpdate(ChannelActivityEntity entity) { await Clients.All.SendAsync("StreamUpdate", entity); }