using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Nettle; using Wabbajack.Common; using Wabbajack.Common.Serialization.Json; using Wabbajack.Lib; using Wabbajack.Lib.ModListRegistry; using Wabbajack.Server; using Wabbajack.Server.DataLayer; using Wabbajack.Server.DTOs; using Wabbajack.Server.Services; namespace Wabbajack.BuildServer.Controllers { [ApiController] [Route("/lists")] public class ListsStatus : ControllerBase { private ILogger _logger; private ListValidator _validator; public ListsStatus(ILogger logger, ListValidator validator) { _logger = logger; _validator = validator; } [HttpGet] [Route("status.json")] public async Task> HandleGetLists() { return (_validator.Summaries).Select(d => d.Summary); } private static readonly Func HandleGetRssFeedTemplate = NettleEngine.GetCompiler().Compile(@" {{lst.Name}} - Broken Mods http://build.wabbajack.org/status/{{lst.Name}}.html These are mods that are broken and need updating {{ each $.failed }} {{$.Archive.Name}} {{$.Archive.Hash}} {{$.Archive.State.PrimaryKeyString}} {{$.Archive.Name}} {{/each}} "); [HttpGet] [Route("status/{Name}/broken.rss")] public async Task HandleGetRSSFeed(string Name) { var lst = await DetailedStatus(Name); var response = HandleGetRssFeedTemplate(new { lst, failed = lst.Archives.Where(a => a.IsFailing).ToList(), passed = lst.Archives.Where(a => !a.IsFailing).ToList() }); return new ContentResult { ContentType = "application/rss+xml", StatusCode = (int) HttpStatusCode.OK, Content = response }; } private static readonly Func HandleGetListTemplate = NettleEngine.GetCompiler().Compile(@"

{{lst.Name}} - {{lst.Checked}} - {{ago}}min ago

Failed ({{failed.Count}}):

    {{each $.failed }} {{if $.HasUrl}}
  • {{$.Name}}
  • {{else}}
  • {{$.Name}}
  • {{/if}} {{/each}}

Updated ({{updated.Count}}):

    {{each $.updated }} {{if $.HasUrl}}
  • {{$.Name}}
  • {{else}}
  • {{$.Name}}
  • {{/if}} {{/each}}

Mirrored ({{mirrored.Count}}):

    {{each $.mirrored }} {{if $.HasUrl}}
  • {{$.Name}}
  • {{else}}
  • {{$.Name}}
  • {{/if}} {{/each}}

Updating ({{updating.Count}}):

    {{each $.updating }} {{if $.HasUrl}}
  • {{$.Name}}
  • {{else}}
  • {{$.Name}}
  • {{/if}} {{/each}}

Passed ({{passed.Count}}):

    {{each $.passed }} {{if $.HasUrl}}
  • {{$.Name}}
  • {{else}}
  • {{$.Name}}
  • {{/if}} {{/each}}
"); [HttpGet] [Route("status/{Name}.html")] public async Task HandleGetListHtml(string Name) { var lst = await DetailedStatus(Name); var response = HandleGetListTemplate(new { lst, ago = (DateTime.UtcNow - lst.Checked).TotalMinutes, failed = lst.Archives.Where(a => a.IsFailing).ToList(), passed = lst.Archives.Where(a => !a.IsFailing).ToList(), updated = lst.Archives.Where(a => a.ArchiveStatus == ArchiveStatus.Updated).ToList(), updating = lst.Archives.Where(a => a.ArchiveStatus == ArchiveStatus.Updating).ToList(), mirrored = lst.Archives.Where(a => a.ArchiveStatus == ArchiveStatus.Mirrored).ToList() }); return new ContentResult { ContentType = "text/html", StatusCode = (int) HttpStatusCode.OK, Content = response }; } [HttpGet] [Route("status/{Name}.json")] [ResponseCache(Duration = 60 * 5)] public async Task HandleGetListJson(string Name) { var lst = await DetailedStatus(Name); if (lst == null) return NotFound(); return Ok(lst.ToJson()); } private async Task DetailedStatus(string Name) { var results = _validator.Summaries .Select(d => d.Detailed) .FirstOrDefault(d => d.MachineName == Name); if (results == null) return null; results!.Archives.Do(itm => { if (string.IsNullOrWhiteSpace(itm.Archive.Name)) itm.Archive.Name = itm.Archive.State.PrimaryKeyString; }); results.Archives = results.Archives.OrderBy(a => a.Name).ToList(); return results; } [HttpGet] [Route("status/badge.json")] public async Task HandleGitHubBadge() { //var failing = _validator.Summaries.Select(x => x.Summary.Failed).Aggregate((x, y) => x + y); var succeeding = _validator.Summaries.Select(x => x.Summary.Passed).Aggregate((x, y) => x + y); var total = _validator.Summaries.Count(); double ration = total / (double)succeeding * 100.0; string color; if (ration >= 95) color = "brightgreen"; else if (ration >= 80) color = "green"; else if (ration >= 50) color = "yellowgreen"; else if (ration >= 20) color = "orange"; else color = "red"; Response.ContentType = "application/json"; return Ok(new Badge("Modlist Availability", $"{ration}%"){color = color}); } [HttpGet] [Route("status/{Name}/badge.json")] public async Task HandleNamedGitHubBadge(string Name) { var info = _validator.Summaries.Select(x => x.Summary) .FirstOrDefault(x => x.MachineURL == Name); if (info == null) return new NotFoundObjectResult("Not Found!"); var failing = info.HasFailures; Response.ContentType = "application/json"; return Ok(new Badge(info.Name, failing ? "Failing" : "Succeeding"){color = failing ? "red" : "green"}); } } }