public void ValidateContainerBinding_PerformsExpectedValidations() { BlobAttribute attribute = new BlobAttribute("test/blob", FileAccess.Write); Mock<IBindableBlobPath> mockPath = new Mock<IBindableBlobPath>(MockBehavior.Strict); var ex = Assert.Throws<InvalidOperationException>(() => { BlobContainerBinding.ValidateContainerBinding(attribute, typeof(IEnumerable<CloudBlockBlob>), mockPath.Object); }); Assert.Equal("Only the 'Read' FileAccess mode is supported for blob container bindings.", ex.Message); attribute = new BlobAttribute("test/blob", FileAccess.Read); mockPath.Setup(p => p.BlobNamePattern).Returns("prefix"); ex = Assert.Throws<InvalidOperationException>(() => { BlobContainerBinding.ValidateContainerBinding(attribute, typeof(CloudBlobContainer), mockPath.Object); }); Assert.Equal("Only a container name can be specified when binding to CloudBlobContainer.", ex.Message); }
public async static Task Run([QueueTrigger("queue-image-insert")] MessageImage message, IBinder binder, ILogger log) { log.LogInformation($"Função ativada!"); using var webClient = new WebClient(); byte[] imageBytes = webClient.DownloadData(message.ImageUri.ToString()); var image = (Image)(new Bitmap(Image.FromStream(new MemoryStream(imageBytes)), new Size(150, 150))); var converter = new ImageConverter(); var img = (byte[])converter.ConvertTo(image, typeof(byte[])); var blobAttribute = new BlobAttribute($"imagens/{Guid.NewGuid()}.jpg", FileAccess.Write); var cloudBlobStream = await binder.BindAsync <ICloudBlob>(blobAttribute); await cloudBlobStream.UploadFromByteArrayAsync(img, 0, img.Length); await cloudBlobStream.Container.SetPermissionsAsync(new BlobContainerPermissions() { PublicAccess = BlobContainerPublicAccessType.Blob }); var connectionString = Environment.GetEnvironmentVariable("PostContext"); using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); var textSql = $@"UPDATE [dbo].[Posts] SET [UrlFoto] = '{cloudBlobStream.Uri}' WHERE Id = {message.Id}"; using (SqlCommand cmd = new SqlCommand(textSql, conn)) { var rowsAffected = cmd.ExecuteNonQuery(); log.LogInformation($"rowsAffected: {rowsAffected}"); } } log.LogInformation($"Função encerrada!"); }
public async Task DownloadPictures( [QueueTrigger(DownloadPng, Connection = "AzureWebJobsStorage")] DownloadPngMessage message, IBinder binder, [Table(PetsTable, Connection = "AzureWebJobsStorage")] IAsyncCollector <PetEntity> tables, ILogger log) { var correlationId = message.CorrelationId; using (log.BeginScope(new Dictionary <string, object>() { [nameof(correlationId)] = correlationId })) { log.LogInformation("Downloading image {name}", message.Name); var stream = await _pngService.GetPngAsync(message.Url); log.LogInformation("downloaded png"); var blobName = $"pets/{message.Name}.png"; var attribute = new BlobAttribute(blobName, FileAccess.Write) { Connection = "AzureWebJobsStorage" }; await using var blob = await binder.BindAsync <Stream>(attribute); await stream.CopyToAsync(blob); await tables.AddAsync(new PetEntity() { BlobUrl = $"https://{GetAccountName()}.blob.core.windows.net/{blobName}", PartitionKey = DateTime.UtcNow.Date.ToString("yy-MM-dd"), RowKey = message.Name }); await tables.FlushAsync(); log.LogInformation("Saved Blob and reference {name}", message.Name); } }
public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequestMessage req, IBinder binder, TraceWriter log) { var userId = Utils.WhoAmI(); var attribute = new BlobAttribute($"{userId}", FileAccess.Read); attribute.Connection = "ImageStorageAccount"; var userStorage = await binder.BindAsync <CloudBlobContainer>(attribute); await userStorage.CreateIfNotExistsAsync(); var blobs = await userStorage.ListBlobsSegmentedAsync(String.Empty, true, BlobListingDetails.All, Int32.MaxValue, null, new BlobRequestOptions(), new OperationContext()); var paths = blobs.Results.Where(x => !x.Uri.AbsoluteUri.Contains("_thumbnail.")) .Select(e => e.Uri.AbsoluteUri); var root = paths.GetHierarchy(userId); return(req.CreateResponse(HttpStatusCode.OK, root)); }
public static async Task Run([QueueTrigger("orders", Connection = "AzureWebJobsStorage")] Order order, ILogger log, // blob output binding i.e writes to the blob container //[Blob("licenses/{rand-guid}.lic")] TextWriter outputBlob, IBinder binder) { // when message is added to the orders queue this function is triggered and generates a license file for the added item in the blob storage. log.LogInformation($"Generating License for order : {order.OrderId}"); // to the blob storage myself at run time by using IBinder so that I can access the content/item coming in. var blobAttribute = new BlobAttribute("licenses/{order.OrderId}.lic"); var blobOutputBinding = await binder.BindAsync <TextWriter>(blobAttribute); // TextWriter: output binding property blobOutputBinding.WriteLine($"OrderId: {order.OrderId}"); blobOutputBinding.WriteLine($"Email: {order.Email}"); blobOutputBinding.WriteLine($"ProductId: {order.ProductId}"); blobOutputBinding.WriteLine($"PurchasedDate: {DateTime.UtcNow}"); log.LogInformation($"Generating License for order : {order.OrderId}"); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, IBinder binder) { { log.LogInformation("C# HTTP trigger function processed a request."); string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); Order Orderdata = JsonConvert.DeserializeObject <Order>(requestBody); Orderdata.OrderName = Orderdata.OrderName + "-received"; BlobAttribute dynamicBlobBinding = new BlobAttribute(blobPath: $"orders/{Orderdata.OrderId}/{Orderdata.OrderName}"); using (var writer = binder.Bind <TextWriter>(dynamicBlobBinding)) { writer.Write(JsonConvert.SerializeObject(Orderdata)); } return(new OkResult()); } }
public static async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, IBinder binder, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); ToDoItem item = JsonConvert.DeserializeObject<ToDoItem>(requestBody); item.Id = Guid.NewGuid().ToString(); BlobAttribute dynamicBlobBinding = new BlobAttribute(blobPath: $"todo/{item.Category}/{item.Id}"); using (var writer = binder.Bind<TextWriter>(dynamicBlobBinding)) { writer.Write(JsonConvert.SerializeObject(item)); } var responseMessage = "Ok added" + item.Id; return new OkObjectResult(responseMessage); }
private async Task UpdateHistory(Match match, Player player, Ability ability, IBinder binder, ILogger log) { var attr = new BlobAttribute(string.Format(HISTORY_PATH, ability.Id)); var blob = await binder.BindAsync <CloudBlockBlob>(attr); Action <AbilityHistory> updateFn = (history) => { var victory = match.Victory(player); var ancestry = (ability.HeroId == player.hero_id); var priority = player.PickPriority(); var date = DateTimeOffset.FromUnixTimeSeconds(match.start_time); var bounds = date.AddDays(-6); var mid = date.AddDays(-3); history.Total.Picks++; history.Total.Wins += victory ? 1 : 0; history.Total.Ancestry += ancestry ? 1 : 0; history.Total.Priority += priority; history.Data.Add(new AbilityHistoryVictory() { Timestamp = date, Victory = victory, Ancestry = ancestry, Priority = priority }); history.Data.RemoveAll(_ => _.Timestamp < bounds); var current = history.Data.Where(_ => _.Timestamp > mid).ToList(); history.Current.Picks = current.Count(); history.Current.Wins = current.Count(_ => _.Victory == true); history.Current.Ancestry = current.Count(_ => _.Ancestry == true); history.Current.Priority = current.Sum(_ => _.Priority); var previous = history.Data.Where(_ => _.Timestamp < mid).ToList(); history.Previous.Picks = previous.Count; history.Previous.Wins = previous.Count(_ => _.Victory == true); history.Previous.Ancestry = previous.Count(_ => _.Ancestry == true); history.Previous.Priority = previous.Sum(_ => _.Priority); }; await ProcessBlob(blob, updateFn, log); }
private async Task UpdateLeaderboard(int regionId, List <PlayerEntity> players, IBinder binder, ILogger log) { var collection = players.Select(_ => new LeaderboardEntity() { RegionId = int.Parse(_.PartitionKey), AccountId = uint.Parse(_.RowKey), Ranking = _.Ranking, Total = _.Total, WinRate = _.WinRate, }).ToList(); var identities = collection.Select(_ => _.SteamId).ToArray(); var profiles = await GetProfiles(regionId, identities); if (profiles.Count() > 0) { collection = collection.Join(profiles, _ => _.SteamId, _ => _.steamid, (lhs, rhs) => new LeaderboardEntity() { RegionId = lhs.RegionId, AccountId = lhs.AccountId, Ranking = lhs.Ranking, Total = lhs.Total, WinRate = lhs.WinRate, Persona = rhs.personaname, Avatar = rhs.avatarfull }).ToList(); } var model = new LeaderboardDetails() { Region = regionId, List = collection }; var attr = new BlobAttribute(string.Format(LEADERBOARD_PATH, regionId)); var writer = await binder.BindAsync <TextWriter>(attr); var json = JsonConvert.SerializeObject(model); await writer.WriteAsync(json); }
public async Task <IActionResult> Backup( [HttpTrigger(AuthorizationLevel.Function, "post", Route = nameof(Backup))] HttpRequest req, IBinder binder, CancellationToken cancellationToken, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); var accessToken = await _azureServiceTokenProvider.GetAccessTokenAsync(KeyVaultAccessTokenResource, cancellationToken : cancellationToken); using var httpClient = _httpClientFactory.CreateClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken); var tasks = _options.Secrets.Select(Backup); await Task.WhenAll(tasks); return(new OkResult()); async Task Backup(string secret) { var url = string.Format(BackupUrlTemplate, _options.KeyVaultName, secret); var backupResponse = await httpClient.PostAsync(url, null, cancellationToken); backupResponse.EnsureSuccessStatusCode(); var model = await backupResponse.Content.ReadAsAsync <BackupModel>(cancellationToken); var blobName = $"backups/{DateTime.Now:yy-MM-dd}/{secret}"; var attribute = new BlobAttribute(blobName, FileAccess.Write) { Connection = "AzureWebJobsStorage" }; var byteArray = Encoding.ASCII.GetBytes(model.Value); await using var stream = new MemoryStream(byteArray); await using var blob = await binder.BindAsync <Stream>(attribute, cancellationToken); await stream.CopyToAsync(blob, cancellationToken); } }
public static async Task <long> CopyFileToBlob([ActivityTrigger] string filePath, Binder binder, ILogger log) { long byteCount = new FileInfo(filePath).Length; // strip the drive letter prefix and convert to forward slashes string blobPath = filePath.Substring(Path.GetPathRoot(filePath).Length).Replace('\\', '/'); string outputLocation = $@"backups/Logs"; BlobAttribute attribute = new BlobAttribute(outputLocation, FileAccess.Write); attribute.Connection = System.Environment.GetEnvironmentVariable("blobConnectionString"); log.LogInformation($"Copying '{filePath}' to '{outputLocation}'. Total bytes = {byteCount}."); // copy the file contents into a blob using (Stream source = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (Stream destination = await binder.BindAsync <CloudBlobStream>(attribute)) //new BlobAttribute(outputLocation, FileAccess.Write))) { await source.CopyToAsync(destination); } return(byteCount); }
public static void ProcessLogQueue([QueueTrigger("logbatch")] string queueData, IBinder binder) { try { string data = queueData; string containerAndBlob = ""; BlobAttribute blobAttribute; if (Uri.IsWellFormedUriString(queueData, UriKind.Absolute)) { var uri = new Uri(queueData); containerAndBlob = uri.AbsolutePath.Substring(1); blobAttribute = new BlobAttribute(containerAndBlob, FileAccess.Read); data = queueData; using (var stream = binder.Bind <Stream>(blobAttribute)) { StreamReader reader = new StreamReader(stream); data = reader.ReadToEnd(); } } IEnumerable <SyncLogEntry> logBatch = JsonConvert.DeserializeObject <IEnumerable <SyncLogEntry> >(data); var res = SyncLogEntryUtil.ProcessCollection(logBatch); if (containerAndBlob.Length > 0) { //delete block blob //Must be "FileAccess.ReadWrite" blobAttribute = new BlobAttribute(containerAndBlob, FileAccess.ReadWrite); var blockBlob = binder.Bind <CloudBlockBlob>(blobAttribute); blockBlob.DeleteIfExists(); } } catch (Exception ex) { Logging.WriteToAppLog("Error processing queue 'logbatch'", System.Diagnostics.EventLogEntryType.Error, ex); } }
public override async Task BindAsync(BindingContext context) { string boundBlobPath = Path; if (context.BindingData != null) { boundBlobPath = _pathBindingTemplate.Bind(context.BindingData); } boundBlobPath = Resolve(boundBlobPath); var attribute = new BlobAttribute(boundBlobPath, Access); Attribute[] additionalAttributes = null; if (!string.IsNullOrEmpty(Metadata.Connection)) { additionalAttributes = new Attribute[] { new StorageAccountAttribute(Metadata.Connection) }; } RuntimeBindingContext runtimeContext = new RuntimeBindingContext(attribute, additionalAttributes); await BindStreamAsync(context.Value, Access, context.Binder, runtimeContext); }
public async Task Run( [QueueTrigger("xasa-newhire-queue", Connection = "AzureWebJobsStorage")] NewHire newHire, IBinder binder, ILogger log) { var subscriptionUri = "https://demo-neo.azure-api.net/setup/subscription"; var queryParams = new Dictionary <string, string> { { "name", newHire.Name } }; var subscriptionUriWithQueryParams = QueryHelpers.AddQueryString(subscriptionUri, queryParams); var result = await HttpClient.PostAsync(subscriptionUriWithQueryParams, null); if (result.IsSuccessStatusCode) { var subscription = await result.Content.ReadAsAsync <JToken>(); var dynamicBlobBinding = new BlobAttribute(blobPath: "xasa-subscriptions/{rand-guid}.json"); using (var writer = binder.Bind <TextWriter>(dynamicBlobBinding)) { writer.Write(subscription.ToString(Formatting.Indented)); } } }
public async Task <List <Leaderboard> > GetLeaderboard(int id, IBinder binder, ILogger log) { var attr = new BlobAttribute(string.Format(LEADERBOARD_PATH, id)); var data = await ReadData <LeaderboardDetails>(binder, attr); var regions = this.metaClient.GetRegionsMeta(); var collection = data.List .Join(regions, _ => _.RegionId, _ => _.id, (lhs, rhs) => new Leaderboard() { RegionGroup = rhs.group, RegionName = rhs.name, AccountId = lhs.AccountId, SteamId = lhs.SteamId, Persona = lhs.Persona, Avatar = lhs.Avatar, Total = lhs.Total, WinRate = lhs.WinRate, Ranking = lhs.Ranking, }).ToList(); return(collection); }
public static async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, TraceWriter log, IBinder binder) { var files = req.Form.Files; if (files.Count == 0) { return(new NoContentResult()); } for (int i = 0; i < req.Form.Files.Count; i++) { var file = req.Form.Files[i]; log.Info($"Upload to Blob: {file.FileName}"); // Upload to the Blob Storage var guid = Guid.NewGuid(); var path = $"images/{guid.ToString()}" + file.Name; var blobAttribute = new BlobAttribute(path, FileAccess.Write) { Connection = "AzureStorageConnectionString" }; using (var ms = new MemoryStream()) { file.CopyTo(ms); var fileBytes = ms.ToArray(); // Save to blob storage using (var writer = await binder.BindAsync <Stream>(blobAttribute)) { await writer.WriteAsync(fileBytes, 0, fileBytes.Length); } } } return(new OkResult()); }
// This function will get triggered/executed when a new message is written // on an Azure Queue called queue. public static void ProcessPdfFiles( [QueueTrigger("workitems")] string pdfFilename, [Blob("pdf-files/{queueTrigger}.pdf", FileAccess.Read)] Stream pdfBlob, IBinder binder, ILogger logger) { logger.LogInformation($"Start Processing: {pdfFilename}"); GhostscriptVersionInfo gvi = new GhostscriptVersionInfo(@"gsdll32.dll"); using (GhostscriptRasterizer _rasterizer = new GhostscriptRasterizer()) { logger.LogInformation($"Open: {pdfFilename}"); _rasterizer.Open(pdfBlob, gvi, true); for (int pageNumber = 1; pageNumber <= _rasterizer.PageCount; pageNumber++) { string pngFilename = $"{pdfFilename}-page-{pageNumber.ToString()}.png".ToLower(); logger.LogInformation($"pageFilePath: {pngFilename}"); BlobAttribute blobAttribute = new BlobAttribute($"png-files/{pngFilename}"); CloudBlockBlob pngBlob = binder.Bind <CloudBlockBlob>(blobAttribute); logger.LogInformation($"GetPage: {pageNumber}"); Image img = _rasterizer.GetPage(desired_x_dpi, desired_y_dpi, pageNumber); logger.LogInformation($"Save: {pngFilename}"); MemoryStream ms = new MemoryStream(); img.Save(ms, ImageFormat.Png); ms.Flush(); ms.Position = 0; pngBlob.UploadFromStream(ms); } } logger.LogInformation($"Finish Processing: {pdfFilename}"); }
/// <summary> /// This function will execute on a timer. For testing purposes, it is setup to execute every 30 seconds. /// Typically one would trigger these every 24 hours to ensure subscriptions don't expire. /// </summary> /// <param name="timer">Timer object containing schedule information.</param> /// <param name="binder">Binder object can be used to bind to remote resources such as Azure storage blobs, queues etc.</param> /// <param name="cancellationToken">A cancellation token that can be used for long executing functions, in case webjobs is shutting down.</param> /// <param name="log">Log object for adding diagnostic logs.</param> /// <returns></returns> public static async Task ManageSubscriptions( [TimerTrigger(Functions.SubscriptionRenewalSchedule, RunOnStartup = true)] TimerInfo timer, IBinder binder, CancellationToken cancellationToken, TextWriter log) { // Step#1: Obtain App only auth token string authority = string.Format( CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}", Functions.TenantId); ClientCredential clientCredential = new ClientCredential(Functions.ClientSecret); var app = new ConfidentialClientApplication(Functions.ClientId, authority, RedirectUri, clientCredential, null, new TokenCache()); string[] scopes = new string[] { "https://graph.microsoft.com/.default" }; AuthenticationResult authenticationResult = null; authenticationResult = await app.AcquireTokenForClientAsync(scopes); // Step#2: Check if a subscription already exists from a cache. We are using blob storage to cache the subscriptionId. // If a subscription doesn't exist in blob store, then we need to create one. BlobAttribute blobAttributeRead = new BlobAttribute(Functions.SubscriptionBlobName, FileAccess.Read); Stream steram = binder.Bind <Stream>(blobAttributeRead); StreamBinder streamBinder = new StreamBinder(); string subscriptionId = await streamBinder.ReadFromStreamAsync(steram, cancellationToken); bool subscriptionExists = false; string subscriptionsUrl = null; if (!string.IsNullOrWhiteSpace(subscriptionId)) { subscriptionsUrl = string.Format( CultureInfo.InvariantCulture, Functions.SubscriptionUrlTemplate, subscriptionId); using (HttpRequestMessage message = new HttpRequestMessage( HttpMethod.Get, subscriptionsUrl)) { message.Headers.Authorization = AuthenticationHeaderValue .Parse(authenticationResult.CreateAuthorizationHeader()); HttpResponseMessage response = await Functions.Client.SendAsync(message); subscriptionExists = response.IsSuccessStatusCode; } } if (!subscriptionExists) { Subscription subscription = new Subscription(); subscription.ChangeType = "updated,deleted"; subscription.ClientState = "mysecret"; subscription.ExpirationDateTime = DateTime.UtcNow.AddDays(2); subscription.NotificationUrl = Functions.NotificationUrl; subscription.Resource = "Users"; using (HttpRequestMessage message = new HttpRequestMessage( HttpMethod.Post, Functions.SubscriptionsEntitySetUrl)) { message.Content = new StringContent( JsonConvert.SerializeObject(subscription), Encoding.UTF8, Functions.ContentTypeApplicationJson); message.Headers.Authorization = AuthenticationHeaderValue .Parse(authenticationResult.CreateAuthorizationHeader()); HttpResponseMessage response = await Functions.Client.SendAsync(message); response.EnsureSuccessStatusCode(); subscription = await response.Content.ReadAsAsync <Subscription>(); BlobAttribute blobAttributeWrite = new BlobAttribute(Functions.SubscriptionBlobName, FileAccess.Write); Stream newState = binder.Bind <Stream>(blobAttributeWrite); await streamBinder.WriteToStreamAsync(subscription.Id, newState, cancellationToken); log.WriteLine("Created new subscription with id:" + subscription.Id); } } else { // Step#3: If a subscription already exists in blob store, then we will extend the expiration date by 1 day. Dictionary <string, string> update = new Dictionary <string, string>(); update.Add("expirationDateTime", DateTime.UtcNow.AddDays(1).ToString(Functions.ODataDateTimeFormat)); using (HttpRequestMessage message = new HttpRequestMessage( Functions.HttpMethodPatch, subscriptionsUrl)) { message.Content = new StringContent( JsonConvert.SerializeObject(update), Encoding.UTF8, Functions.ContentTypeApplicationJson); message.Headers.Authorization = AuthenticationHeaderValue .Parse(authenticationResult.CreateAuthorizationHeader()); HttpResponseMessage response = await Functions.Client.SendAsync(message); response.EnsureSuccessStatusCode(); log.WriteLine("Updated existing subscription with id:" + subscriptionId); } } }
internal static void ValidateContainerBinding(BlobAttribute attribute, Type parameterType, IBindableBlobPath path) { if (attribute.Access != null && attribute.Access != FileAccess.Read) { throw new InvalidOperationException("Only the 'Read' FileAccess mode is supported for blob container bindings."); } if (parameterType == typeof(CloudBlobContainer) && !string.IsNullOrEmpty(path.BlobNamePattern)) { throw new InvalidOperationException("Only a container name can be specified when binding to CloudBlobContainer."); } }
public async Task CloneNoDefaultCtorShortList() { // Use shorter parameter list. var a1 = new BlobAttribute("container/{name}.txt"); Dictionary<string, object> values = new Dictionary<string, object>() { { "name", "green" }, }; var ctx = GetCtx(values); var cloner = new AttributeCloner<BlobAttribute>(a1, GetBindingContract("name")); var attr2 = await cloner.ResolveFromBindingDataAsync(ctx); Assert.Equal("container/green.txt", attr2.BlobPath); Assert.Equal(a1.Access, attr2.Access); }
public async Task <Details> GetDetails(int id, IBinder binder, ILogger log) { try { var attr = new BlobAttribute(string.Format(DETAILS_PATH, id)); var data = await ReadData <PlayerDetail>(binder, attr); var heroes = metaClient.GetHeroes(); var skills = metaClient.GetSkills(); var details = new Details(); details.AccountId = id; var combatants = data.Combatants .OrderByDescending(_ => _.With.Count) .ThenByDescending(_ => _.Against.Count) .Take(99) .ToList(); var identities = combatants .Select(_ => _.SteamId) .Concat(new List <ulong>() { details.SteamId }) .ToArray(); var profiles = await GetProfiles(id, identities); var self = profiles.Where(_ => _.steamid == details.SteamId); details.Persona = self.Select(_ => _.personaname).FirstOrDefault(); details.Avatar = self.Select(_ => _.avatarfull).FirstOrDefault(); var friends = await GetFriends(details.SteamId); details.Summaries = await GetSummaries(id, binder, log); var query = combatants .Join(profiles, _ => _.SteamId, _ => _.steamid, (player, profile) => new { AccountId = player.AccountId, SteamId = player.SteamId, Persona = profile.personaname, Avatar = profile.avatarfull, Friend = friends.Any(x => x.SteamId == player.SteamId), With = player.With, Against = player.Against, }) .ToList(); details.Combatants = query .Select(_ => new DTO.PlayerSummary() { AccountId = _.AccountId, SteamId = _.SteamId, Persona = _.Persona, Avatar = _.Avatar, Friend = _.Friend, Total = _.With.Count + _.Against.Count, With = _.With.Count, VictoriesWith = _.With.Count(x => x.Victory == true), Against = _.Against.Count, VictoriesAgainst = _.Against.Count(x => x.Victory == false) }) .ToList(); var heroSummaries = heroes .Select(hero => new HeroSummary() { Id = hero.Id, Name = hero.Name, Image = hero.ImageIcon }) .ToList(); var with = query.SelectMany(_ => _.With.Select(x => new { AccountId = _.AccountId, SteamId = _.SteamId, Persona = _.Persona, Avatar = _.Avatar, Friend = _.Friend, MatchId = x.MatchId, Victory = x.Victory, Hero = x.Hero, Abilities = x.Abilities, })) .Join(heroes, _ => _.Hero, _ => _.Id, (lhs, rhs) => new PlayerHistory() { AccountId = lhs.AccountId, SteamId = lhs.SteamId, Persona = lhs.Persona, Avatar = lhs.Avatar, Friend = lhs.Friend, MatchId = lhs.MatchId, Victory = lhs.Victory, Hero = new HeroSummary() { Id = rhs.Id, Name = rhs.Name, Image = rhs.ImageIcon, }, Abilities = lhs.Abilities .Join(skills, _ => _, _ => _.Id, (abilityId, ability) => new AbilitySummary { Id = ability.Id, Name = ability.Name, Image = ability.Image, IsUltimate = ability.IsUltimate }) .OrderBy(_ => _.IsUltimate) .ToList() }) .ToList(); var against = query.SelectMany(_ => _.Against.Select(x => new { AccountId = _.AccountId, SteamId = _.SteamId, Persona = _.Persona, Avatar = _.Avatar, Friend = _.Friend, MatchId = x.MatchId, Victory = x.Victory, Hero = x.Hero, Abilities = x.Abilities, })) .Join(heroes, _ => _.Hero, _ => _.Id, (lhs, rhs) => new PlayerHistory() { AccountId = lhs.AccountId, SteamId = lhs.SteamId, Persona = lhs.Persona, Avatar = lhs.Avatar, Friend = lhs.Friend, MatchId = lhs.MatchId, Victory = lhs.Victory, Hero = new HeroSummary() { Id = rhs.Id, Name = rhs.Name, Image = rhs.ImageIcon, }, Abilities = lhs.Abilities .Join(skills, _ => _, _ => _.Id, (abilityId, ability) => new AbilitySummary { Id = ability.Id, Name = ability.Name, Image = ability.Image, IsUltimate = ability.IsUltimate }) .OrderBy(_ => _.IsUltimate) .ToList() }) .ToList(); foreach (var item in data.History) { var history = new DTO.History(); history.MatchId = item.MatchId; history.Date = item.Date; history.Victory = item.Victory; history.Hero = heroSummaries.Find(_ => _.Id == item.Hero); history.Abilities = item.Abilities .Join(skills, _ => _, _ => _.Id, (abilityId, ability) => new AbilitySummary { Id = ability.Id, Name = ability.Name, Image = ability.Image, IsUltimate = ability.IsUltimate }) .OrderBy(_ => _.IsUltimate) .ToList(); history.With = with.Where(_ => _.MatchId == item.MatchId).ToList(); history.Against = against.Where(_ => _.MatchId == item.MatchId).ToList(); details.History.Add(history); } details.History = details.History.OrderByDescending(_ => _.Date).ToList(); return(details); } catch (Exception ex) { log.LogError(ex.Message); return(null); } }
private async Task UpdateDetails(Match match, IBinder binder, ILogger log) { foreach (var player in match.players) { if (player.account_id == CATCH_ALL_ACCOUNT) { continue; } var attr = new BlobAttribute(string.Format(DETAILS_PATH, player.account_id)); var blob = await binder.BindAsync <CloudBlockBlob>(attr); Action <PlayerDetail> updateFn = (model) => { var date = DateTimeOffset.FromUnixTimeSeconds(match.start_time); model.History.Add(new Models.History() { MatchId = match.match_id, Region = metaClient.GetRegionId(match.cluster), Date = date, Hero = player.hero_id, Victory = match.Victory(player), Abilities = player.GetAbilities(metaClient).Select(_ => _.Id).ToList() }); foreach (var p in match.players) { if (p.account_id == CATCH_ALL_ACCOUNT) { continue; } if (p.account_id == player.account_id) { continue; } // If Exists var combatant = model.Combatants.Find(_ => _.AccountId == p.account_id); if (combatant == null) { combatant = new Models.PlayerSummary() { AccountId = p.account_id, }; model.Combatants.Add(combatant); } var history = new Models.History() { MatchId = match.match_id, Region = metaClient.GetRegionId(match.cluster), Date = date, Hero = p.hero_id, Victory = match.Victory(p), Abilities = p.GetAbilities(metaClient).Select(_ => _.Id).ToList() }; if (p.GetTeam() == player.GetTeam()) { combatant.With.Add(history); } else { combatant.Against.Add(history); } } }; await ProcessBlob(blob, updateFn, log); } }
public static T BindBlob <T>(this IBinder binder, string blobPath, FileAccess access) { var attribute = new BlobAttribute(blobPath, access); return(binder.Bind <T>(attribute)); }