AIVersionManager rework.
This commit is contained in:
@@ -6,135 +6,174 @@ using System.Threading.Tasks;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public class VersionIndex
|
|
||||||
{
|
|
||||||
public string MappedPath;
|
|
||||||
public string RawPath;
|
|
||||||
public string Version;
|
|
||||||
public double Coverage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AIVersionManager
|
public static class AIVersionManager
|
||||||
{
|
{
|
||||||
private const string BaseUrl = "https://raw.githubusercontent.com/radioegor146/gi-asset-indexes/master/";
|
private const string BaseUrl = "https://raw.githubusercontent.com/radioegor146/gi-asset-indexes/master/";
|
||||||
private const string CommitsUrl = "https://api.github.com/repos/radioegor146/gi-asset-indexes/commits?path=";
|
private const string CommitsUrl = "https://api.github.com/repos/radioegor146/gi-asset-indexes/commits?path=";
|
||||||
|
private const string VersionIndexName = "version-index.json";
|
||||||
|
private const string VersionIndexKey = "index";
|
||||||
|
|
||||||
private static readonly string BaseAIFolder = Path.Combine(Environment.CurrentDirectory, "AI");
|
private static readonly string BaseAIFolder = Path.Combine(Environment.CurrentDirectory, "AI");
|
||||||
private static readonly string VersionsPath = Path.Combine(BaseAIFolder, "versions.json");
|
private static readonly string VersionsPath = Path.Combine(BaseAIFolder, "versions.json");
|
||||||
private static readonly string VersionIndexUrl = Path.Combine(BaseUrl, "version-index.json");
|
|
||||||
private static readonly HttpClient Client;
|
private static readonly HttpClient Client;
|
||||||
|
|
||||||
private static List<VersionIndex> Versions;
|
private static Dictionary<string, VersionIndex> Versions;
|
||||||
|
|
||||||
public static bool Loaded;
|
|
||||||
|
|
||||||
static AIVersionManager()
|
static AIVersionManager()
|
||||||
{
|
{
|
||||||
Client = new HttpClient();
|
Client = new HttpClient();
|
||||||
Client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 6.0; Windows 98; Trident/5.1)");
|
Client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 6.0; Windows 98; Trident/5.1)");
|
||||||
Client.Timeout = TimeSpan.FromMinutes(1);
|
Versions = new Dictionary<string, VersionIndex>();
|
||||||
Versions = new List<VersionIndex>();
|
|
||||||
Loaded = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uri CreateUri(string source, out Uri result) => Uri.TryCreate(source, UriKind.Absolute, out result) && result.Scheme == Uri.UriSchemeHttps ? result : null;
|
public static List<(string, bool)> GetVersions()
|
||||||
|
|
||||||
public static void FetchVersions()
|
|
||||||
{
|
{
|
||||||
var versions = Task.Run(() => DownloadString(VersionIndexUrl)).Result;
|
var versions = new List<(string, bool)>();
|
||||||
if (string.IsNullOrEmpty(versions))
|
var cachedVersions = LoadVersions();
|
||||||
|
foreach (var version in Versions)
|
||||||
{
|
{
|
||||||
Logger.Warning("Could not load AI versions !!");
|
versions.Add((version.Key, cachedVersions.ContainsKey(version.Key)));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
Versions = JsonConvert.DeserializeObject<List<VersionIndex>>(versions);
|
return versions;
|
||||||
Loaded = Versions.Count > 0;
|
}
|
||||||
|
public static async Task<bool> FetchVersions()
|
||||||
|
{
|
||||||
|
var versions = "";
|
||||||
|
var url = Path.Combine(BaseUrl, VersionIndexName);
|
||||||
|
var path = GetPath(VersionIndexKey);
|
||||||
|
if (await NeedDownload(VersionIndexKey, VersionIndexName))
|
||||||
|
{
|
||||||
|
versions = await DownloadString(url, TimeSpan.FromSeconds(2));
|
||||||
|
if (string.IsNullOrEmpty(versions))
|
||||||
|
{
|
||||||
|
Logger.Warning("Could not load AI versions !!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!await StoreCommit(VersionIndexKey, VersionIndexName))
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to store version list !!");
|
||||||
|
}
|
||||||
|
File.WriteAllText(path, versions);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
versions = File.ReadAllText(path);
|
||||||
|
}
|
||||||
|
Versions = JsonConvert.DeserializeObject<List<VersionIndex>>(versions).ToDictionary(x => x.Version, x => x);
|
||||||
|
return Versions.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string> DownloadString(string url)
|
public static async Task<string> FetchAI(string version)
|
||||||
{
|
{
|
||||||
string json = "";
|
var path = "";
|
||||||
if (CreateUri(url, out var uri) != null)
|
if (Versions.TryGetValue(version, out var versionIndex))
|
||||||
|
{
|
||||||
|
var url = Path.Combine(BaseUrl, versionIndex.MappedPath);
|
||||||
|
path = GetPath(version);
|
||||||
|
if (await NeedDownload(version, versionIndex.MappedPath))
|
||||||
|
{
|
||||||
|
Logger.Info("Downloading...");
|
||||||
|
var json = await DownloadString(url, TimeSpan.FromMinutes(1));
|
||||||
|
if (string.IsNullOrEmpty(json))
|
||||||
|
{
|
||||||
|
Logger.Warning("Could not load AI !!");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (!await StoreCommit(version, versionIndex.MappedPath))
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to store AI !!");
|
||||||
|
}
|
||||||
|
File.WriteAllText(path, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
private static bool CreateUri(string source, out Uri result) => Uri.TryCreate(source, UriKind.Absolute, out result) && result.Scheme == Uri.UriSchemeHttps;
|
||||||
|
|
||||||
|
private static async Task<string> DownloadString(string url, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
var content = "";
|
||||||
|
if (CreateUri(url, out var uri))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
json = await Client.GetStringAsync(uri);
|
using (var cts = new CancellationTokenSource())
|
||||||
|
{
|
||||||
|
cts.CancelAfter(timeout);
|
||||||
|
var response = await Client.GetAsync(uri, cts.Token);
|
||||||
|
content = await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (TaskCanceledException ex)
|
||||||
|
{
|
||||||
|
Logger.Warning($"Timeout occured while trying to download {Path.GetFileName(url)}, {ex.Message}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Warning($"Failed to fetch {Path.GetFileName(url)}, {ex.Message}");
|
Logger.Warning($"Failed to download {Path.GetFileName(url)}, {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return json;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string> DownloadAI(string version)
|
private static async Task<bool> NeedDownload(string key, string path)
|
||||||
{
|
{
|
||||||
var versionIndex = Versions.FirstOrDefault(x => x.Version == version);
|
if (!File.Exists(GetPath(key)))
|
||||||
|
|
||||||
Logger.Info("Downloading....");
|
|
||||||
string json = await DownloadString(BaseUrl + versionIndex.MappedPath);
|
|
||||||
if (!await StoreCommit(version))
|
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to store AIVersion");
|
return true;
|
||||||
}
|
}
|
||||||
return json;
|
var latestCommit = await GetLatestCommit(path);
|
||||||
}
|
if (string.IsNullOrEmpty(latestCommit))
|
||||||
|
|
||||||
public static async Task<bool> NeedDownload(string version)
|
|
||||||
{
|
|
||||||
var path = GetAIPath(version);
|
|
||||||
if (!File.Exists(path)) return true;
|
|
||||||
var latestCommit = await GetLatestCommit(version);
|
|
||||||
if (string.IsNullOrEmpty(latestCommit)) return true;
|
|
||||||
var dict = LoadVersions();
|
|
||||||
if (dict.TryGetValue(version, out var commit))
|
|
||||||
{
|
{
|
||||||
if (commit == latestCommit) return false;
|
return !File.Exists(GetPath(key));
|
||||||
|
}
|
||||||
|
var dict = LoadVersions();
|
||||||
|
if (dict.TryGetValue(key, out var commit))
|
||||||
|
{
|
||||||
|
if (commit == latestCommit)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<bool> StoreCommit(string version)
|
private static async Task<bool> StoreCommit(string key, string path)
|
||||||
{
|
{
|
||||||
var latestCommit = await GetLatestCommit(version);
|
var latestCommit = await GetLatestCommit(path);
|
||||||
if (string.IsNullOrEmpty(latestCommit)) return false;
|
if (string.IsNullOrEmpty(latestCommit))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var dict = LoadVersions();
|
var dict = LoadVersions();
|
||||||
if (dict.TryGetValue(version, out var commit))
|
if (dict.TryGetValue(key, out var commit))
|
||||||
{
|
{
|
||||||
if (commit != latestCommit)
|
if (commit != latestCommit)
|
||||||
dict[version] = latestCommit;
|
{
|
||||||
|
dict[key] = latestCommit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else dict.Add(version, latestCommit);
|
else dict.Add(key, latestCommit);
|
||||||
StoreVersions(dict);
|
StoreVersions(dict);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, string> CreateVersions()
|
private static Dictionary<string, string> CreateVersions()
|
||||||
{
|
{
|
||||||
var dict = new Dictionary<string, string>();
|
var dict = new Dictionary<string, string>();
|
||||||
var dir = Path.GetDirectoryName(VersionsPath);
|
var dir = Path.GetDirectoryName(VersionsPath);
|
||||||
if (!Directory.Exists(dir))
|
Directory.CreateDirectory(dir);
|
||||||
Directory.CreateDirectory(dir);
|
var json = JsonConvert.SerializeObject(dict);
|
||||||
using (var stream = File.Create(VersionsPath))
|
File.WriteAllText(VersionsPath, json);
|
||||||
{
|
|
||||||
var serializer = new JsonSerializer();
|
|
||||||
|
|
||||||
using (StreamWriter writer = new StreamWriter(stream))
|
|
||||||
using (JsonTextWriter jsonWriter = new JsonTextWriter(writer))
|
|
||||||
{
|
|
||||||
JsonSerializer ser = new JsonSerializer();
|
|
||||||
ser.Serialize(jsonWriter, dict);
|
|
||||||
jsonWriter.Flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, string> LoadVersions()
|
private static Dictionary<string, string> LoadVersions()
|
||||||
{
|
{
|
||||||
if (!File.Exists(VersionsPath))
|
if (!File.Exists(VersionsPath))
|
||||||
{
|
{
|
||||||
@@ -145,35 +184,48 @@ namespace AssetStudio
|
|||||||
return JsonConvert.DeserializeObject<Dictionary<string, string>>(file);
|
return JsonConvert.DeserializeObject<Dictionary<string, string>>(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void StoreVersions(Dictionary<string, string> dict)
|
private static void StoreVersions(Dictionary<string, string> dict)
|
||||||
{
|
{
|
||||||
var json = JsonConvert.SerializeObject(dict, Formatting.Indented);
|
var json = JsonConvert.SerializeObject(dict, Formatting.Indented);
|
||||||
File.WriteAllText(VersionsPath, json);
|
File.WriteAllText(VersionsPath, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetAIPath(string version)
|
private static string GetPath(string version)
|
||||||
{
|
{
|
||||||
var versionIndex = Versions.FirstOrDefault(x => x.Version == version);
|
string path = "";
|
||||||
return Path.Combine(BaseAIFolder, Path.GetFileName(versionIndex.MappedPath));
|
if (Versions.TryGetValue(version, out var versionIndex))
|
||||||
|
{
|
||||||
|
path = Path.Combine(BaseAIFolder, Path.GetFileName(versionIndex.MappedPath));
|
||||||
|
}
|
||||||
|
else if (version == VersionIndexKey)
|
||||||
|
{
|
||||||
|
path = Path.Combine(BaseAIFolder, VersionIndexName);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string> GetLatestCommit(string version)
|
private static async Task<string> GetLatestCommit(string path)
|
||||||
{
|
{
|
||||||
var versionIndex = Versions.FirstOrDefault(x => x.Version == version);
|
|
||||||
string commit = "";
|
string commit = "";
|
||||||
|
var json = await DownloadString($"{CommitsUrl}{path}", TimeSpan.FromSeconds(2));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string json = await DownloadString(CommitsUrl + versionIndex.MappedPath);
|
|
||||||
JArray data = JArray.Parse(json);
|
JArray data = JArray.Parse(json);
|
||||||
commit = data[0]["sha"].ToString();
|
commit = data[0]["sha"].ToString();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
Logger.Error($"Failed to fetch latest commit", ex);
|
Logger.Warning($"Failed to parse latest commit {Path.GetFileName(path)}");
|
||||||
}
|
}
|
||||||
return commit;
|
return commit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] GetVersions() => Versions.Select(x => x.Version).ToArray();
|
internal class VersionIndex
|
||||||
|
{
|
||||||
|
public string MappedPath = "";
|
||||||
|
public string RawPath = "";
|
||||||
|
public string Version = "";
|
||||||
|
public double Coverage = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user