using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sony.ChartBot.ChartApi; using Sony.ChartBot.Entities.ChartApi; using Sony.ChartBot.Entities.Storage; using Sony.ChartBot.Repository; using Sony.ChartBot.Messages.Helpers; using Sony.ChartBot.Messages.MessageBuilders; using System.Threading; using Hangfire; using Sony.ChartBot.Entities; using Sony.ChartBot.Entities.MessengerApi; using Sony.ChartBot.Helpers; using Sony.ChartBot.Tasks.DependencyResolution; namespace Sony.ChartBot.Tasks { public class SendChartMessagesToSubscribersTask : IScheduledTask { public ChartApiClient ChartApiClient { get; set; } public SubscriptionRepository SubscriptionRepository { get; set; } public CountryRepository CountryRepository { get; set; } public ErrorRepository ErrorRepository { get; set; } public MessageSender MessageSender { get; set; } public ChartTrackModelBuilder ChartTrackModelBuilder { get; set; } private readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1); public SendChartMessagesToSubscribersTask() { var ioc = IoC.Initialize(); ChartApiClient = ioc.GetInstance(); SubscriptionRepository = ioc.GetInstance(); CountryRepository = ioc.GetInstance(); ErrorRepository = ioc.GetInstance(); MessageSender = ioc.GetInstance(); ChartTrackModelBuilder = ioc.GetInstance(); } public string CronExpression => Cron.MinuteInterval(30); public async Task ExecuteAsync() { await _semaphoreSlim.WaitAsync(); try { var subscriptions = (await SubscriptionRepository.GetDueSubscriptionsAsync()) .GroupBy(s => s.UserId); var exceptions = new List(); foreach (var group in subscriptions) { var input = BuildInput(group.Key); try { await MessageSender.BuildAndSendMessagesAsync(input); foreach (var subscription in group) { try { await SendChartPositionMessageAsync(input, subscription); subscription.LatestSendoutDay = DateTime.Today; await SubscriptionRepository.UpdateSubscriptionAsync(subscription); } catch (Exception exception) { exceptions.Add(exception); } } } catch (Exception exception) { exceptions.Add(exception); } } if (exceptions.Any()) { throw new AggregateException(exceptions); } } catch (Exception exception) { ErrorRepository.LogException(exception); throw; } finally { _semaphoreSlim.Release(); } } private MessagingData BuildInput(string userId) { return new MessagingData { sender = new Sender { id = userId }, message = new Message { text = "[subscription]" } }; } private async Task SendChartPositionMessageAsync(MessagingData input, SubscriptionRecord subscription) { string trackName, artistName, countryCode; if (string.IsNullOrWhiteSpace(subscription.TrackReference) || !new TrackReferenceGenerator().TryParseTrackReference(subscription.TrackReference, out artistName, out trackName, out countryCode)) { throw new Exception($"Invalid track reference for subscription: {subscription.TrackReference}"); } var country = CountryRepository.GetSupportedCountry(countryCode); if (country == null) { throw new Exception($"Invalid country reference for subscription: {countryCode}"); } var chartResponse = await ChartApiClient.GetChartPositionsAsync(artistName, countryCode, trackName); if (chartResponse == null) { await MessageSender.BuildAndSendMessagesAsync( input, artistName); } else if (!chartResponse.Tracks.Any()) { var model = await ChartTrackModelBuilder.BuildModel(subscription.TrackReference, input.sender.id); await MessageSender .BuildAndSendMessagesAsync( input, model); } else { var model = await ChartTrackModelBuilder.BuildModels(chartResponse, country, input.sender.id, subscriptionStatusDefault: true); await MessageSender .BuildAndSendMessagesAsync>( input, model); } } } }