public static int ModUpdate() { updated = new List <ModUpdateManifest>(); repoContents = new Dictionary <string, IReadOnlyList <RepositoryContent> >(); string modsPath = (string)typeof(Constants).GetProperty("ModsPath", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).GetValue(null); string configFile = Path.Combine(modsPath, "ModUpdater", "config.json"); github = github ?? new GitHubClient(new ProductHeaderValue("Platonymous.ModUpdater", "1.0.0")); if (!File.Exists(configFile)) { File.WriteAllText(configFile, Newtonsoft.Json.JsonConvert.SerializeObject(new Config())); } config = Newtonsoft.Json.JsonConvert.DeserializeObject <Config>(File.ReadAllText(configFile)); if (config.GitHubUser != "") { var basicAuth = new Credentials(config.GitHubUser, config.GitHubPassword); github.Credentials = basicAuth; } if ((DateTime.Now - config.LastUpdateCheck).TotalMinutes >= config.Interval) { config.LastUpdateCheck = DateTime.Now; shouldUpdate = true; } if (!shouldUpdate) { return(0); } File.WriteAllText(configFile, Newtonsoft.Json.JsonConvert.SerializeObject(config)); int result = 0; foreach (var manifestFile in Directory.GetFiles(modsPath, "manifest.json", SearchOption.AllDirectories)) { string dir = Path.GetDirectoryName(manifestFile); if (dir.StartsWith(".")) { continue; } if (Directory.GetParent(dir).Name.StartsWith(".")) { continue; } ModUpdateManifest mod = Newtonsoft.Json.JsonConvert.DeserializeObject <ModUpdateManifest>(File.ReadAllText(manifestFile)); try { if (config.Exclude.Contains(mod.UniqueID)) { continue; } if (mod.ModUpdater.ModFolder == "" && !string.IsNullOrEmpty(mod.EntryDll)) { mod.ModUpdater.ModFolder = mod.EntryDll.Substring(0, mod.EntryDll.Length - 4); } if (mod.ModUpdater.Repository != "") { result += CheckMod(modsPath, dir, mod); } else if (mod.Author == "Platonymous" && !string.IsNullOrEmpty(mod.EntryDll)) { mod.ModUpdater = new PyModUpdateInformation(mod.EntryDll.Substring(0, mod.EntryDll.Length - 4)); result += CheckMod(modsPath, dir, mod); } } catch (RateLimitExceededException e) { Console.WriteLine("[ModUpdater] [" + mod.UniqueID + "] Updater failed: " + "API Rate Limit exceeded. Please try again later."); continue; } catch (Exception e) { Console.WriteLine("[ModUpdater] [" + mod.UniqueID + "] Updater failed. Please try again later."); continue; } } if (result > 0) { patchModLoad(); } string tempFolder = Path.Combine(modsPath, "ModUpdater", "Temp"); if (Directory.Exists(tempFolder)) { new DirectoryInfo(tempFolder).Delete(true); } return(result); }
public static int CheckMod(string modsPath, string modFolder, ModUpdateManifest mod) { if (!shouldUpdate && !mod.ModUpdater.Install) { if (!loggedNextUpdateCheck) { Console.WriteLine("[ModUpdater] Next update check: " + (config.LastUpdateCheck.AddMinutes(config.Interval).ToString("s"))); loggedNextUpdateCheck = true; } return(0); } string tempFolder = Path.Combine(modsPath, "ModUpdater", "Temp"); var currentVersion = mod.Version; if (!Directory.Exists(tempFolder)) { Directory.CreateDirectory(tempFolder); } var rkey = mod.ModUpdater.User + ">" + mod.ModUpdater.Repository + ">" + mod.ModUpdater.ModFolder; IReadOnlyList <RepositoryContent> rContent = null; if (repoContents.ContainsKey(rkey)) { rContent = repoContents[rkey]; } Repository repo = null; if (rContent == null) { var repoRequest = github.Repository.Get(mod.ModUpdater.User, mod.ModUpdater.Repository); repoRequest.Wait(); repo = repoRequest.Result; } Console.WriteLine("[ModUpdater] Checking for updates: " + mod.Name); Console.WriteLine("[ModUpdater] Current version: " + currentVersion); if (rContent != null || repo is Repository) { if (rContent == null) { var fileRequest = github.Repository.Content.GetAllContents(repo.Id, mod.ModUpdater.Directory); fileRequest.Wait(); var files = fileRequest.Result; rContent = files; repoContents.Add(rkey, rContent); } var selector = mod.ModUpdater.FileSelector.Replace("{ModFolder}", mod.ModUpdater.ModFolder.Replace("[", @"\[").Replace("]", @"\]")); Regex findFile = new Regex(selector, RegexOptions.IgnoreCase | RegexOptions.Singleline); var filesFound = rContent.Where(f => { var m = findFile.Match(Path.GetFileNameWithoutExtension(f.Path)); return(m.Success && m.Groups.Count == 2); }); if (filesFound.Count() == 0) { Console.WriteLine("File not found:" + selector); return(0); } foreach (RepositoryContent file in filesFound) { var fileName = Path.GetFileNameWithoutExtension(file.Path); var match = findFile.Match(fileName); string newVersion = match.Groups[1].Value; if (SemanticVersion.TryParse(newVersion, out ISemanticVersion version) && (mod.ModUpdater.Install || (shouldUpdate && SemanticVersion.TryParse(currentVersion, out ISemanticVersion current) && version.IsNewerThan(current)))) { if (version.IsPrerelease() && !config.LoadPrereleases) { continue; } var url = file.DownloadUrl; var tempFile = Path.Combine(tempFolder, Path.GetFileName(file.Path)); using (WebClient client = new WebClient()) client.DownloadFile(url, tempFile); ModUpdateManifest updateManifest = null; using (ZipArchive zip1 = ZipFile.OpenRead(tempFile)) { if (zip1.Entries.FirstOrDefault(entry => entry.Name.Equals("manifest.json", StringComparison.InvariantCultureIgnoreCase)) is ZipArchiveEntry manifestEntry) { using (StreamReader sr = new StreamReader(manifestEntry.Open(), System.Text.Encoding.UTF8)) { if (Newtonsoft.Json.JsonConvert.DeserializeObject <ModUpdateManifest>(sr.ReadToEnd()) is ModUpdateManifest um) { updateManifest = um; } if (updateManifest is ModUpdateManifest && SemanticVersion.TryParse(updateManifest.MinimumApiVersion, out ISemanticVersion updateApiVersion) && Constants.ApiVersion.IsOlderThan(updateApiVersion)) { Console.WriteLine("[ModUpdater] [" + updateManifest.UniqueID + "]" + "Could not update to version" + updateManifest.Version + ". Need at least SMAPI " + updateManifest.MinimumApiVersion); continue; } } } else { continue; } foreach (ZipArchiveEntry e in zip1.Entries) { string filePath = e.FullName.Replace('/', '\\'); List <string> filePathParts = filePath.Split('\\').ToList(); filePathParts.RemoveAt(0); Console.WriteLine(modFolder); filePath = Path.Combine(filePathParts.ToArray()); var tPath = Path.Combine(modFolder, filePath); var tDirectory = Path.Combine(modFolder, Path.GetDirectoryName(filePath)); if (!Directory.Exists(tDirectory)) { Directory.CreateDirectory(tDirectory); } Console.WriteLine("[ModUpdater] " + " [" + mod.UniqueID + "] " + "Updating file: " + tPath); if (File.Exists(tPath) && updateManifest.ModUpdater.DoNotReplace.Contains(Path.GetFileName(tPath))) { continue; } foreach (string dFile in updateManifest.ModUpdater.DeleteFiles) { string dfilePath = Path.Combine(modFolder, Path.Combine(dFile.Replace('/', '\\').Split('\\'))); Console.WriteLine("[ModUpdater] " + " [" + mod.UniqueID + "] " + "Deleting file: " + dFile); if (File.Exists(dfilePath)) { File.Delete(dfilePath); } } foreach (string dFolder in updateManifest.ModUpdater.DeleteFolders) { string dFolderPath = Path.Combine(modFolder, Path.Combine(dFolder.Replace('/', '\\').Split('\\'))); Console.WriteLine("[ModUpdater] " + " [" + mod.UniqueID + "] " + "Deleting folder: " + dFolder); if (Directory.Exists(dFolderPath)) { Directory.Delete(dFolderPath, true); } } e.ExtractToFile(tPath, true); } } Console.WriteLine("[ModUpdater] [" + mod.UniqueID + "] " + mod.Name + " was successfully updated to version " + version); if (updateManifest is ModUpdateManifest) { updated.Add(updateManifest); } return(1); } } } return(0); }