integrated the new download framework into the app

This commit is contained in:
Timothy Baldridge 2019-10-12 16:15:20 -06:00
parent 1e64544783
commit bf11273c15
18 changed files with 138 additions and 411 deletions

View File

@ -551,5 +551,11 @@ namespace Wabbajack.Common
{
return tv.ToJSON().FromJSONString<T>();
}
public static void Error(string msg)
{
Log(msg);
throw new Exception(msg);
}
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Security.Policy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Wabbajack.Common;
using Wabbajack.Downloaders;
using Wabbajack.Validation;
using Game = Wabbajack.Common.Game;
@ -56,7 +57,7 @@ namespace Wabbajack.Test
[TestMethod]
public void TestRightsFallthrough()
{
var permissions = validate.FilePermissions(new NexusMod()
var permissions = validate.FilePermissions(new NexusDownloader.State
{
Author = "bill",
GameName = "Skyrim",
@ -69,7 +70,7 @@ namespace Wabbajack.Test
permissions.CanModifyAssets.AssertIsFalse();
permissions.CanUseInOtherGames.AssertIsFalse();
permissions = validate.FilePermissions(new NexusMod()
permissions = validate.FilePermissions(new NexusDownloader.State
{
Author = "bob",
GameName = "Skyrim",
@ -82,7 +83,7 @@ namespace Wabbajack.Test
permissions.CanModifyAssets.AssertIsTrue();
permissions.CanUseInOtherGames.AssertIsTrue();
permissions = validate.FilePermissions(new NexusMod()
permissions = validate.FilePermissions(new NexusDownloader.State
{
Author = "bill",
GameName = "Fallout4",
@ -95,7 +96,7 @@ namespace Wabbajack.Test
permissions.CanModifyAssets.AssertIsTrue();
permissions.CanUseInOtherGames.AssertIsTrue();
permissions = validate.FilePermissions(new NexusMod()
permissions = validate.FilePermissions(new NexusDownloader.State
{
Author = "bill",
GameName = "Skyrim",
@ -108,7 +109,7 @@ namespace Wabbajack.Test
permissions.CanModifyAssets.AssertIsTrue();
permissions.CanUseInOtherGames.AssertIsTrue();
permissions = validate.FilePermissions(new NexusMod()
permissions = validate.FilePermissions(new NexusDownloader.State
{
Author = "bill",
GameName = "Skyrim",
@ -131,14 +132,18 @@ namespace Wabbajack.Test
GameType = Game.Skyrim,
Archives = new List<Archive>
{
new NexusMod
new Archive
{
GameName = "Skyrim",
Author = "bill",
ModID = "42",
FileID = "33",
State = new NexusDownloader.State
{
GameName = "Skyrim",
Author = "bill",
ModID = "42",
FileID = "33",
},
Hash = "DEADBEEF"
}
},
Directives = new List<Directive>
{
@ -196,44 +201,44 @@ namespace Wabbajack.Test
// Error due to file downloaded from 3rd party
modlist.GameType = Game.Skyrim;
modlist.Archives[0] = new DirectURLArchive()
modlist.Archives[0] = new Archive()
{
URL = "https://somebadplace.com",
State = new HTTPDownloader.State() { Url = "https://somebadplace.com" },
Hash = "DEADBEEF"
};
errors = validate.Validate(modlist);
Assert.AreEqual(errors.Count(), 1);
Assert.AreEqual(1, errors.Count());
// Ok due to file downloaded from whitelisted 3rd party
modlist.GameType = Game.Skyrim;
modlist.Archives[0] = new DirectURLArchive()
modlist.Archives[0] = new Archive
{
URL = "https://somegoodplace.com/myfile",
State = new HTTPDownloader.State { Url = "https://somegoodplace.com/baz.7z" },
Hash = "DEADBEEF"
};
errors = validate.Validate(modlist);
Assert.AreEqual(errors.Count(), 0);
Assert.AreEqual(0, errors.Count());
// Error due to file downloaded from bad 3rd party
modlist.GameType = Game.Skyrim;
modlist.Archives[0] = new GoogleDriveMod()
modlist.Archives[0] = new Archive
{
Id = "bleg",
State = new GoogleDriveDownloader.State { Id = "bleg"},
Hash = "DEADBEEF"
};
errors = validate.Validate(modlist);
Assert.AreEqual(errors.Count(), 1);
// Error due to file downloaded from good 3rd party
// Ok due to file downloaded from good google site
modlist.GameType = Game.Skyrim;
modlist.Archives[0] = new GoogleDriveMod()
modlist.Archives[0] = new Archive
{
Id = "googleDEADBEEF",
State = new GoogleDriveDownloader.State { Id = "googleDEADBEEF" },
Hash = "DEADBEEF"
};
errors = validate.Validate(modlist);
Assert.AreEqual(errors.Count(), 0);
Assert.AreEqual(0, errors.Count());
}

View File

@ -15,6 +15,7 @@ using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Wabbajack.Common;
using Wabbajack.Downloaders;
using Wabbajack.NexusApi;
using Wabbajack.UI;
@ -484,7 +485,10 @@ namespace Wabbajack
ApplyModlistProperties();
_slideShow.SlideShowElements = modlist.Archives.OfType<NexusMod>().Select(m =>
_slideShow.SlideShowElements = modlist.Archives
.Select(m => m.State)
.OfType<NexusDownloader.State>()
.Select(m =>
new Slide(NexusApiUtils.FixupSummary(m.ModName),m.ModID,
NexusApiUtils.FixupSummary(m.Summary), NexusApiUtils.FixupSummary(m.Author),
m.Adult,m.NexusURL,m.SlideShowPic)).ToList();

View File

@ -13,6 +13,7 @@ using System.Text.RegularExpressions;
using System.Web;
using VFS;
using Wabbajack.Common;
using Wabbajack.Downloaders;
using Wabbajack.NexusApi;
using Wabbajack.Validation;
using Directory = Alphaleonis.Win32.Filesystem.Directory;
@ -469,123 +470,21 @@ namespace Wabbajack
{
if (found.IniData == null)
Error($"No download metadata found for {found.Name}, please use MO2 to query info or add a .meta file and try again.");
var general = found.IniData.General;
if (general == null)
Error($"No General section in mod metadata found for {found.Name}, please use MO2 to query info or add the info and try again.");
Archive result;
var result = new Archive();
result.State = (AbstractDownloadState)DownloadDispatcher.ResolveArchive(found.IniData);
if (general.directURL != null && general.directURL.StartsWith("https://drive.google.com"))
{
var regex = new Regex("((?<=id=)[a-zA-Z0-9_-]*)|(?<=\\/file\\/d\\/)[a-zA-Z0-9_-]*");
var match = regex.Match(general.directURL);
result = new GoogleDriveMod
{
Id = match.ToString()
};
}
else if (general.directURL != null && general.directURL.StartsWith(Consts.MegaPrefix))
{
result = new MEGAArchive
{
URL = general.directURL
};
}
else if (general.directURL != null && general.directURL.StartsWith("https://www.dropbox.com/"))
{
var uri = new UriBuilder((string)general.directURL);
var query = HttpUtility.ParseQueryString(uri.Query);
if (query.GetValues("dl").Count() > 0)
query.Remove("dl");
query.Set("dl", "1");
uri.Query = query.ToString();
result = new DirectURLArchive
{
URL = uri.ToString()
};
}
else if (general.directURL != null &&
general.directURL.StartsWith("https://www.moddb.com/downloads/start"))
{
result = new MODDBArchive
{
URL = general.directURL
};
}
else if (general.directURL != null && general.directURL.StartsWith("http://www.mediafire.com/file/"))
{
Error("MediaFire links are not currently supported");
return null;
/*result = new MediaFireArchive()
{
URL = general.directURL
};*/
}
else if (general.directURL != null)
{
var tmp = new DirectURLArchive
{
URL = general.directURL
};
if (general.directURLHeaders != null)
{
tmp.Headers = new List<string>();
tmp.Headers.AddRange(general.directURLHeaders.Split('|'));
}
result = tmp;
}
else if (general.modID != null && general.fileID != null && general.gameName != null)
{
var nm = new NexusMod
{
GameName = general.gameName,
FileID = general.fileID,
ModID = general.modID,
Version = general.version ?? "0.0.0.0"
};
/*var info = new NexusApiClient().GetModInfo(nm);
nm.Author = info.author;
nm.UploadedBy = info.uploaded_by;
nm.UploaderProfile = info.uploaded_users_profile_url;
nm.ModName = info.name;
nm.SlideShowPic = info.picture_url;
nm.NexusURL = NexusApiUtils.GetModURL(info.game_name, info.mod_id);
nm.Summary = info.summary;
nm.Adult = info.contains_adult_content;*/
result = nm;
}
else if (general.manualURL != null)
{
result = new ManualArchive
{
URL = general.manualURL,
Notes = general.manualNotes,
};
}
else
{
Error($"No way to handle archive {found.Name} but it's required by the modlist");
return null;
}
if (result.State == null)
Error($"{found.Name} could not be handled by any of the downloaders");
result.Name = found.Name;
result.Hash = found.File.Hash;
result.Meta = found.Meta;
result.Size = found.File.Size;
if (result is ManualArchive) return result;
Info($"Checking link for {found.Name}");
var installer = new Installer("", null, "");
if (!installer.DownloadArchive(result, false))
if (!result.State.Verify())
Error(
$"Unable to resolve link for {found.Name}. If this is hosted on the Nexus the file may have been removed.");

View File

@ -4,6 +4,7 @@ using System.Collections.Generic;
using Compression.BSA;
using VFS;
using Wabbajack.Common;
using Wabbajack.Downloaders;
namespace Wabbajack
{
@ -218,81 +219,7 @@ namespace Wabbajack
public string Name;
public long Size;
}
[Serializable]
public class NexusMod : Archive
{
public string Author;
public string FileID;
public string GameName;
public string ModID;
public string UploadedBy;
public string UploaderProfile;
public string Version;
public string SlideShowPic;
public string ModName;
public string NexusURL;
public string Summary;
public bool Adult;
}
[Serializable]
public class ManualArchive : Archive
{
public string URL;
public string Notes;
}
[Serializable]
public class GoogleDriveMod : Archive
{
public string Id;
}
/// <summary>
/// URL that can be downloaded directly without any additional options
/// </summary>
[Serializable]
public class DirectURLArchive : Archive
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<string> Headers;
public string URL;
}
/// <summary>
/// An archive that requires additional HTTP headers.
/// </summary>
[Serializable]
public class DirectURLArchiveEx : DirectURLArchive
{
public Dictionary<string, string> Headers;
}
/// <summary>
/// Archive that comes from MEGA
/// </summary>
[Serializable]
public class MEGAArchive : DirectURLArchive
{
}
/// <summary>
/// Archive that comes from MODDB
/// </summary>
[Serializable]
public class MODDBArchive : DirectURLArchive
{
}
/// <summary>
/// Archive that comes from MediaFire
/// </summary>
[Serializable]
public class MediaFireArchive : DirectURLArchive
{
public AbstractDownloadState State { get; set; }
}
[Serializable]

View File

@ -30,5 +30,7 @@ namespace Wabbajack.Downloaders
/// </summary>
/// <returns></returns>
public abstract bool Verify();
public abstract IDownloader GetDownloader();
}
}

View File

@ -15,7 +15,8 @@ namespace Wabbajack.Downloaders
new DropboxDownloader(),
new GoogleDriveDownloader(),
new HTTPDownloader(),
new NexusDownloader()
new NexusDownloader(),
new ManualDownloader()
};
private static Dictionary<Type, IDownloader> _indexedDownloaders;

View File

@ -9,11 +9,6 @@ namespace Wabbajack.Downloaders
{
public class DropboxDownloader : IDownloader
{
public void Init()
{
}
public AbstractDownloadState GetDownloaderState(dynamic archive_ini)
{
var urlstring = archive_ini?.General?.directURL;
@ -34,5 +29,9 @@ namespace Wabbajack.Downloaders
Url = uri.ToString().Replace("dropbox.com:443/", "dropbox.com/")
};
}
public void Prepare()
{
}
}
}

View File

@ -29,6 +29,10 @@ namespace Wabbajack.Downloaders
return null;
}
public void Prepare()
{
}
public class State : AbstractDownloadState
{
public string Id { get; set; }
@ -58,6 +62,11 @@ namespace Wabbajack.Downloaders
{
return ToHttpState().Verify();
}
public override IDownloader GetDownloader()
{
return DownloadDispatcher.GetInstance<GoogleDriveDownloader>();
}
}
}
}

View File

@ -36,6 +36,10 @@ namespace Wabbajack.Downloaders
return null;
}
public void Prepare()
{
}
public class State : AbstractDownloadState
{
public string Url { get; set; }
@ -119,6 +123,11 @@ namespace Wabbajack.Downloaders
{
return DoDownload(new Archive {Name = ""}, "", false);
}
public override IDownloader GetDownloader()
{
return DownloadDispatcher.GetInstance<HTTPDownloader>();
}
}
}
}

View File

@ -7,8 +7,13 @@ using Wabbajack.Validation;
namespace Wabbajack.Downloaders
{
interface IDownloader
public interface IDownloader
{
AbstractDownloadState GetDownloaderState(dynamic archive_ini);
/// <summary>
/// Called before any downloads are inacted by the installer;
/// </summary>
void Prepare();
}
}

View File

@ -24,6 +24,10 @@ namespace Wabbajack.Downloaders
return null;
}
public void Prepare()
{
}
public class State : HTTPDownloader.State
{
public override void Download(Archive a, string destination)

View File

@ -39,6 +39,23 @@ namespace Wabbajack.Downloaders
return null;
}
public void Prepare()
{
var client = new NexusApiClient();
var status = client.GetUserStatus();
if (!client.IsAuthenticated)
{
Utils.Error($"Authenticating for the Nexus failed. A nexus account is required to automatically download mods.");
return;
}
if (!status.is_premium)
{
Utils.Error($"Automated installs with Wabbajack requires a premium nexus account. {client.Username} is not a premium account.");
return;
}
}
public class State : AbstractDownloadState
{
public string Author;
@ -96,6 +113,11 @@ namespace Wabbajack.Downloaders
}
}
public override IDownloader GetDownloader()
{
return DownloadDispatcher.GetInstance<NexusDownloader>();
}
}
}
}

View File

@ -11,6 +11,7 @@ using System.Text.RegularExpressions;
using System.Windows;
using VFS;
using Wabbajack.Common;
using Wabbajack.Downloaders;
using Wabbajack.NexusApi;
using Wabbajack.Validation;
using Directory = Alphaleonis.Win32.Filesystem.Directory;
@ -162,7 +163,8 @@ namespace Wabbajack
private void AskToEndorse()
{
var mods = ModList.Archives
.OfType<NexusMod>()
.Select(m => m.State)
.OfType<NexusDownloader.State>()
.GroupBy(f => (f.GameName, f.ModID))
.Select(mod => mod.First())
.ToArray();
@ -419,24 +421,11 @@ namespace Wabbajack
Info($"Missing {missing.Count} archives");
Info("Getting Nexus API Key, if a browser appears, please accept");
if (ModList.Archives.OfType<NexusMod>().Any())
{
var client = new NexusApiClient();
var status = client.GetUserStatus();
if (!client.IsAuthenticated)
{
Error(
$"Authenticating for the Nexus failed. A nexus account is required to automatically download mods.");
return;
}
if (!status.is_premium)
{
Error(
$"Automated installs with Wabbajack requires a premium nexus account. {client.Username} is not a premium account.");
return;
}
}
var dispatchers = ModList.Archives.Select(m => m.State.GetDownloader()).Distinct();
foreach (var dispatcher in dispatchers)
dispatcher.Prepare();
DownloadMissingArchives(missing);
}
@ -460,39 +449,7 @@ namespace Wabbajack
{
try
{
switch (archive)
{
case NexusMod a:
string url;
/*
try
{
url = new NexusApiClient().GetNexusDownloadLink(a, !download);
if (!download) return true;
}
catch (Exception ex)
{
Info($"{a.Name} - Error Getting Nexus Download URL - {ex.Message}");
return false;
}
Info($"Downloading Nexus Archive - {archive.Name} - {a.GameName} - {a.ModID} - {a.FileID}");
DownloadURLDirect(archive, url);
*/
return true;
case MEGAArchive a:
return DownloadMegaArchive(a, download);
case GoogleDriveMod a:
return DownloadGoogleDriveArchive(a, download);
case MODDBArchive a:
return DownloadModDBArchive(archive, (archive as MODDBArchive).URL, download);
case MediaFireArchive a:
return false;
//return DownloadMediaFireArchive(archive, a.URL, download);
case DirectURLArchive a:
return DownloadURLDirect(archive, a.URL, headers: a.Headers, download: download);
}
archive.State.Download(archive, Path.Combine(DownloadFolder, archive.Name));
}
catch (Exception ex)
{
@ -504,128 +461,6 @@ namespace Wabbajack
return false;
}
private void DownloadMediaFireArchive(Archive a, string url)
{
var client = new HttpClient();
var result = client.GetStringSync(url);
var regex = new Regex("(?<= href =\\\").*\\.mediafire\\.com.*(?=\\\")");
var confirm = regex.Match(result);
DownloadURLDirect(a, confirm.ToString(), client);
}
private bool DownloadMegaArchive(MEGAArchive m, bool download)
{
var client = new MegaApiClient();
Status("Logging into MEGA (as anonymous)");
client.LoginAnonymous();
var file_link = new Uri(m.URL);
var node = client.GetNodeFromLink(file_link);
if (!download) return true;
Status($"Downloading MEGA file: {m.Name}");
var output_path = Path.Combine(DownloadFolder, m.Name);
client.DownloadFile(file_link, output_path);
return true;
}
private bool DownloadGoogleDriveArchive(GoogleDriveMod a, bool download)
{
var initial_url = $"https://drive.google.com/uc?id={a.Id}&export=download";
var client = new HttpClient();
var result = client.GetStringSync(initial_url);
var regex = new Regex("(?<=/uc\\?export=download&amp;confirm=).*(?=;id=)");
var confirm = regex.Match(result);
return DownloadURLDirect(a, $"https://drive.google.com/uc?export=download&confirm={confirm}&id={a.Id}",
client, download);
}
private bool DownloadModDBArchive(Archive archive, string url, bool download)
{
var client = new HttpClient();
var result = client.GetStringSync(url);
var regex = new Regex("https:\\/\\/www\\.moddb\\.com\\/downloads\\/mirror\\/.*(?=\\\")");
var match = regex.Match(result);
return DownloadURLDirect(archive, match.Value, download: download);
}
private bool DownloadURLDirect(Archive archive, string url, HttpClient client = null, bool download = true,
List<string> headers = null)
{
try
{
if (client == null)
{
client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", Consts.UserAgent);
}
if (headers != null)
foreach (var header in headers)
{
var idx = header.IndexOf(':');
var k = header.Substring(0, idx);
var v = header.Substring(idx + 1);
client.DefaultRequestHeaders.Add(k, v);
}
long total_read = 0;
var buffer_size = 1024 * 32;
var response = client.GetSync(url);
var stream = response.Content.ReadAsStreamAsync();
try
{
stream.Wait();
}
catch (Exception ex)
{
}
;
if (stream.IsFaulted)
{
Info($"While downloading {url} - {stream.Exception.ExceptionToString()}");
return false;
}
if (!download)
return true;
var header_var = "1";
if (response.Content.Headers.Contains("Content-Length"))
header_var = response.Content.Headers.GetValues("Content-Length").FirstOrDefault();
var content_size = header_var != null ? long.Parse(header_var) : 1;
var output_path = Path.Combine(DownloadFolder, archive.Name);
;
using (var webs = stream.Result)
using (var fs = File.OpenWrite(output_path))
{
var buffer = new byte[buffer_size];
while (true)
{
var read = webs.Read(buffer, 0, buffer_size);
if (read == 0) break;
Status($"Downloading {archive.Name}", (int)(total_read * 100 / content_size));
fs.Write(buffer, 0, read);
total_read += read;
}
}
Status($"Hashing {archive.Name}");
HashArchive(output_path);
return true;
}
catch (Exception ex)
{
Info($"{archive.Name} - Error downloading from: {url}");
return false;
}
}
private void HashArchives()
{
HashedArchives = Directory.EnumerateFiles(DownloadFolder)

View File

@ -208,7 +208,7 @@ namespace Wabbajack.NexusApi
return true;
}
public NexusFileInfo GetFileInfo(NexusMod mod)
public NexusFileInfo GetFileInfo(NexusDownloader.State mod)
{
var url = $"https://api.nexusmods.com/v1/games/{ConvertGameName(mod.GameName)}/mods/{mod.ModID}/files/{mod.FileID}.json";
return Get<NexusFileInfo>(url);
@ -251,7 +251,7 @@ namespace Wabbajack.NexusApi
return result;
}
public EndorsementResponse EndorseMod(NexusMod mod)
public EndorsementResponse EndorseMod(NexusDownloader.State mod)
{
Utils.Status($"Endorsing ${mod.GameName} - ${mod.ModID}");
var url = $"https://api.nexusmods.com/v1/games/{ConvertGameName(mod.GameName)}/mods/{mod.ModID}/endorse.json";

View File

@ -63,6 +63,7 @@ namespace Wabbajack
var hash = archive.Hash.FromBase64().ToHEX();
switch (archive)
{
/*
case NexusMod m:
var profile = m.UploaderProfile.Replace("/games/",
"/" + NexusApiUtils.ConvertGameName(m.GameName).ToLower() + "/");
@ -84,6 +85,7 @@ namespace Wabbajack
case DirectURLArchive m:
NoWrapText($"* URL - [{m.Name} - {m.URL}]({m.URL})");
break;
*/
}
NoWrapText($" * Size : {archive.Size.ToFileSizeString()}");
@ -147,8 +149,11 @@ namespace Wabbajack
private IEnumerable<Archive> SortArchives(List<Archive> lstArchives)
{
/*
var lst = lstArchives.OfType<NexusMod>().OrderBy(m => m.Author).ThenBy(m => m.Name);
return lst.Concat(lstArchives.Where(m => !(m is NexusMod)).OrderBy(m => m.Name));
*/
return lstArchives;
}
}
}

View File

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Net.Http;
using Wabbajack.Common;
using Wabbajack.Downloaders;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using Path = Alphaleonis.Win32.Filesystem.Path;
@ -84,7 +85,7 @@ namespace Wabbajack.Validation
/// </summary>
/// <param name="mod"></param>
/// <returns></returns>
public Permissions FilePermissions(NexusMod mod)
public Permissions FilePermissions(NexusDownloader.State mod)
{
var author_permissions = AuthorPermissions.GetOrDefault(mod.Author)?.Permissions;
var game_permissions = AuthorPermissions.GetOrDefault(mod.Author)?.Games.GetOrDefault(mod.GameName)?.Permissions;
@ -109,10 +110,10 @@ namespace Wabbajack.Validation
public IEnumerable<string> Validate(ModList modlist)
{
ConcurrentStack<string> ValidationErrors = new ConcurrentStack<string>();
var nexus_mod_permissions = modlist.Archives
.OfType<NexusMod>()
.PMap(a => (a.Hash, FilePermissions(a), a))
.Where(a => a.State is NexusDownloader.State)
.PMap(a => (a.Hash, FilePermissions((NexusDownloader.State)a.State), a))
.ToDictionary(a => a.Hash, a => new { permissions = a.Item2, archive = a.a });
modlist.Directives
@ -122,13 +123,14 @@ namespace Wabbajack.Validation
if (nexus_mod_permissions.TryGetValue(p.ArchiveHashPath[0], out var archive))
{
var ext = Path.GetExtension(p.ArchiveHashPath.Last());
var url = (archive.archive.State as NexusDownloader.State).NexusURL;
if (Consts.AssetFileExtensions.Contains(ext) && !(archive.permissions.CanModifyAssets ?? true))
{
ValidationErrors.Push($"{p.To} from {archive.archive.NexusURL} is set to disallow asset modification");
ValidationErrors.Push($"{p.To} from {url} is set to disallow asset modification");
}
else if (Consts.ESPFileExtensions.Contains(ext) && !(archive.permissions.CanModifyESPs ?? true))
{
ValidationErrors.Push($"{p.To} from {archive.archive.NexusURL} is set to disallow asset ESP modification");
ValidationErrors.Push($"{p.To} from {url} is set to disallow asset ESP modification");
}
}
});
@ -139,10 +141,11 @@ namespace Wabbajack.Validation
{
if (nexus_mod_permissions.TryGetValue(p.ArchiveHashPath[0], out var archive))
{
var url = (archive.archive.State as NexusDownloader.State).NexusURL;
if (!(archive.permissions.CanExtractBSAs ?? true) &&
p.ArchiveHashPath.Skip(1).ButLast().Any(a => Consts.SupportedBSAs.Contains(Path.GetExtension(a).ToLower())))
{
ValidationErrors.Push($"{p.To} from {archive.archive.NexusURL} is set to disallow BSA Extraction");
ValidationErrors.Push($"{p.To} from {url} is set to disallow BSA Extraction");
}
}
});
@ -150,34 +153,25 @@ namespace Wabbajack.Validation
var nexus = NexusApi.NexusApiUtils.ConvertGameName(GameRegistry.Games[modlist.GameType].NexusName);
modlist.Archives
.OfType<NexusMod>()
.Where(m => NexusApi.NexusApiUtils.ConvertGameName(m.GameName) != nexus)
.Where(a => a.State is NexusDownloader.State)
.Where(m => NexusApi.NexusApiUtils.ConvertGameName(((NexusDownloader.State)m.State).GameName) != nexus)
.Do(m =>
{
var permissions = FilePermissions(m);
var permissions = FilePermissions((NexusDownloader.State)m.State);
if (!(permissions.CanUseInOtherGames ?? true))
{
ValidationErrors.Push(
$"The modlist is for {nexus} but {m.Name} is for game type {m.GameName} and is not allowed to be converted to other game types");
$"The modlist is for {nexus} but {m.Name} is for game type {((NexusDownloader.State)m.State).GameName} and is not allowed to be converted to other game types");
}
});
modlist.Archives
.OfType<GoogleDriveMod>()
.PMap(m =>
{
if (!ServerWhitelist.GoogleIDs.Contains(m.Id))
ValidationErrors.Push($"{m.Name} uses Google Drive id {m.Id} but that id is not in the file whitelist.");
});
modlist.Archives
.OfType<DirectURLArchive>()
.PMap(m =>
.Where(m => !m.State.IsWhitelisted(ServerWhitelist))
.Do(m =>
{
if (!ServerWhitelist.AllowedPrefixes.Any(prefix => m.URL.StartsWith(prefix)))
ValidationErrors.Push($"{m.Name} will be downloaded from {m.URL} but that URL is not in the server whitelist");
ValidationErrors.Push($"{m.Name} is not a whitelisted download");
});
return ValidationErrors.ToList();
}
}

View File

@ -194,6 +194,7 @@
<Compile Include="Downloaders\DownloadDispatcher.cs" />
<Compile Include="Downloaders\DropboxDownloader.cs" />
<Compile Include="Downloaders\IDownloader.cs" />
<Compile Include="Downloaders\ManualDownloader.cs" />
<Compile Include="Downloaders\MegaDownloader.cs" />
<Compile Include="Downloaders\NexusDownloader.cs" />
<Compile Include="LambdaCommand.cs" />