wabbajack/Wabbajack.BuildServer/Models/Jobs/UpdateModLists.cs

189 lines
6.5 KiB
C#
Raw Normal View History

2020-01-09 12:14:48 +00:00
using System;
using System.Linq;
using System.Threading.Tasks;
using Wabbajack.BuildServer.Model.Models;
2020-01-09 12:14:48 +00:00
using Wabbajack.BuildServer.Models.JobQueue;
using Wabbajack.Common;
using Wabbajack.Lib;
using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.ModListRegistry;
using Wabbajack.Lib.NexusApi;
using Wabbajack.Lib.Validation;
2020-01-09 12:14:48 +00:00
namespace Wabbajack.BuildServer.Models.Jobs
{
public class UpdateModLists : AJobPayload, IFrontEndJob
2020-01-09 12:14:48 +00:00
{
public override string Description => "Validate curated modlists";
public override async Task<JobResult> Execute(SqlService sql, AppSettings settings)
2020-01-09 12:14:48 +00:00
{
Utils.Log("Starting Modlist Validation");
var modlists = await ModlistMetadata.LoadFromGithub();
using (var queue = new WorkQueue())
{
2020-03-22 15:50:53 +00:00
var whitelists = new ValidateModlist();
await whitelists.LoadListsFromGithub();
foreach (var list in modlists)
2020-01-09 12:14:48 +00:00
{
try
{
await ValidateList(sql, list, queue, whitelists);
2020-01-09 12:14:48 +00:00
}
catch (Exception ex)
{
Utils.Log(ex.ToString());
}
}
}
return JobResult.Success();
}
private async Task ValidateList(SqlService sql, ModlistMetadata list, WorkQueue queue, ValidateModlist whitelists)
2020-01-09 12:14:48 +00:00
{
2020-03-28 20:42:45 +00:00
var modlistPath = Consts.ModListDownloadFolder.Combine(list.Links.MachineURL + Consts.ModListExtension);
2020-01-09 12:14:48 +00:00
2020-03-28 20:42:45 +00:00
if (list.NeedsDownload(modlistPath))
2020-01-09 12:14:48 +00:00
{
2020-03-28 20:42:45 +00:00
modlistPath.Delete();
2020-01-09 12:14:48 +00:00
var state = DownloadDispatcher.ResolveArchive(list.Links.Download);
Utils.Log($"Downloading {list.Links.MachineURL} - {list.Title}");
2020-03-28 20:42:45 +00:00
await state.Download(modlistPath);
2020-01-09 12:14:48 +00:00
}
else
{
Utils.Log($"No changes detected from downloaded modlist");
}
2020-03-28 20:42:45 +00:00
Utils.Log($"Loading {modlistPath}");
2020-01-09 12:14:48 +00:00
2020-03-28 20:42:45 +00:00
var installer = AInstaller.LoadFromFile(modlistPath);
2020-01-09 12:14:48 +00:00
Utils.Log($"{installer.Archives.Count} archives to validate");
DownloadDispatcher.PrepareAll(installer.Archives.Select(a => a.State));
2020-01-09 12:14:48 +00:00
var validated = (await installer.Archives
.PMap(queue, async archive =>
{
var isValid = await IsValid(sql, whitelists, archive);
return new DetailedStatusItem {IsFailing = !isValid, Archive = archive};
2020-01-09 12:14:48 +00:00
}))
.ToList();
var status = new DetailedStatus
{
Name = list.Title,
Archives = validated.OrderBy(v => v.Archive.Name).ToList(),
DownloadMetaData = list.DownloadMetadata,
HasFailures = validated.Any(v => v.IsFailing)
};
var dto = new ModListStatus
{
Id = list.Links.MachineURL,
Summary = new ModlistSummary
{
Name = status.Name,
MachineURL = list.Links?.MachineURL ?? status.Name,
2020-01-09 12:14:48 +00:00
Checked = status.Checked,
Failed = status.Archives.Count(a => a.IsFailing),
Passed = status.Archives.Count(a => !a.IsFailing),
},
DetailedStatus = status,
Metadata = list
};
Utils.Log(
$"Writing Update for {dto.Summary.Name} - {dto.Summary.Failed} failed - {dto.Summary.Passed} passed");
await sql.UpdateModListStatus(dto);
Utils.Log(
$"Done updating {dto.Summary.Name}");
2020-01-09 12:14:48 +00:00
}
private async Task<bool> IsValid(SqlService sql, ValidateModlist whitelists, Archive archive)
{
try
{
if (!archive.State.IsWhitelisted(whitelists.ServerWhitelist)) return false;
try
{
if (archive.State is NexusDownloader.State state)
{
if (await ValidateNexusFast(sql, state)) return true;
}
else if (archive.State is GoogleDriveDownloader.State)
{
// Disabled for now
return true;
}
else if (archive.State is HTTPDownloader.State hstate &&
hstate.Url.StartsWith("https://wabbajack"))
{
return true;
}
else
{
if (await archive.State.Verify(archive)) return true;
}
}
catch (Exception)
{
// ignored
}
Utils.Log($"{archive.State.PrimaryKeyString} is broken, looking for upgrade: {archive.Name}");
var result = await ClientAPI.GetModUpgrade(archive.Hash);
if (result != null)
{
Utils.Log($"{archive.State.PrimaryKeyString} is broken, upgraded to {result.State.PrimaryKeyString} {result.Name}");
return true;
}
Utils.Log($"{archive.State.PrimaryKeyString} is broken, no alternative found");
return false;
}
catch (Exception ex)
{
Utils.Log(ex.ToString());
return false;
}
}
private async Task<bool> ValidateNexusFast(SqlService sql, NexusDownloader.State state)
{
try
{
var modFiles = await sql.GetModFiles(state.Game, state.ModID);
if (modFiles == null)
{
Utils.Log($"No Cache for {state.PrimaryKeyString} falling back to HTTP");
var nexusApi = await NexusApiClient.Get();
2020-04-04 04:02:53 +00:00
modFiles = await nexusApi.GetModFiles(state.Game, state.ModID);
}
var found = modFiles.files
2020-04-03 03:57:59 +00:00
.FirstOrDefault(file => file.file_id == state.FileID && file.category_name != null);
return found != null;
}
2020-04-03 22:33:19 +00:00
catch (Exception)
{
return false;
}
}
2020-01-09 12:14:48 +00:00
}
}