TBMM/GCMM/MainModList.cs
NorbiPeti 873fdbfce4 Fix some issues & add support for other assets
Support for downloading mods while having other assets
2020-06-18 18:49:43 +02:00

133 lines
5.8 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(Settings.Default.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()
{
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)) //If it's actually a mod
AddUpdateModInList(mod);
}
}
}
public async Task<bool> FetchModInfo(ModInfo mod)
{
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 => !(bool)rel["prerelease"] && !(bool)rel["draft"]);
if (release == null)
return false;
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 = release["tag_name"].ToString().Replace("v", "").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;
}
public void RemoveModFromList(ModInfo mod)
{
if (mods.Remove(mod.Name))
modlist.Items.RemoveByKey(mod.Name);
}
}
}