public AiringRoutes( IIdDistributor airingIdDistributorSvc, IAiringIdService airingIdSvc, IAiringService airingSvc, IReportingService reporterSvc, IProductService productSvc, AiringValidator _validator, IQueueService queueSvc, Serilog.ILogger logger, IDestinationService destinationSvc ) : base("v1") { this.RequiresAuthentication(); #region "GET Operations" Get("/airing/{airingId}", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb()); var options = GetOptionsFromQueryString(); // These timers are added for instrumentation and will be removed // in the future Dictionary <string, object> routeStats = new Dictionary <string, object>(); long start = Stopwatch.GetTimestamp(); var airing = airingSvc.GetBy((string)_.airingId); routeStats.Add("rtAiring_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); var user = Context.User(); FilterDestinations(airing, user.Destinations.ToList()); ValidateRequest(airing, user.Brands); var airingLong = airing.ToBusinessModel <BLAiringModel.Airing, BLAiringLongModel.Airing>(); start = Stopwatch.GetTimestamp(); if (options.Contains(Appenders.File.ToString().ToLower())) { airingSvc.AppendFile(ref airingLong); } routeStats.Add("appendFile_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); start = Stopwatch.GetTimestamp(); if (options.Contains(Appenders.Title.ToString().ToLower())) { airingSvc.AppendTitle(ref airingLong); } routeStats.Add("appendTitle_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); if (options.Contains(Appenders.Series.ToString().ToLower()) && (options.Contains(Appenders.File.ToString().ToLower()))) { airingSvc.AppendSeries(ref airingLong); } else if (options.Contains(Appenders.Series.ToString().ToLower())) { airingSvc.AppendSeries(ref airingLong); airingSvc.AppendFileBySeriesId(ref airingLong); } start = Stopwatch.GetTimestamp(); if (options.Contains(Appenders.Destination.ToString().ToLower())) { airingSvc.AppendDestinations(ref airingLong); } routeStats.Add("appendDestination_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); start = Stopwatch.GetTimestamp(); if (options.Contains(Appenders.Change.ToString().ToLower())) { airingSvc.AppendChanges(ref airingLong); } routeStats.Add("appendChanges_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); // Append status information if requested start = Stopwatch.GetTimestamp(); if (options.Contains(Appenders.Status.ToString().ToLower())) { airingSvc.AppendStatus(ref airingLong); } routeStats.Add("appendStatus_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); start = Stopwatch.GetTimestamp(); if (options.Contains(Appenders.Package.ToString().ToLower())) { airingSvc.AppendPackage(ref airingLong, Request.Headers.Accept); } routeStats.Add("appendPackage_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); start = Stopwatch.GetTimestamp(); if (options.Contains(Appenders.Premiere.ToString().ToLower())) { airingSvc.AppendPremiere(ref airingLong); } routeStats.Add("appendPremiere_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); start = Stopwatch.GetTimestamp(); if (options.Contains(Appenders.Version.ToString().ToLower())) { airingSvc.AppendVersion(ref airingLong); } routeStats.Add("appendVersion_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); start = Stopwatch.GetTimestamp(); var model = airingLong.ToViewModel <BLAiringLongModel.Airing, VMAiringLongModel.Airing>(); routeStats.Add("BLtoVM_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp())); if (!options.Contains(Appenders.Package.ToString().ToLower())) { model.Options.Packages = null; } routeStats.Add("context", "Instrumentation-GET-Airing-Route"); routeStats.Add("requestMethod", this.Request.Method); routeStats.Add("path", this.Request.Path); logger.Information("Request -" + this.Request.Path + "{@info}", routeStats); return(model); }); Get("/airings/titleId/{titleId}", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb()); var airings = airingSvc .GetNonExpiredBy((int)_.titleId, DateTime.UtcNow) .ToList(); var user = Context.User(); airings = FilterDestinations(airings, user.Destinations.ToList()); airings = FilterBrands(airings, user.Brands.ToList()); var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList(); return(viewModels); }); Get("/airings/seriesId/{seriesId}", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb()); var airings = airingSvc .GetNonExpiredBy((int)_.seriesId, DateTime.UtcNow, true) .ToList(); var user = Context.User(); airings = FilterDestinations(airings, user.Destinations.ToList()); airings = FilterBrands(airings, user.Brands.ToList()); var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList(); return(viewModels); }); Get("/airings/mediaId/{mediaId}", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb()); List <BLAiringModel.Airing> airings; DateTime startDate; DateTime endDate; if ((Request.Query.ContainsKey("startDate")) && (Request.Query.ContainsKey("endDate"))) { // validate ValidationResult results = new ValidationResult(); results = validateRequestDate(Request.Query["startDate"], Request.Query["endDate"]); if (results.Errors.Any()) // Verify if there are any validation errors. If so, return error { return(Negotiate.WithModel(results.Errors.Select(c => c.ErrorMessage)) .WithStatusCode(HttpStatusCode.BadRequest)); // Return status } startDate = getDate(Request.Query["startDate"]); endDate = getDate(Request.Query["endDate"]); if (startDate > endDate) { return(Negotiate.WithModel("Start date should be smaller than the end date") .WithStatusCode(HttpStatusCode.PreconditionFailed)); } airings = airingSvc.GetAiringsByMediaId((string)_.mediaId, startDate, endDate); } else { airings = new List <BLAiringModel.Airing>(airingSvc.GetByMediaId((string)_.mediaId)); } var user = Context.User(); airings = FilterDestinations(airings, user.Destinations.ToList()); airings = FilterBrands(airings, user.Brands.ToList()); var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList(); return(viewModels); }); Get("/airings/destination/{destination}", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb()); var airings = airingSvc .GetNonExpiredBy((string)_.destination, DateTime.UtcNow) .ToList(); var user = Context.User(); airings = FilterDestinations(airings, user.Destinations.ToList()); airings = FilterBrands(airings, user.Brands.ToList()); var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList(); return(viewModels); }); Get("/airings/brand/{brand}/destination/{destination}", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb()); List <BLAiringModel.Airing> airings = airingSvc .GetBy((string)_.brand, (string)_.destination, (DateTime)Request.Query["startDate"], (DateTime)Request.Query["endDate"], Request.Query["airingStatus"]); var user = Context.User(); airings = FilterDestinations(airings, user.Destinations.ToList()); airings = FilterBrands(airings, user.Brands.ToList()); var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList(); return(viewModels); }); #endregion #region "POST Operations" Post("/airing/task", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb()); var request = this.Bind <TaskViewModel>(); airingSvc.UpdateTask(request.AiringIds, request.Tasks); return(new { request.AiringIds, Message = "updated successfully" }); }); Post("/airing/send/{airingId}", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb()); if (!airingSvc.IsAiringExists((string)_.airingId)) { return(Negotiate.WithModel("airingId not found") .WithStatusCode(HttpStatusCode.NotFound)); } airingSvc.PushToQueues(new List <string> { (string)_.airingId }); return(new { AiringId = (string)_.airingId, Message = "AiringId flagged for delivery for valid queues" }); }); Post("/airing/deliver/{airingId}", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb()); if (!airingSvc.IsAiringExists((string)_.airingId)) { return(Negotiate.WithModel("airingId not found") .WithStatusCode(HttpStatusCode.NotFound)); } airingSvc.PushToQueues(new List <string> { (string)_.airingId }); return(new { AiringId = (string)_.airingId, Message = "AiringId flagged for delivery for valid queues" }); }); Post("/airing/send", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb()); var request = this.Bind <QueuePushViewModel>(); var queueName = queueSvc.GetByApiKey(request.QueueName); if (queueName == null) { return(Negotiate.WithModel("Queue not found") .WithStatusCode(HttpStatusCode.NotFound)); } if (!queueName.Active) { return(Negotiate.WithModel("Inactive queue") .WithStatusCode(HttpStatusCode.PreconditionFailed)); } var invalidAirings = new List <string>(); var validAiringIds = new List <string>(); foreach (string airingId in request.AiringIds) { if (!airingSvc.IsAiringExists(airingId)) { invalidAirings.Add(airingId); } else { validAiringIds.Add(airingId); } } if (validAiringIds.Any()) { airingSvc.PushToQueue(request.QueueName, request.AiringIds); } return(new { validAiringIds = validAiringIds, invalidAiringsIds = invalidAirings, Message = "validAiringIds are flagged for delivery and delivered based on enabled options of the queue" }); }); Post("/airing/deliver", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb()); var request = this.Bind <QueuePushViewModel>(); var queueName = queueSvc.GetByApiKey(request.QueueName); if (queueName == null) { return(Negotiate.WithModel("Queue not found") .WithStatusCode(HttpStatusCode.NotFound)); } if (!queueName.Active) { return(Negotiate.WithModel("Inactive queue") .WithStatusCode(HttpStatusCode.PreconditionFailed)); } var invalidAirings = new List <string>(); var validAiringIds = new List <string>(); foreach (string airingId in request.AiringIds) { if (!airingSvc.IsAiringExists(airingId)) { invalidAirings.Add(airingId); } else { validAiringIds.Add(airingId); } } if (validAiringIds.Any()) { airingSvc.PushToQueue(request.QueueName, request.AiringIds); } return(new { AiringIds = validAiringIds, invalidAiringsIds = invalidAirings, Message = "AiringIds are flagged for delivery and delivered based on enabled options of the queue" }); }); Post("/airing/{prefix}", _ => { // Verify that the user has permission to POST this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb()); var user = Context.User(); // Bind POST request to data contract var request = this.Bind <VMAiringRequestModel.AiringRequest>(); try { // If the Airing provided in the request doesn't have an // AiringId, create new one. CurrentAiringId currentAiringId = null; if (string.IsNullOrEmpty(request.AiringId)) { currentAiringId = airingIdDistributorSvc.Distribute((string)_.prefix); request.AiringId = currentAiringId.AiringId; } else { try { var assetDetails = airingSvc.GetBy(request.AiringId); if (assetDetails.SequenceNumber != 0) { currentAiringId = new CurrentAiringId { SequenceNumber = assetDetails.SequenceNumber, BillingNumber = new BillingNumber { Current = assetDetails.BillingNumber.Current, Lower = assetDetails.BillingNumber.Lower, Upper = assetDetails.BillingNumber.Upper } }; } } catch (AiringNotFoundException e) { logger.Information("Airing released from other systems like turniverse"); } } // Translate data contract to airing business model var airing = Mapper.Map <BLAiringModel.Airing>(request); // validate List <ValidationResult> results = new List <ValidationResult>(); results.Add(_validator.Validate(airing, ruleSet: AiringValidationRuleSet.PostAiring.ToString())); // Verify if there are any validation errors. If so, return error if (results.Where(c => (!c.IsValid)).Count() > 0) { var message = results.Where(c => (!c.IsValid)) .Select(c => c.Errors.Select(d => d.ErrorMessage)); logger.Error("Failure ingesting released asset: {AssetId}", new Dictionary <string, object>() { { "airingid", request.AiringId }, { "mediaid", airing.MediaId }, { "error", message } }); // Return status return(Negotiate.WithModel(message) .WithStatusCode(HttpStatusCode.BadRequest)); } // Now that the validation is succesful, proceed to // persisting the data. But first, populate remaining // properties for the airing business model. if (currentAiringId != null) { airing.SequenceNumber = currentAiringId.SequenceNumber; airing.BillingNumber.Lower = currentAiringId.BillingNumber.Lower; airing.BillingNumber.Current = currentAiringId.BillingNumber.Current; airing.BillingNumber.Upper = currentAiringId.BillingNumber.Upper; } else { airing.BillingNumber = null; } airing.ReleaseOn = DateTime.UtcNow; airing.UserName = user.UserName; //Get the username // If flight information is provided in the airing, create // the corresponding product to destination mapping as defined // in ODT if (airing.Flights.SelectMany(f => f.Products).Any()) { productSvc.ProductDestinationConverter(ref airing); destinationSvc.FilterDestinationPropertiesDeliverablesAndCategoriesAndTransformTokens(ref airing); } else { // Retrieve destination related data - properties, deliverables and categories - lsand // augment it to airing destinationSvc.GetAiringDestinationRelatedData(ref airing); destinationSvc.FilterDestinationPropertiesDeliverablesAndCategoriesAndTransformTokens(ref airing); } // If the versions exist, create a mediaid based on the // provided version informtion,playlists and the network to which this // asset/airing belongs if (airing.Versions.Any()) { airingSvc.AugmentMediaId(ref airing); } // Finally, persist the airing data var savedAiring = airingSvc.Save(airing, request.Instructions.DeliverImmediately, true); // If immediate deliver requested, force push the airing to the // respective queues (based on: product=>destination=>queue relationship) if (request.Instructions.DeliverImmediately) { airingSvc.PushToQueues(new List <string> { savedAiring.AssetId }); } // Report status of this airing to monitoring system (digital fulfillment/logzio) reporterSvc.Report(savedAiring, airingSvc.IsAiringExists(savedAiring.AssetId)); logger.Information("Successfully ingested released asset: {Asset}", GeneratePostAiringpropertiesForLogzIO(savedAiring, user)); // Return airing model return(savedAiring.ToViewModel <BLAiringModel.Airing, VMAiringPostResponseModel.PostResponseAiring>()); } catch (Exception e) { logger.Error(e, "Failure ingesting released asset. AssetId:{@assetId}", request.AiringId); throw e; } }); #endregion #region "DELETE Operations" Delete("/airing", _ => { this.RequiresClaims(c => c.Type == HttpMethod.Delete.Verb()); var request = this.Bind <VMAiringRequestModel.AiringRequest>(); var airing = Mapper.Map <BLAiringModel.Airing>(request); // validate List <ValidationResult> results = new List <ValidationResult>(); results.Add(_validator.Validate(airing, ruleSet: AiringValidationRuleSet.DeleteAiring.ToString())); // Verify if there are any validation errors. If so, return error if (results.Where(c => (!c.IsValid)).Count() > 0) { // Return status return(Negotiate.WithModel(results.Where(c => (!c.IsValid)) .Select(c => c.Errors.Select(d => d.ErrorMessage))) .WithStatusCode(HttpStatusCode.BadRequest)); } var existingAiring = airingSvc.GetBy(airing.AssetId); ValidateRequest(existingAiring, Context.User().Brands); existingAiring.ReleaseBy = airing.ReleaseBy; existingAiring.ReleaseOn = DateTime.UtcNow; existingAiring.UserName = Context.User().UserName; existingAiring.DeliveredTo.Clear(); airingSvc.Delete(existingAiring); //Delete related packages of airing airingSvc.DeleteAiringMappedPackages(airing.AssetId); if (request.Instructions.DeliverImmediately) { airingSvc.PushToQueues(new List <string> { existingAiring.AssetId }); } reporterSvc.Report(existingAiring, false); return(new VMAiringLongModel.AiringMessage { AiringId = airing.AssetId, Message = "deleted successfully" }); }); #endregion }
public PlaylistRoutes( IAiringService airingSvc, AiringValidator validator, Serilog.ILogger logger ) : base("v1") { this.RequiresAuthentication(); #region "POST Operations" Post("/playlist/{airingid}", _ => { // Verify that the user has permission to POST this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb()); var airingId = (string)_.airingid; // Bind POST request to data contract var request = this.Bind <VMAiringRequestModel.PlayListRequest>(); try { BLAiringModel.Airing airing; if (airingSvc.IsAiringExists(airingId)) { airing = airingSvc.GetBy(airingId, AiringCollection.CurrentCollection); //Updates the airing with the given Playlist payload airing.PlayList = Mapper.Map <List <BLAiringModel.PlayItem> >(request.PlayList); airing.ReleaseBy = request.ReleasedBy; //Clears the existing delivery details airing.IgnoredQueues = new List <string>(); airing.DeliveredTo = new List <string>(); //Sets the date with the current date time airing.ReleaseOn = DateTime.UtcNow; //Sets the user name airing.UserName = Context.User().UserName; } else { var airingErrorMessage = string.IsNullOrWhiteSpace(airingId) ? "AiringId is required." : "Provided AiringId does not exists or expired."; // Return status return(Negotiate.WithModel(airingErrorMessage) .WithStatusCode(string.IsNullOrWhiteSpace(airingId) ? HttpStatusCode.BadRequest : HttpStatusCode.NotFound)); } // validate var results = new List <ValidationResult> { validator.Validate(airing, ruleSet: AiringValidationRuleSet.PostPlaylist.ToString()) }; // Verify if there are any validation errors. If so, return error if (results.Any(c => (!c.IsValid))) { var message = results.Where(c => (!c.IsValid)) .Select(c => c.Errors.Select(d => d.ErrorMessage)).ToList(); logger.Error("Failure ingesting playlist released asset: {AssetId}", new Dictionary <string, object>() { { "airingid", airingId }, { "mediaid", airing.MediaId }, { "error", message } }); // Return status return(Negotiate.WithModel(message) .WithStatusCode(HttpStatusCode.BadRequest)); } // If the versions exist, create a mediaid based on the // provided version informtion,playlists and the network to which this // asset/airing belongs if (airing.Versions.Any()) { airingSvc.AugmentMediaId(ref airing); } // Finally, persist the airing data airingSvc.Save(airing, false, true); return("Successfully updated the playlist."); } catch (Exception e) { logger.Error(e, "Failure ingesting playlist to airing. Airingid:{@airingId}", airingId); throw; } }); #endregion }