public static async Task CheckCanaryUpdate(string openFile, bool manual, bool force) { try { char[] slashes = { '\\', '/' }; string[] repoData = currentRepo.Split(slashes); Release release = await github.Repository.Release.Get(repoData[0], repoData[1], $"Canary-{currentBranch}"); if (release == null || release.Assets.Count == 0) { MessageBox.Show( $"Error: Canary release for {currentRepo}@{currentBranch} could not be found. Update failed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (!force) { string oldID = File.ReadAllLines(AppPath + "\\Canary\\New")[2]; string newID = release.TargetCommitish; if (oldID.Equals(newID, StringComparison.OrdinalIgnoreCase)) { if (manual) { MessageBox.Show("No updates found."); } return; } ReleaseAsset Asset = release.Assets.First(a => a.Name.Contains(platform)); if (Asset != null) { GitHubCommit c = await github.Repository.Commit.Get(repoData[0], repoData[1], release.TargetCommitish); if (Asset.CreatedAt.UtcDateTime <= c.Commit.Committer.Date) { // Asset has not yet been updated return; } } } if ((manual || GetOpenWindowsCount() > 1) && MessageBox.Show( "Update to #" + release.TargetCommitish + " was found. Would you like to download now?\n\nAll current windows will be closed and changes will be lost!", "Canary Updater", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } if (!File.Exists(AppPath + "\\Canary\\Old") && File.Exists(AppPath + "\\Canary\\New")) { File.Move(AppPath + "\\Canary\\New", AppPath + "\\Canary\\Old"); } await DownloadRelease(release, true, true, manual, false, openFile); } catch (Exception e) { Console.WriteLine(e.Message); MessageBox.Show( "ERROR: Current Canary version could not be found. Canary has been disabled. The latest stable build will be downloaded instead."); await ForceDownloadStable(openFile); } }
public static async Task DownloadRelease(Release release, bool overwrite, bool automatic, bool manual, bool documentation, string openFile) { try { ReleaseAsset Asset = release.Assets.Any(a => a.Name.Contains(platform)) ? release.Assets.First(a => a.Name.Contains(platform)) : release.Assets[0]; // If open windows need to be closed, ensure they are all properly closed if (overwrite && !documentation) { await KillOpenWindows(); } // Check if we were passed in the overwrite parameter, and if not create a new folder to extract in. if (!overwrite) { Directory.CreateDirectory(AppPath + "/" + release.TagName); AppPath += "/" + release.TagName; } using (WebClient client = new WebClient()) { // Add the user agent header, otherwise we will get access denied. client.Headers.Add("User-Agent: Other"); // Full asset streamed into a single string string html = client.DownloadString(Asset.Url); // The browser download link to the self extracting archive, hosted on github string URL = html.Substring(html.IndexOf("browser_download_url\":\"")) .TrimEnd('}', '"'); URL = URL.Substring(URL.IndexOf("http")); // Download the update, using a download tracker DLProgressWindow.finished = false; DLProgressWindow dlTrack = new DLProgressWindow( release.Name + (release.Name.ToLower().Contains("canary") ? " #" + release.TargetCommitish.Substring(0, 7) : ""), AppPath, URL); while (!DLProgressWindow.finished) { // do nothing } dlTrack.Close(); dlTrack.Dispose(); } // If the update didn't download properly, throw an error if (!File.Exists(AppPath + "/temp.exe") || new FileInfo(AppPath + "/temp.exe").Length != DLProgressWindow.MaxValue || new FileInfo(AppPath + "/temp.exe").Length == 0) { MessageBox.Show("Error downloading update"); if (File.Exists(AppPath + "/temp.exe")) { File.Delete(AppPath + "/temp.exe"); } return; } // Case 1: Cross-platform (Batch files won't work, so user will have to ), documentation update, or non-overwriting update if (Process.GetProcessesByName("winlogon").Count() == 0 || documentation || !overwrite) { try { Process update = Process.Start(AppPath + "/temp.exe", "-o\"" + AppPath + "\" -y"); // For documentation updates, ensure temp.exe is properly deleted and show changelog if the download was automated. if (documentation) { update?.WaitForExit(); if (File.Exists(AppPath + "\\temp.exe")) { File.Delete(AppPath + "\\temp.exe"); } MessageBox.Show("Documentation was successfully updated to " + (release.Name.StartsWith("BrawlCrate Documentation", StringComparison.OrdinalIgnoreCase) && release.Name.Length > 26 ? release.Name.Substring(25) : release.Name) + (automatic ? "\nThis documentation release:\n" + release.Body : "")); } } catch (Exception e) { MessageBox.Show("Error: " + e.Message); } return; } // Case 2: Windows (Can use a batch file to further automate the update) WriteBatchScript(openFile); Process updateBat = Process.Start(new ProcessStartInfo { FileName = AppPath + "/Update.bat", WindowStyle = ProcessWindowStyle.Hidden }); } catch (HttpRequestException) { if (manual) { MessageBox.Show("Unable to connect to the internet."); } } catch (Exception e) { if (manual) { MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
// Used to check for and download non-canary releases (including documentation updates) public static async Task CheckUpdate(bool overwrite, string releaseTag, bool manual, string openFile, bool checkDocumentation, bool automatic) { // If canary is active, disable it if (File.Exists(AppPath + "\\Canary\\Active")) { File.Delete(AppPath + "\\Canary\\Active"); } string repoOwner = mainRepo.Split('/')[0]; string repoName = mainRepo.Split('/')[1]; try { // check to see if the user is online, and that github is up and running. Console.Write("Checking connection to server... "); try { using (Ping s = new Ping()) { IPStatus status = s.Send("www.github.com").Status; Console.WriteLine(status); if (status != IPStatus.Success) { Console.WriteLine("Failed to connect"); if (manual) { MessageBox.Show("Unable to connect to GitHub. The website may be down."); } return; } } } catch { throw new HttpRequestException(); } // Initiate the github client. // get Release IReadOnlyList <Release> AllReleases = await github.Repository.Release.GetAll(repoOwner, repoName); IReadOnlyList <Release> releases = null; Release release = null; bool documentation = false; if (AllReleases.Count == 0) { goto UpdateDL; } // Remove all pre-release versions from the list (Prerelease versions are exclusively documentation updates) releases = AllReleases.Where(r => !r.Prerelease).ToList(); if (releases[0].TagName != releaseTag) { release = releases[0]; goto UpdateDL; } if (checkDocumentation) { // Figure out what documentation version you're on string docVer = ""; try { docVer = File.ReadAllLines(AppPath + "\\InternalDocumentation\\version.txt")[0]; } catch (Exception e) { Console.WriteLine(e.Message); MessageBox.Show( "ERROR: Documentation Version could not be found. Downloading the latest documentation release."); await ForceDownloadDocumentation(); try { docVer = File.ReadAllLines(AppPath + "\\InternalDocumentation\\version.txt")[0]; // Documentation has already been updated, no need to check again. checkDocumentation = false; } catch (Exception e2) { Console.WriteLine(e2.Message); MessageBox.Show( "ERROR: Documentation Version still could not be found. Please report this on Discord or Github.\n" + e2.Message); } } // Don't need to check for update unless the latest release is a prerelease (documentation is included in full releases) if (AllReleases[0].Prerelease) { // This track is shared by canary updates. Ensure that a documentation release is found. foreach (Release r in AllReleases) { if (r.TagName == releaseTag || r.TagName == docVer) { // Documentation is already up-to-date if the latest release (either of documentation or the full program) has been downloaded release = null; break; } if (r.Prerelease && r.Name.ToLower().Contains("documentation")) { release = r; documentation = true; break; } } } } UpdateDL: // If there are no releases available, download will fail. if (release == null || release.Assets.Count == 0) { if (manual) { MessageBox.Show("No updates found."); } return; } // Show warnings as applicable to those using the automatic updater if (automatic) { if (release.Body.Contains("WARNING: ")) { if (release.Body.StartsWith("WARNING: ")) { DialogResult dr = MessageBox.Show( release.Body.Substring(0, release.Body.IndexOf("\n") - 1) + "\n\nWould you like to continue updating?", "Automatic Update Warning", MessageBoxButtons.YesNo); if (dr != DialogResult.Yes) { return; } } else { DialogResult dr = MessageBox.Show( release.Body.Substring(release.Body.IndexOf("WARNING: ")) + "\n\nWould you like to continue updating?", "Automatic Update Warning", MessageBoxButtons.YesNo); if (dr != DialogResult.Yes) { return; } } } if (GetOpenWindowsCount() > 1 && MessageBox.Show( "Update to " + release.Name + " was found. Would you like to download now?\n\nAll current windows will be closed and changes will be lost!", "Updater", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } } else // Allow the user to choose whether or not to download a release if not using the automatic updater { if (MessageBox.Show( release.Name + " is available!\n\nThis release:\n\n" + release.Body + "\n\nUpdate now?" + (manual ? "\n\nThe program will be closed, and changes will not be saved!" : ""), "Update", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } } await DownloadRelease(release, overwrite, automatic, manual, documentation, openFile); } catch (HttpRequestException) { if (manual) { MessageBox.Show("Unable to connect to the internet."); } } catch (Exception e) { if (manual) { MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }