TBMM/GCMM/MainModList.cs
NorbiPeti b4d64c50d0
Fix lib bug, check game exe more, preview support
Fixed the game folder method returning the library file
Checking the game's exe when starting
Added support for the preview branch of the game
Added support for preview versions of mods
2020-07-17 20:57:46 +02:00

156 lines
6.7 KiB
C#

using GCMM.Properties;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GCMM
{
partial class MainForm
{
public void GetInstalledMods()
{
foreach (var modPath in Directory.GetFiles(GamePath(@"\Plugins"), "*.dll"))
{
try
{
var an = AssemblyName.GetAssemblyName(modPath);
if (an.Name == "0Harmony") continue;
//Use filename to avoid differences between repository & assembly name casing
AddUpdateModInList(new ModInfo { Name = Path.GetFileNameWithoutExtension(modPath), Version = an.Version, LastUpdated = File.GetLastWriteTime(modPath) });
}
catch (BadImageFormatException)
{ //Not a .NET assembly
}
}
}
public async void GetAvailableMods()
{
bool preview = GetExe()?.Contains("Preview") ?? false;
using (var client = GetClient())
{
string str = await client.DownloadStringTaskAsync("https://exmods.org/mods/modlist.tsv");
foreach (string line in str.Trim().Split('\n'))
{
var sp = line.Split('\t');
if (sp.Length < 2) continue;
var mod = new ModInfo
{
Author = sp[0].Trim(),
Name = sp[1].Trim()
};
if (await FetchModInfo(mod, preview)) //If it's actually a mod
AddUpdateModInList(mod);
}
}
}
public async Task<bool> FetchModInfo(ModInfo mod, bool preview)
{
string repoURL = "/api/v1/repos/" + mod.Author + "/" + mod.Name + "/releases";
using (var client = GetClient())
{
var arr = JArray.Parse(await client.DownloadStringTaskAsync(repoURL));
var release = arr.FirstOrDefault(rel =>
{
if ((bool) rel["prerelease"] || (bool) rel["draft"])
return false;
var vs = rel["tag_name"].ToString();
int ind = vs.IndexOf('-');
if (ind != -1)
{
if (vs.Substring(ind + 1).Equals("preview", StringComparison.InvariantCultureIgnoreCase)
&& !preview)
return false;
}
return true;
});
if (release == null)
return false;
var verstr = release["tag_name"].ToString().Replace("v", "");
int index = verstr.IndexOf('-');
if (index != -1)
verstr = verstr.Substring(0, index);
JToken asset;
if (release["assets"].Count() == 1)
asset = release["assets"].First;
else
asset = release["assets"].FirstOrDefault(token =>
{
string name = token["name"].ToString();
return name == mod.Name + ".dll" || name == mod.Name + ".zip";
});
mod.DownloadURL = asset?["browser_download_url"]?.ToString();
mod.LastUpdated = (DateTime)release["published_at"];
var ver = verstr.Split('.').Select(str => int.Parse(str)).ToArray();
int getver(byte i) => ver.Length > i ? ver[i] : 0; //By default it sets values not present to -1, but we need them to be 0
mod.LatestVersion = new Version(getver(0), getver(1), getver(2), getver(3));
mod.UpdateDetails = release["name"] + "\n\n" + release["body"].ToString();
try
{
var obj = JObject.Parse(await client.DownloadStringTaskAsync("/api/v1/repos/" + mod.Author + "/" + mod.Name + "/contents/README.md"));
mod.Description = Encoding.UTF8.GetString(Convert.FromBase64String(obj["content"].ToString()));
}
catch(WebException)
{ //It returns a HTTP 500 if it doesn't exist...
}
return true;
}
}
public void AddUpdateModInList(ModInfo mod)
{
if (mods.ContainsKey(mod.Name) ^ modlist.Items.ContainsKey(mod.Name)) //The ListView's keys aren't case sensitive
throw new InvalidOperationException("The mod isn't present in one of the two places: " + mod.Name);
ListViewItem item;
if (modlist.Items.ContainsKey(mod.Name))
{
var omod = mods[mod.Name];
item = modlist.Items[mod.Name];
var items = item.SubItems;
omod.Author = mod.Author ?? omod.Author;
omod.Version = mod.Version ?? omod.Version;
omod.LatestVersion = mod.LatestVersion ?? omod.LatestVersion;
omod.LastUpdated = mod.LastUpdated == default ? omod.LastUpdated : mod.LastUpdated;
omod.Description = mod.Description ?? omod.Description;
omod.DownloadURL = mod.DownloadURL ?? omod.DownloadURL;
omod.UpdateDetails = mod.UpdateDetails ?? omod.UpdateDetails;
items[1].Text = omod.Author ?? "";
items[2].Text = (omod.Version ?? omod.LatestVersion)?.ToString();
items[3].Text = omod.LastUpdated.ToString();
item.Group = omod.Installed ? modlist.Groups["installed"] : modlist.Groups["available"];
mod = omod;
}
else
{
mods.Add(mod.Name, mod);
item = new ListViewItem(new[] { mod.Name, mod.Author ?? "", (mod.Version ?? mod.LatestVersion)?.ToString() ?? "", mod.LastUpdated.ToString() }, modlist.Groups[mod.Installed ? "installed" : "available"]);
item.Name = mod.Name;
modlist.Items.Add(item);
}
if (mod.LatestVersion != null && mod.Version != null && mod.Version < mod.LatestVersion)
item.ForeColor = Color.Blue;
else
item.ForeColor = modlist.ForeColor;
}
public void RemoveModFromList(ModInfo mod)
{
if (mods.Remove(mod.Name))
modlist.Items.RemoveByKey(mod.Name);
}
}
}