2020-01-13 04:31:43 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net;
|
2020-01-08 04:41:50 +00:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
2020-01-13 04:31:43 +00:00
|
|
|
|
using Nettle;
|
2020-03-10 20:41:45 +00:00
|
|
|
|
using Wabbajack.BuildServer.Model.Models;
|
2020-04-13 23:31:48 +00:00
|
|
|
|
using Wabbajack.BuildServer.Models;
|
2020-02-27 13:46:34 +00:00
|
|
|
|
using Wabbajack.Common;
|
2020-04-13 23:31:48 +00:00
|
|
|
|
using Wabbajack.Lib.Downloaders;
|
2020-01-08 04:41:50 +00:00
|
|
|
|
using Wabbajack.Lib.ModListRegistry;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack.BuildServer.Controllers
|
|
|
|
|
{
|
|
|
|
|
[ApiController]
|
|
|
|
|
[Route("/lists")]
|
|
|
|
|
public class ListValidation : AControllerBase<ListValidation>
|
|
|
|
|
{
|
2020-04-05 21:15:01 +00:00
|
|
|
|
public ListValidation(ILogger<ListValidation> logger, SqlService sql) : base(logger, sql)
|
2020-01-08 04:41:50 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
2020-04-13 23:31:48 +00:00
|
|
|
|
|
|
|
|
|
public async Task<IEnumerable<(ModListSummary Summary, DetailedStatus Detailed)>> GetSummaries()
|
|
|
|
|
{
|
|
|
|
|
var data = await SQL.GetValidationData();
|
|
|
|
|
|
|
|
|
|
using var queue = new WorkQueue();
|
|
|
|
|
|
|
|
|
|
var results = data.ModLists.PMap(queue, list =>
|
|
|
|
|
{
|
|
|
|
|
var archives = list.ModList.Archives.Select(archive =>
|
|
|
|
|
{
|
|
|
|
|
switch (archive.State)
|
|
|
|
|
{
|
|
|
|
|
case NexusDownloader.State nexusState when data.NexusFiles.Contains((
|
|
|
|
|
nexusState.Game.MetaData().NexusGameId, nexusState.ModID, nexusState.FileID)):
|
|
|
|
|
return (archive, true);
|
|
|
|
|
case NexusDownloader.State nexusState:
|
|
|
|
|
return (archive, false);
|
|
|
|
|
case ManualDownloader.State _:
|
|
|
|
|
return (archive, true);
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
if (data.ArchiveStatus.TryGetValue((archive.State.PrimaryKeyString, archive.Hash),
|
|
|
|
|
out var isValid))
|
|
|
|
|
{
|
|
|
|
|
return (archive, isValid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (archive, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
var failedCount = archives.Count(f => !f.Item2);
|
|
|
|
|
var passCount = archives.Count(f => f.Item2);
|
|
|
|
|
|
|
|
|
|
var summary = new ModListSummary
|
|
|
|
|
{
|
|
|
|
|
Checked = DateTime.UtcNow,
|
|
|
|
|
Failed = failedCount,
|
|
|
|
|
MachineURL = list.Metadata.Links.MachineURL,
|
|
|
|
|
Name = list.Metadata.Title,
|
|
|
|
|
Passed = passCount
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var detailed = new DetailedStatus
|
|
|
|
|
{
|
|
|
|
|
Name = list.Metadata.Title,
|
|
|
|
|
Checked = DateTime.UtcNow,
|
|
|
|
|
DownloadMetaData = list.Metadata.DownloadMetadata,
|
|
|
|
|
HasFailures = failedCount > 0,
|
|
|
|
|
MachineName = list.Metadata.Links.MachineURL,
|
|
|
|
|
Archives = archives.Select(a => new DetailedStatusItem
|
|
|
|
|
{
|
|
|
|
|
Archive = a.archive, IsFailing = !a.Item2
|
|
|
|
|
}).ToList()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (summary, detailed);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return await results;
|
|
|
|
|
}
|
2020-01-13 04:31:43 +00:00
|
|
|
|
|
2020-01-08 04:41:50 +00:00
|
|
|
|
[HttpGet]
|
2020-01-09 13:36:27 +00:00
|
|
|
|
[Route("status.json")]
|
2020-04-08 04:19:36 +00:00
|
|
|
|
public async Task<IEnumerable<ModListSummary>> HandleGetLists()
|
2020-01-08 04:41:50 +00:00
|
|
|
|
{
|
2020-04-13 23:31:48 +00:00
|
|
|
|
return (await GetSummaries()).Select(d => d.Summary);
|
2020-01-08 04:41:50 +00:00
|
|
|
|
}
|
2020-01-13 04:31:43 +00:00
|
|
|
|
|
|
|
|
|
private static readonly Func<object, string> HandleGetRssFeedTemplate = NettleEngine.GetCompiler().Compile(@"
|
|
|
|
|
<?xml version=""1.0""?>
|
|
|
|
|
<rss version=""2.0"">
|
|
|
|
|
<channel>
|
|
|
|
|
<title>{{lst.Name}} - Broken Mods</title>
|
|
|
|
|
<link>http://build.wabbajack.org/status/{{lst.Name}}.html</link>
|
|
|
|
|
<description>These are mods that are broken and need updating</description>
|
|
|
|
|
{{ each $.failed }}
|
|
|
|
|
<item>
|
2020-02-27 13:46:34 +00:00
|
|
|
|
<title>{{$.Archive.Name}} {{$.Archive.Hash}} {{$.Archive.State.PrimaryKeyString}}</title>
|
2020-01-13 04:31:43 +00:00
|
|
|
|
<link>{{$.Archive.Name}}</link>
|
|
|
|
|
</item>
|
|
|
|
|
{{/each}}
|
|
|
|
|
</channel>
|
|
|
|
|
</rss>
|
|
|
|
|
");
|
|
|
|
|
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("status/{Name}/broken.rss")]
|
|
|
|
|
public async Task<ContentResult> HandleGetRSSFeed(string Name)
|
|
|
|
|
{
|
2020-04-13 23:31:48 +00:00
|
|
|
|
var lst = await DetailedStatus(Name);
|
2020-01-13 04:31:43 +00:00
|
|
|
|
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<object, string> HandleGetListTemplate = NettleEngine.GetCompiler().Compile(@"
|
|
|
|
|
<html><body>
|
|
|
|
|
<h2>{{lst.Name}} - {{lst.Checked}} - {{ago}}min ago</h2>
|
|
|
|
|
<h3>Failed ({{failed.Count}}):</h3>
|
|
|
|
|
<ul>
|
|
|
|
|
{{each $.failed }}
|
|
|
|
|
<li>{{$.Archive.Name}}</li>
|
|
|
|
|
{{/each}}
|
|
|
|
|
</ul>
|
|
|
|
|
<h3>Passed ({{passed.Count}}):</h3>
|
|
|
|
|
<ul>
|
|
|
|
|
{{each $.passed }}
|
|
|
|
|
<li>{{$.Archive.Name}}</li>
|
|
|
|
|
{{/each}}
|
|
|
|
|
</ul>
|
|
|
|
|
</body></html>
|
|
|
|
|
");
|
|
|
|
|
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("status/{Name}.html")]
|
|
|
|
|
public async Task<ContentResult> HandleGetListHtml(string Name)
|
|
|
|
|
{
|
|
|
|
|
|
2020-04-13 23:31:48 +00:00
|
|
|
|
var lst = await DetailedStatus(Name);
|
2020-01-13 04:31:43 +00:00
|
|
|
|
var response = HandleGetListTemplate(new
|
|
|
|
|
{
|
|
|
|
|
lst,
|
2020-01-13 22:55:55 +00:00
|
|
|
|
ago = (DateTime.UtcNow - lst.Checked).TotalMinutes,
|
2020-01-13 04:31:43 +00:00
|
|
|
|
failed = lst.Archives.Where(a => a.IsFailing).ToList(),
|
|
|
|
|
passed = lst.Archives.Where(a => !a.IsFailing).ToList()
|
|
|
|
|
});
|
|
|
|
|
return new ContentResult
|
|
|
|
|
{
|
|
|
|
|
ContentType = "text/html",
|
|
|
|
|
StatusCode = (int) HttpStatusCode.OK,
|
|
|
|
|
Content = response
|
|
|
|
|
};
|
|
|
|
|
}
|
2020-02-27 13:46:34 +00:00
|
|
|
|
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("status/{Name}.json")]
|
2020-04-13 23:31:48 +00:00
|
|
|
|
public async Task<IActionResult> HandleGetListJson(string Name)
|
2020-02-27 13:46:34 +00:00
|
|
|
|
{
|
2020-04-13 23:31:48 +00:00
|
|
|
|
return Ok((await DetailedStatus(Name)).ToJson());
|
2020-02-27 13:46:34 +00:00
|
|
|
|
}
|
2020-01-13 04:31:43 +00:00
|
|
|
|
|
2020-04-13 23:31:48 +00:00
|
|
|
|
private async Task<DetailedStatus> DetailedStatus(string Name)
|
|
|
|
|
{
|
|
|
|
|
return (await GetSummaries())
|
|
|
|
|
.Select(d => d.Detailed)
|
|
|
|
|
.FirstOrDefault(d => d.MachineName == Name);
|
|
|
|
|
}
|
2020-01-08 04:41:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|