Singularity/Assets/Scripts/NexusModController.cs

331 lines
12 KiB
C#
Raw Normal View History

2024-05-06 14:45:45 -04:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class NexusModController : MonoBehaviour
{
[SerializeField] private OnlineAccountHandler OAH;
[SerializeField] private Controller controller;
[SerializeField] private ModList modList;
[SerializeField] private Transform Container;
[SerializeField] private GameObject Prefab;
[SerializeField] private GameObject UserInfoBlob;
[SerializeField] private RawImage ProfilePic;
[SerializeField] private List<GameObject> UserList;
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void GetUser(string ID) {
StartCoroutine(GetNexusUserIDA(ID));
}
IEnumerator GetNexusUserIDA(string ID) {
string uri = "https://api.nexusmods.com/v1/users/validate.json";
UnityWebRequest uwr = UnityWebRequest.Get(uri);
uwr.SetRequestHeader("accept", "application/json");
uwr.SetRequestHeader("apikey", ID);
yield return uwr.SendWebRequest();
if (uwr.result == UnityWebRequest.Result.ConnectionError) {
Debug.LogError($"Error While Sending GetNexusUserIDA({ID}): {uwr.error}");
controller.Alert("NexusMods", $"Error While Sending GetNexusUserIDA({ID}): {uwr.error}");
} else {
string result = uwr.downloadHandler.text;
NexusMods.NMProfile User = JsonConvert.DeserializeObject<NexusMods.NMProfile>(result);
GetUserInfo(User, true);
}
}
public void GetUserInfo(NexusMods.NMProfile User, bool Save = false) {
Dictionary<string, string> UserInfo = new() {
{ "Name", User.Name },
{ "User ID", User.UserId.ToString() },
{ "EMail", User.Email },
{ "Supporter", User.IsSupporter.ToString() },
{ "Premium", User.IsPremium.ToString() }
};
foreach (KeyValuePair<string, string> info in UserInfo) {
GameObject NewInfo = Instantiate(Prefab, Container);
NewInfo.GetComponent<ModInfoPrefab>().FillMe(info.Key, info.Value);
UserList.Add(NewInfo);
}
string profilePic = User.ProfileUrl;
StartCoroutine (LoadWebP (profilePic, ProfilePic));
if (Save) {
string updatedJson = JsonConvert.SerializeObject(User, Formatting.Indented);
OAH.SaveSettings(updatedJson, 1);
}
UserInfoBlob.SetActive(true);
}
private IEnumerator LoadImage (string B, RawImage A) {
UnityWebRequest WWW = UnityWebRequestTexture.GetTexture(B);
yield return WWW.SendWebRequest();
if (WWW.result != UnityWebRequest.Result.ConnectionError) {
A.texture = DownloadHandlerTexture.GetContent(WWW);
A.SetNativeSize();
A.SizeToParent();
}
}
private IEnumerator LoadWebP(string url, RawImage rawImage) {
using (UnityWebRequest www = UnityWebRequest.Get(url)) {
yield return www.SendWebRequest();
if (www.result != UnityWebRequest.Result.Success) {
Debug.LogError(www.error);
} else {
byte[] webPData = www.downloadHandler.data;
if (webPData == null || webPData.Length == 0) {
Debug.LogError("No WebP data received.");
yield break;
}
WebpImporter.ByteWebpTexture2D(webPData, (texture) => {
rawImage.texture = texture;
});
rawImage.SetNativeSize();
rawImage.SizeToParent();
}
}
}
public void GetMyMods(string A) {
string[] Mods = A.Split("/");
for (int i = 0; i < Mods.Length; i++) {
string Game = Mods[i].Split("?")[0];
string Mod = Mods[i].Split("?")[1];
string url = $"https://api.nexusmods.com/v1/games/{Game}/mods/{Mod}.json".ToString();
string originalDateString = WebUtility.UrlDecode(Mods[i].Split("?")[2]);
if (DateTime.TryParse(originalDateString, out DateTime originalDate)) {
string formattedDateString = originalDate.ToString("yyyy-MM-ddTHH:mm:ssZ");
StartCoroutine(GetMyModsA(url, formattedDateString));
} else {
Debug.LogError("The original date string could not be parsed.");
}
}
}
IEnumerator GetMyModsA(string A, string Date, bool TF = false, string file = "") {
Debug.Log("Link: "+A);
string Key = OAH.NMKey;
SchakenMods SMMod = null;
using (UnityWebRequest uwr = UnityWebRequest.Get(A)) {
uwr.SetRequestHeader("Content-Type", "application/json");
uwr.SetRequestHeader("apikey", Key);
yield return uwr.SendWebRequest();
if (uwr.result == UnityWebRequest.Result.ConnectionError) {
Debug.LogError($"Error While Sending GetMyModsA({A}, {Date}, {TF}, {file}): {uwr.error}");
// Debug.LogError("Error While Sending TEST: " + uwr.error);
} else {
if (uwr.downloadHandler.text.Contains("Please provide an authentication method")) {
Debug.LogError("You need to login first");
controller.Alert("NexusMods", "You have to login to Nexus first. please click settings in the top left corner, then click \"My Nexus Account\" then login. After you are logged in you can download mods into Singularity");
yield break;
}
Debug.Log($"Full Report of ({A}): {uwr.downloadHandler.text}");
if (uwr.downloadHandler.text.Contains("\"status\":\"wastebinned\"")) {
Debug.LogError($"Mod at {A} was removed by Author");
controller.Alert("NexusMods", "This mod was removed by the Author.");
yield break;
} else if (uwr.downloadHandler.text.Contains("\"status\":\"hidden\"")) {
controller.Alert("NexusMods", "This mod is set to hidden.");
Debug.LogError($"Mod at {A} was hidden by Author");
yield break;
} else {
NexusMods.Mod JSON = JsonConvert.DeserializeObject<NexusMods.Mod>(uwr.downloadHandler.text);
SMMod = ConvertMod(JSON);
}
}
}
Debug.Log("Looking up profile: "+SMMod.Mod.ModAuthor.ProfileUrl);
using (UnityWebRequest uwr = UnityWebRequest.Get(SMMod.Mod.ModAuthor.ProfileUrl)) {
yield return uwr.SendWebRequest();
if (uwr.result == UnityWebRequest.Result.ConnectionError) {
Debug.LogError("Error While Sending TEST: " + uwr.error);
controller.Alert("NexusMods", "Connection to NexusMods failed.");
} else {
string HTML = uwr.downloadHandler.text;
if (HTML.Contains("<title>Just a moment...")) {
Debug.LogError("Cloudflare blocked this from finishing...");
controller.Alert("NexusMods", "Cloudflare blocked connection.");
yield break;
}
string htmlString;
if (HTML.Contains("<h3>Last active</h3>")) {
htmlString = HTML.Split(S("<h3>Last active</h3>"))[1].Split(S("<time datetime=\""))[1].Split("\"")[0];
if (DateTime.TryParse(htmlString, out DateTime lastVisit)) {
SMMod.Mod.ModAuthor.LastVisit = lastVisit;
} else {
SMMod.Mod.ModAuthor.LastVisit = null;
}
} else {
SMMod.Mod.ModAuthor.LastVisit = null;
}
htmlString = HTML.Split(S("<h3>Join date</h3>"))[1].Split(S("<time datetime=\""))[1].Split("\"")[0];
if (DateTime.TryParse(htmlString, out DateTime joinDate)) {
SMMod.Mod.ModAuthor.Joined = joinDate;
} else {
SMMod.Mod.ModAuthor.Joined = DateTime.Now;
}
SMMod.Mod.ModAuthor.ProfileViews = int.Parse(HTML.Split(S("<div class=\"titlestat\">Profile views</div>"))[1].Split(S("<div class=\"stat\">"))[1].Split("</div>")[0].Replace(",", ""));
SMMod.Mod.ModAuthor.PhotoUrl = HTML.Split(S("<img class=\"user-avatar\" src=\""))[1].Split("\"")[0];
}
}
using (UnityWebRequest uwr = UnityWebRequest.Get(SMMod.Mod.Url)) {
yield return uwr.SendWebRequest();
if (uwr.result == UnityWebRequest.Result.ConnectionError) {
Debug.LogError("Error While Sending TEST: " + uwr.error);
controller.Alert("NexusMods", "Connection to NexusMods failed.");
} else {
string HTML = uwr.downloadHandler.text;
string[] Thumbs = HTML.Split(S("<li class=\"thumb \" data-src=\""));
List<SchakenMods.Screenshot> Screenshots = new();
List<SchakenMods.ScreenshotThumbnail> ScreenshotsThumbs = new();
for (int j = 1; j < Thumbs.Length; j++) {
SchakenMods.Screenshot screenshot = new() {
Url = Thumbs[j].Split("\"")[0]
};
SchakenMods.ScreenshotThumbnail screenshotThumb = new() {
Url = Thumbs[j].Split("\"")[0].Replace("/images/","/images/thumbnails/")
};
Screenshots.Add(screenshot);
ScreenshotsThumbs.Add(screenshotThumb);
}
SMMod.Mod.Screenshots = Screenshots;
SMMod.Mod.ScreenshotThumbnails = ScreenshotsThumbs;
}
}
SchakenMods NewSMMod = SaveJSON(SMMod, Date);
ModListPrefab MLP = modList.AddMod(NewSMMod);
if (TF) {
string[] Sections = file.Split("/");
string ModName = WebUtility.UrlDecode(Sections[5].Split(S("?md"))[0]);
StartCoroutine(controller.DownloadFileA(file, ModName, MLP, false));
}
}
public void DownloadMod(string Download) {
int i = 0;
if (Download.Contains("/cdn/")) {
i = 1;
}
string[] Sections = Download.Split("/");
string ID = Sections[4+i];
string Game = Sections[3+i];
string url = $"https://api.nexusmods.com/v1/games/{Game}/mods/{ID}.json".ToString();
string Date = DateTime.Now.ToString();
StartCoroutine(GetMyModsA(url, Date, true, Download));
}
private SchakenMods SaveJSON(SchakenMods SM, string Date) {
string JSONPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Schaken-Mods®\Singularity\Mods\";
var settings = new JsonSerializerSettings {
Formatting = Formatting.Indented
};
string CurrentJSON = JsonConvert.SerializeObject(SM.Mod, settings);
CurrentJSON = CurrentJSON.Split(S("\"downloaded\": \""))[0]+"\"downloaded\": \""+Date+CurrentJSON.Split(S("0001-01-01T00:00:00"))[1];
File.WriteAllText($"{JSONPath}/NM{SanitizeFileName(SM.Mod.Id.ToString())}.sing", CurrentJSON);
JObject jsonObject = JObject.Parse(CurrentJSON);
SchakenMods.Download mod = jsonObject.ToObject<SchakenMods.Download>();
SchakenMods Mod = new() { Mod = mod};
return Mod;
}
public SchakenMods ConvertMod(NexusMods.Mod mod) {
if (mod == null) {
Debug.LogError("mod is null");
controller.Alert("NexusMods", "Data recieved from nexus contained unexpected data, or no data at all.");
return null; // or handle the error as appropriate
}
string Thumbnail = mod.ImageURL?.Split(S("/images/"))[0] + "/images/thumbnails/" + mod.ImageURL?.Split(S("/images/"))[1];
if (string.IsNullOrEmpty(Thumbnail)) {
Debug.LogError("Thumbnail URL is null or empty on id "+mod.ModID);
controller.Alert("NexusMods", "Content received from nexus was missing. (Thumbnails?)");
return null; // or handle the error as appropriate
}
SchakenMods SMMod = new() {
Mod = new SchakenMods.Download {
Title = mod.Name,
Description = mod.Description,
PrimaryScreenshot = new SchakenMods.Screenshot { Url = mod.ImageURL },
PrimaryScreenshotThumb = new SchakenMods.ScreenshotThumbnail { Url = Thumbnail },
Downloads = (int)mod.UniqueDownload,
Id = (int)mod.ModID,
ModCategory = new SchakenMods.Category { Id = mod.CategoryID, Name = mod.GameName },
Version = mod.Version,
Date = mod.CreatedTime,
Updated = mod.UpdatedTime,
ModAuthor = new SchakenMods.User { Name = mod.Author, ProfileUrl = mod.UploaderProfileURL },
Url = $"https://www.nexusmods.com/{mod.GameName}/mods/{mod.ModID}"
}
};
return SMMod;
}
private string S(string a) {
return a;
}
private Dictionary<SchakenMods.Screenshot, SchakenMods.ScreenshotThumbnail> ExtractImageUrls(string html) {
Dictionary<SchakenMods.Screenshot, SchakenMods.ScreenshotThumbnail> Images = new();
SchakenMods.Screenshot screenshot = null;
SchakenMods.ScreenshotThumbnail screenshotThumbnail = null;
string[] listItems = html.Split(new string[] { "<li class=\"thumb \"" }, StringSplitOptions.None);
foreach (string listItem in listItems) {
if (listItem.Contains("data-src=\"")) {
string fullImageUrl = listItem.Split(S("data-src=\""))[1].Split("\"")[0];
screenshot = new SchakenMods.Screenshot { Url = fullImageUrl };
}
if (listItem.Contains("data-exthumbimage=\"")) {
string thumbnailUrl = listItem.Split(S("data-exthumbimage=\""))[1].Split("\"")[0];
screenshotThumbnail = new SchakenMods.ScreenshotThumbnail { Url = thumbnailUrl };
}
if (screenshot != null && screenshotThumbnail != null) {
Images.Add(screenshot, screenshotThumbnail);
} else {
Debug.LogError("Adding images failed");
}
}
return Images;
}
public string SanitizeFileName(string fileName)
{
string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
foreach (char c in invalidChars) {
fileName = fileName.Replace(c.ToString(), string.Empty);
}
return fileName;
}
}