diff --git a/Wabbajack.Common/Utils.cs b/Wabbajack.Common/Utils.cs
index 77ff661b..9b2034bc 100644
--- a/Wabbajack.Common/Utils.cs
+++ b/Wabbajack.Common/Utils.cs
@@ -147,13 +147,28 @@ namespace Wabbajack.Common
return Convert.ToBase64String(data);
}
- public static string ToHEX(this byte[] bytes)
+ public static string ToHex(this byte[] bytes)
{
var builder = new StringBuilder();
for (var i = 0; i < bytes.Length; i++) builder.Append(bytes[i].ToString("x2"));
return builder.ToString();
}
+ public static byte[] FromHex(this string hex)
+ {
+ return Enumerable.Range(0, hex.Length)
+ .Where(x => x % 2 == 0)
+ .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
+ .ToArray();
+ }
+
+ public static DateTime AsUnixTime(this long timestamp)
+ {
+ System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
+ dtDateTime = dtDateTime.AddSeconds(timestamp).ToLocalTime();
+ return dtDateTime;
+ }
+
///
/// Returns data from a base64 stream
///
@@ -535,8 +550,8 @@ namespace Wabbajack.Common
public static void CreatePatch(byte[] a, byte[] b, Stream output)
{
- var data_a = a.SHA256().FromBase64().ToHEX();
- var data_b = b.SHA256().FromBase64().ToHEX();
+ var data_a = a.SHA256().FromBase64().ToHex();
+ var data_b = b.SHA256().FromBase64().ToHex();
var cache_file = Path.Combine("patch_cache", $"{data_a}_{data_b}.patch");
if (!Directory.Exists("patch_cache"))
Directory.CreateDirectory("patch_cache");
@@ -570,7 +585,7 @@ namespace Wabbajack.Common
public static void TryGetPatch(string foundHash, string fileHash, out byte[] ePatch)
{
var patch_name = Path.Combine("patch_cache",
- $"{foundHash.FromBase64().ToHEX()}_{fileHash.FromBase64().ToHEX()}.patch");
+ $"{foundHash.FromBase64().ToHex()}_{fileHash.FromBase64().ToHex()}.patch");
ePatch = File.Exists(patch_name) ? File.ReadAllBytes(patch_name) : null;
}
diff --git a/Wabbajack.Lib/Downloaders/NexusDownloader.cs b/Wabbajack.Lib/Downloaders/NexusDownloader.cs
index 8abc49e5..9498da77 100644
--- a/Wabbajack.Lib/Downloaders/NexusDownloader.cs
+++ b/Wabbajack.Lib/Downloaders/NexusDownloader.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Wabbajack.Common;
using Wabbajack.Lib.NexusApi;
using Wabbajack.Lib.Validation;
+using Game = Wabbajack.Common.Game;
namespace Wabbajack.Lib.Downloaders
{
@@ -54,6 +55,8 @@ namespace Wabbajack.Lib.Downloaders
Utils.Error($"Automated installs with Wabbajack requires a premium nexus account. {client.Username} is not a premium account.");
return;
}
+
+ var updated = client.GetModsUpdatedSince(Game.Skyrim,DateTime.Now - TimeSpan.FromDays(30));
}
public class State : AbstractDownloadState
diff --git a/Wabbajack.Lib/NexusApi/NexusApi.cs b/Wabbajack.Lib/NexusApi/NexusApi.cs
index e16c210c..44716889 100644
--- a/Wabbajack.Lib/NexusApi/NexusApi.cs
+++ b/Wabbajack.Lib/NexusApi/NexusApi.cs
@@ -197,7 +197,7 @@ namespace Wabbajack.Lib.NexusApi
private T GetCached(string url)
{
- var code = Encoding.UTF8.GetBytes(url).ToHEX();
+ var code = Encoding.UTF8.GetBytes(url).ToHex();
var cache_file = Path.Combine(Consts.NexusCacheDirectory, code + ".json");
if (File.Exists(cache_file) && DateTime.Now - File.GetLastWriteTime(cache_file) < Consts.NexusCacheExpiry)
{
@@ -310,6 +310,40 @@ namespace Wabbajack.Lib.NexusApi
{
public string URI { get; set; }
}
+
+ private class UpdatedMod
+ {
+ public long mod_id;
+ public long latest_file_update;
+ public long latest_mod_activity;
+ }
+
+ public IEnumerable GetModsUpdatedSince(Game game, DateTime since)
+ {
+ var result =
+ Get>(
+ $"https://api.nexusmods.com/v1/games/{GameRegistry.Games[game].NexusName}/mods/updated.json?period=1m");
+ return result.Where(r => r.latest_file_update.AsUnixTime() >= since)
+ .Select(m => m.mod_id)
+ .ToList();
+ }
+
+ public static void ClearCacheFor(HashSet<(Game, long)> mods)
+ {
+ Directory.EnumerateFiles(Consts.NexusCacheDirectory, "*.json")
+ .PMap(f =>
+ {
+ Utils.Status("Cleaning Nexus cache for");
+ var filename = Encoding.UTF8.GetString(Path.GetFileNameWithoutExtension(f).FromHex());
+ foreach (var (game, modid) in mods)
+ {
+ if (filename.Contains(GameRegistry.Games[game].NexusName) &&
+ (filename.Contains("\\" + modid + "\\") ||
+ filename.Contains("\\" + modid + ".")))
+ File.Delete(f);
+ }
+ });
+ }
}
}
\ No newline at end of file
diff --git a/Wabbajack.Lib/ReportBuilder.cs b/Wabbajack.Lib/ReportBuilder.cs
index c6d09198..a87b1f3e 100644
--- a/Wabbajack.Lib/ReportBuilder.cs
+++ b/Wabbajack.Lib/ReportBuilder.cs
@@ -61,7 +61,7 @@ namespace Wabbajack.Lib
$"#### Download Summary ({lst.Archives.Count} archives - {lst.Archives.Sum(a => a.Size).ToFileSizeString()})");
foreach (var archive in SortArchives(lst.Archives))
{
- var hash = archive.Hash.FromBase64().ToHEX();
+ var hash = archive.Hash.FromBase64().ToHex();
NoWrapText(archive.State.GetReportEntry(archive));
NoWrapText($" * Size : {archive.Size.ToFileSizeString()}");
NoWrapText($" * SHA256 : [{hash}](https://www.virustotal.com/gui/file/{hash})");