예제 #1
0
        /*********
        ** Private methods
        *********/
        /// <summary>Get a sorted, parsed list of SMAPI downloads for the latest releases.</summary>
        private async Task <ReleaseVersion[]> GetReleaseVersionsAsync()
        {
            return(await this.Cache.GetOrCreateAsync("available-versions", async entry =>
            {
                entry.AbsoluteExpiration = DateTimeOffset.UtcNow.Add(this.CacheTime);

                // get latest stable release
                GitRelease release = await this.GitHub.GetLatestReleaseAsync(this.RepositoryName, includePrerelease: false);

                // strip 'noinclude' blocks from release description
                if (release != null)
                {
                    HtmlDocument doc = new HtmlDocument();
                    doc.LoadHtml(release.Body);
                    foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//*[@class='noinclude']")?.ToArray() ?? Array.Empty <HtmlNode>())
                    {
                        node.Remove();
                    }
                    release.Body = doc.DocumentNode.InnerHtml.Trim();
                }

                // get versions
                return this
                .ParseReleaseVersions(release)
                .OrderBy(p => p.Version)
                .ToArray();
            }));
        }
예제 #2
0
 /// <summary>
 /// Starts the installation of the release
 /// </summary>
 /// <param name="releaseindex">The index of the release as in the Releases List</param>
 /// <param name="installdir">The installation directory</param>
 internal void StartInstallation(int releaseindex, string installdir)
 {
     if (Settings.ShowLicense)
     {
         LicenseWindow licenseWindow = new LicenseWindow();
         if (licenseWindow.ShowDialog() == true)
         {
             _window.bt_install.IsEnabled = false;
             _installrelease = Releases[releaseindex];
             _window.WriteLog("Starting installation of release \"" + _installrelease.Tag + "\" to \"" + installdir + "\"...");
             _installdir = installdir;
             DownloadAssets();
         }
         else
         {
             _window.WriteLog("You need to accept the license to proceed with the installation.");
         }
     }
     else
     {
         _window.bt_install.IsEnabled = false;
         _installrelease = Releases[releaseindex];
         _window.WriteLog("Starting installation of release \"" + _installrelease.Tag + "\" to \"" + installdir + "\"...");
         _installdir = installdir;
         DownloadAssets();
     }
 }
예제 #3
0
        /*********
        ** Private methods
        *********/
        /****
        ** Event handlers
        ****/
        /// <summary>The method invoked when the player loads the game.</summary>
        private void ReceiveGameLoaded()
        {
            // check for an updated version
            if (this.Config.CheckForUpdates)
            {
                Task.Factory.StartNew(() =>
                {
                    GameHelper.InterceptErrors("checking for a newer version", () =>
                    {
                        using (ICumulativeLog log = this.GetTaskLog())
                        {
                            log.Append("Lookup Anything checking for update... ");

                            GitRelease release = UpdateHelper.GetLatestReleaseAsync("Pathoschild/LookupAnything").Result;
                            if (release.IsNewerThan(this.CurrentVersion))
                            {
                                log.AppendLine($"update to version {release.Name} available.");
                                this.NewRelease = release;
                            }
                            else
                            {
                                log.AppendLine("no update available.");
                            }
                        }
                    });
                });
            }
        }
예제 #4
0
        /// <summary>Get metadata about a mod in the repository.</summary>
        /// <param name="id">The mod ID in this repository.</param>
        public override async Task <ModInfoModel> GetModInfoAsync(string id)
        {
            // validate ID format
            if (!id.Contains("/") || id.IndexOf("/", StringComparison.InvariantCultureIgnoreCase) != id.LastIndexOf("/", StringComparison.InvariantCultureIgnoreCase))
            {
                return(new ModInfoModel($"The value '{id}' isn't a valid GitHub mod ID, must be a username and project name like 'Pathoschild/LookupAnything'."));
            }

            // fetch info
            try
            {
                GitRelease release = await this.Client
                                     .GetAsync(string.Format(this.ReleaseUrlFormat, id))
                                     .As <GitRelease>();

                return(new ModInfoModel(id, this.NormaliseVersion(release.Tag), $"https://github.com/{id}/releases"));
            }
            catch (ApiException ex) when(ex.Status == HttpStatusCode.NotFound)
            {
                return(new ModInfoModel("Found no mod with this ID."));
            }
            catch (Exception ex)
            {
                return(new ModInfoModel(ex.ToString()));
            }
        }
예제 #5
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="release">The underlying GitHub release.</param>
 /// <param name="asset">The underlying download asset.</param>
 /// <param name="version">The SMAPI version.</param>
 /// <param name="isForDevs">Whether this is a 'for developers' download.</param>
 public ReleaseVersion(GitRelease release, GitAsset asset, ISemanticVersion version, bool isForDevs)
 {
     this.Release   = release;
     this.Asset     = asset;
     this.Version   = version;
     this.IsForDevs = isForDevs;
 }
예제 #6
0
        /// <summary>Get a parsed list of SMAPI downloads for a release.</summary>
        /// <param name="release">The GitHub release.</param>
        private IEnumerable <ReleaseVersion> ParseReleaseVersions(GitRelease release)
        {
            if (release?.Assets == null)
            {
                yield break;
            }

            foreach (GitAsset asset in release.Assets)
            {
                if (asset.FileName.StartsWith("Z_"))
                {
                    continue;
                }

                Match match = Regex.Match(asset.FileName, @"SMAPI-(?<version>[\d\.]+(?:-.+)?)-installer(?<forDevs>-for-developers)?.zip");
                if (!match.Success || !SemanticVersion.TryParse(match.Groups["version"].Value, out ISemanticVersion version))
                {
                    continue;
                }
                bool isBeta    = version.IsPrerelease();
                bool isForDevs = match.Groups["forDevs"].Success;

                yield return(new ReleaseVersion(release, asset, version, isBeta, isForDevs));
            }
        }
예제 #7
0
        /// <summary>Get metadata about a mod in the repository.</summary>
        /// <param name="id">The mod ID in this repository.</param>
        public override async Task <ModInfoModel> GetModInfoAsync(string id)
        {
            // validate ID format
            if (!id.Contains("/") || id.IndexOf("/", StringComparison.InvariantCultureIgnoreCase) != id.LastIndexOf("/", StringComparison.InvariantCultureIgnoreCase))
            {
                return(new ModInfoModel($"The value '{id}' isn't a valid GitHub mod ID, must be a username and project name like 'Pathoschild/LookupAnything'."));
            }

            // fetch info
            try
            {
                // get latest release
                GitRelease latest = await this.Client.GetLatestReleaseAsync(id, includePrerelease : true);

                GitRelease preview = null;
                if (latest == null)
                {
                    return(new ModInfoModel("Found no mod with this ID."));
                }

                // get latest stable release (if not latest)
                if (latest.IsPrerelease)
                {
                    preview = latest;
                    latest  = await this.Client.GetLatestReleaseAsync(id, includePrerelease : false);
                }

                // return data
                return(new ModInfoModel(name: id, version: this.NormaliseVersion(latest?.Tag), previewVersion: this.NormaliseVersion(preview?.Tag), url: $"https://github.com/{id}/releases"));
            }
            catch (Exception ex)
            {
                return(new ModInfoModel(ex.ToString()));
            }
        }
예제 #8
0
        /// <summary>Get the latest beta download for a SMAPI release.</summary>
        /// <param name="release">The SMAPI release.</param>
        private IndexVersionModel GetBetaDownload(GitRelease release)
        {
            // get download with the latest version
            SemanticVersionImpl latestVersion = null;
            string latestUrl = null;

            foreach (GitAsset asset in release.Assets ?? new GitAsset[0])
            {
                // parse version
                Match versionMatch = Regex.Match(asset.FileName, @"SMAPI-([\d\.]+(?:-.+)?)-installer.zip");
                if (!versionMatch.Success || !SemanticVersionImpl.TryParse(versionMatch.Groups[1].Value, out SemanticVersionImpl version))
                {
                    continue;
                }

                // save latest version
                if (latestVersion == null || latestVersion.CompareTo(version) < 0)
                {
                    latestVersion = version;
                    latestUrl     = asset.DownloadUrl;
                }
            }

            // return if prerelease
            return(latestVersion?.Tag != null
                ? new IndexVersionModel(latestVersion.ToString(), release.Body, latestUrl, null)
                : null);
        }
예제 #9
0
        private async void MTModulesVw_ItemSelected(object sender, EventArgs e)
        {
            ModuleItem moduleItem = SelectedModuleItem;
            bool       hasAuthors = (moduleItem.Authors.Count > 0);

            UI.MTAuthorsTxt.Enabled    = hasAuthors;
            UI.MTAuthorsTxt.DataSource = (hasAuthors ? SelectedModuleItem.Authors : null);

            GitRepository repository = (moduleItem.Repository);

            if (UI.MTReleasesBtn.Enabled = (repository != null))
            {
                GitRelease currentRelease = (repository.LatestRelease ??
                                             await repository.GetLatestReleaseAsync());

                bool hasReleaseMatch =
                    (currentRelease.GetVersion() == moduleItem.Version);

                if (currentRelease != null && !hasReleaseMatch)
                {
                    List <GitRelease> releases = (repository.Releases ??
                                                  await repository.GetReleasesAsync());

                    foreach (GitRelease release in releases)
                    {
                        if (release.GetVersion() == moduleItem.Version)
                        {
                            hasReleaseMatch = true;
                            currentRelease  = release;
                            break;
                        }
                    }
                }

                if (currentRelease != null &&
                    moduleItem == SelectedModuleItem)
                {
                    if (hasReleaseMatch)
                    {
                        DisplayDownloads(currentRelease);
                    }

                    UI.MTDownloadLatestBtn.Enabled =
                        (repository.LatestRelease.GetVersion() > moduleItem.Version);
                }
            }
            else
            {
                UI.MTDownloadsLbl.Text = "Downloads: 0";

                UI.MTDownloadLatestBtn.Enabled =
                    UI.MTReleasesBtn.Enabled   = false;
            }
        }
예제 #10
0
        /// <summary>Get metadata about a mod in the repository.</summary>
        /// <param name="id">The mod ID in this repository.</param>
        public override async Task <ModInfoModel> GetModInfoAsync(string id)
        {
            ModInfoModel result = new ModInfoModel().SetBasicInfo(id, $"https://github.com/{id}/releases");

            // validate ID format
            if (!id.Contains("/") || id.IndexOf("/", StringComparison.InvariantCultureIgnoreCase) != id.LastIndexOf("/", StringComparison.InvariantCultureIgnoreCase))
            {
                return(result.SetError(RemoteModStatus.DoesNotExist, $"The value '{id}' isn't a valid GitHub mod ID, must be a username and project name like 'Pathoschild/LookupAnything'."));
            }

            // fetch info
            try
            {
                // fetch repo info
                GitRepo repository = await this.Client.GetRepositoryAsync(id);

                if (repository == null)
                {
                    return(result.SetError(RemoteModStatus.DoesNotExist, "Found no GitHub repository for this ID."));
                }
                result
                .SetBasicInfo(repository.FullName, $"{repository.WebUrl}/releases")
                .SetLicense(url: repository.License?.Url, name: repository.License?.SpdxId ?? repository.License?.Name);

                // get latest release (whether preview or stable)
                GitRelease latest = await this.Client.GetLatestReleaseAsync(id, includePrerelease : true);

                if (latest == null)
                {
                    return(result.SetError(RemoteModStatus.DoesNotExist, "Found no GitHub release for this ID."));
                }

                // split stable/prerelease if applicable
                GitRelease preview = null;
                if (latest.IsPrerelease)
                {
                    GitRelease release = await this.Client.GetLatestReleaseAsync(id, includePrerelease : false);

                    if (release != null)
                    {
                        preview = latest;
                        latest  = release;
                    }
                }

                // return data
                return(result.SetVersions(version: this.NormalizeVersion(latest.Tag), previewVersion: this.NormalizeVersion(preview?.Tag)));
            }
            catch (Exception ex)
            {
                return(result.SetError(RemoteModStatus.TemporaryError, ex.ToString()));
            }
        }
예제 #11
0
        /// <summary>Get the for-developers download URL for a SMAPI release.</summary>
        /// <param name="release">The SMAPI release.</param>
        private string GetDevDownloadUrl(GitRelease release)
        {
            // get dev download URL
            foreach (GitAsset asset in release.Assets ?? new GitAsset[0])
            {
                if (Regex.IsMatch(asset.FileName, @"SMAPI-[\d\.]+-installer-for-developers.zip"))
                {
                    return(asset.DownloadUrl);
                }
            }

            // fallback just in case
            return("https://github.com/pathoschild/SMAPI/releases");
        }
예제 #12
0
        /// <summary>Get metadata about a mod in the repository.</summary>
        /// <param name="id">The mod ID in this repository.</param>
        public async Task <ModInfoModel> GetModInfoAsync(string id)
        {
            try
            {
                GitRelease release = await this.Client
                                     .GetAsync(string.Format(this.ReleaseUrlFormat, id))
                                     .As <GitRelease>();

                return(new ModInfoModel(id, release.Tag, $"https://github.com/{id}/releases"));
            }
            catch (Exception ex)
            {
                return(new ModInfoModel(ex.ToString()));
            }
        }
예제 #13
0
        /*********
        ** Private methods
        *********/
        /// <summary>Get a sorted, parsed list of SMAPI downloads for the latest releases.</summary>
        private async Task <ReleaseVersion[]> GetReleaseVersionsAsync()
        {
            return(await this.Cache.GetOrCreateAsync("available-versions", async entry =>
            {
                entry.AbsoluteExpiration = DateTimeOffset.UtcNow.Add(this.CacheTime);

                // get latest release (whether preview or stable)
                GitRelease stableRelease = await this.GitHub.GetLatestReleaseAsync(this.RepositoryName, includePrerelease: true);

                // split stable/prerelease if applicable
                GitRelease betaRelease = null;
                if (stableRelease.IsPrerelease)
                {
                    GitRelease result = await this.GitHub.GetLatestReleaseAsync(this.RepositoryName, includePrerelease: false);
                    if (result != null)
                    {
                        betaRelease = stableRelease;
                        stableRelease = result;
                    }
                }

                // strip 'noinclude' blocks from release descriptions
                foreach (GitRelease release in new[] { stableRelease, betaRelease })
                {
                    if (release == null)
                    {
                        continue;
                    }

                    HtmlDocument doc = new HtmlDocument();
                    doc.LoadHtml(release.Body);
                    foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//*[@class='noinclude']")?.ToArray() ?? new HtmlNode[0])
                    {
                        node.Remove();
                    }
                    release.Body = doc.DocumentNode.InnerHtml.Trim();
                }

                // get versions
                ReleaseVersion[] stableVersions = this.ParseReleaseVersions(stableRelease).ToArray();
                ReleaseVersion[] betaVersions = this.ParseReleaseVersions(betaRelease).ToArray();
                return stableVersions
                .Concat(betaVersions)
                .OrderBy(p => p.Version)
                .ToArray();
            }));
        }
예제 #14
0
        public async Task <ViewResult> Index()
        {
            // fetch latest SMAPI release
            GitRelease release = await this.Cache.GetOrCreateAsync("latest-smapi-release", async entry =>
            {
                entry.AbsoluteExpiration = DateTimeOffset.UtcNow.Add(this.CacheTime);
                return(await this.GitHub.GetLatestReleaseAsync("Pathoschild/SMAPI"));
            });

            string downloadUrl    = this.GetMainDownloadUrl(release);
            string devDownloadUrl = this.GetDevDownloadUrl(release);

            // render view
            var model = new IndexModel(release.Name, release.Body, downloadUrl, devDownloadUrl);

            return(this.View(model));
        }
예제 #15
0
파일: Program.cs 프로젝트: Shanksyue/SMAPI
 /*********
 ** Private methods
 *********/
 /// <summary>Asynchronously check for a new version of SMAPI, and print a message to the console if an update is available.</summary>
 private void CheckForUpdateAsync()
 {
     new Thread(() =>
     {
         try
         {
             GitRelease release             = UpdateHelper.GetLatestVersionAsync(Constants.GitHubRepository).Result;
             ISemanticVersion latestVersion = new SemanticVersion(release.Tag);
             if (latestVersion.IsNewerThan(Constants.ApiVersion))
             {
                 this.Monitor.Log($"You can update SMAPI from version {Constants.ApiVersion} to {latestVersion}", LogLevel.Alert);
             }
         }
         catch (Exception ex)
         {
             this.Monitor.Log($"Couldn't check for a new version of SMAPI. This won't affect your game, but you may not be notified of new versions if this keeps happening.\n{ex.GetLogSummary()}");
         }
     }).Start();
 }
예제 #16
0
        private async void UI_Shown(object sender, EventArgs e)
        {
            UI.Shown -= UI_Shown;

            GitRelease latestRelease =
                await TanjiRepo.GetLatestReleaseAsync();

            if (latestRelease != null)
            {
                LatestVersion = new Version(
                    latestRelease.TagName.Substring(1));

                UI.TanjiVersionTxt.IsLink = true;

                if (LatestVersion > LocalVersion &&
                    !latestRelease.IsPrerelease)
                {
                    UI.TanjiVersionTxt.Text = "Update Found!";
                }
            }
        }
예제 #17
0
        /*********
        ** Private methods
        *********/
        /// <summary>Get a sorted, parsed list of SMAPI downloads for the latest releases.</summary>
        private async Task <ReleaseVersion[]> GetReleaseVersionsAsync()
        {
            return(await this.Cache.GetOrCreateAsync("available-versions", async entry =>
            {
                entry.AbsoluteExpiration = DateTimeOffset.UtcNow.Add(this.CacheTime);

                // get releases
                GitRelease stableRelease = await this.GitHub.GetLatestReleaseAsync(this.RepositoryName, includePrerelease: false);
                GitRelease betaRelease = await this.GitHub.GetLatestReleaseAsync(this.RepositoryName, includePrerelease: true);
                if (stableRelease.Tag == betaRelease.Tag)
                {
                    betaRelease = null;
                }

                // get versions
                ReleaseVersion[] stableVersions = this.ParseReleaseVersions(stableRelease).ToArray();
                ReleaseVersion[] betaVersions = this.ParseReleaseVersions(betaRelease).ToArray();
                return stableVersions
                .Concat(betaVersions)
                .OrderBy(p => p.Version)
                .ToArray();
            }));
        }
예제 #18
0
파일: AboutPage.cs 프로젝트: MOD-/Tanji
        private async void UI_Shown(object sender, EventArgs e)
        {
            UI.Shown -= UI_Shown;
            await Task.Delay(225);

            GitRelease latestRelease =
                await TanjiRepo.GetLatestReleaseAsync();

            if (latestRelease != null)
            {
                LatestVersion = new Version(
                    latestRelease.TagName.Substring(1));

                UI.TanjiVersionTxt.IsLink = true;

                if (LatestVersion > LocalVersion &&
                    !latestRelease.IsPrerelease)
                {
                    UI.TanjiInfoTxt.Spring  = true;
                    UI.TanjiInfoTxt.Text    = "Source Code";
                    UI.TanjiVersionTxt.Text = "Update Available!";
                }
            }
        }
예제 #19
0
        internal async void UpdateAsync()
        {
            var _ReleaseDeserializer = new DataContractJsonSerializer(typeof(GitRelease));

            GitRelease _ReleaseGit = await DownloadJsonObjectAsync <GitRelease>(
                GitReleaseBase.GithubURI, _ReleaseDeserializer, "github").ConfigureAwait(false);

            if (_ReleaseGit == default)
            {
                DepictInfo = string.Format(CultureInfos, "更换服务器......请稍后");

                _ReleaseGit = await DownloadJsonObjectAsync <GitRelease>(
                    GitReleaseBase.GiteeURI, _ReleaseDeserializer, "gitee").ConfigureAwait(false);

                if (_ReleaseGit == default)
                {
                    DepictInfo = string.Format(CultureInfos, "请检查网络或稍后再试!");

                    return;
                }
            }

            UpdateVersionCompareTo(_ReleaseGit.GetVersion());
        }
예제 #20
0
        public async Task <ViewResult> Index()
        {
            // fetch SMAPI releases
            IndexVersionModel stableVersion = await this.Cache.GetOrCreateAsync("stable-version", async entry =>
            {
                entry.AbsoluteExpiration = DateTimeOffset.UtcNow.Add(this.CacheTime);
                GitRelease release       = await this.GitHub.GetLatestReleaseAsync(this.RepositoryName, includePrerelease: false);
                return(new IndexVersionModel(release.Name, release.Body, this.GetMainDownloadUrl(release), this.GetDevDownloadUrl(release)));
            });

            IndexVersionModel betaVersion = await this.Cache.GetOrCreateAsync("beta-version", async entry =>
            {
                entry.AbsoluteExpiration = DateTimeOffset.UtcNow.Add(this.CacheTime);
                GitRelease release       = await this.GitHub.GetLatestReleaseAsync(this.RepositoryName, includePrerelease: true);
                return(release.IsPrerelease
                    ? this.GetBetaDownload(release)
                    : null);
            });

            // render view
            var model = new IndexModel(stableVersion, betaVersion);

            return(this.View(model));
        }
예제 #21
0
 private void DisplayDownloads(GitRelease release)
 {
     UI.MTDownloadsLbl.Text =
         $"Downloads: {release.Assets[0].DownloadCount:n0}";
 }
예제 #22
0
        /// <summary>
        /// Fetches the different versions/releases from the Githup repo
        /// </summary>
        async void GetVersions()
        {
            _window.WriteLog("Trying to fetch releases from GitHub...");
            _window.prog_loading.IsIndeterminate = true;

            using (var client = new WebClient())
            {
                client.Headers.Add("user-agent", "GitInstaller");

                //Save as _releasesjson so you don't have to fetch it again
                _releasesjson = await client.DownloadStringTaskAsync(_url.AbsoluteUri);

                _window.WriteLog("Fetched all releases from GitHub...");

                //Create GitRelease objects from the _releasesjson string
                _window.WriteLog("Creating Release objects...");
                JObject[] jobjs   = JsonConvert.DeserializeObject <JObject[]>(_releasesjson);
                int       idcount = 0;
                Releases.Clear();
                _window.cb_versions.Items.Clear();

                foreach (JObject job in jobjs)
                {
                    GitRelease robj = new GitRelease();
                    robj.Id           = idcount;
                    robj.Name         = job.Value <string>("name");
                    robj.Tag          = job.Value <string>("tag_name");
                    robj.Body         = job.Value <string>("body");
                    robj.GitUrl       = job.Value <string>("html_url");
                    robj.IsPrerelease = job.Value <bool>("prerelease");
                    robj.CreationDate = job.Value <string>("created_at");

                    //Author
                    JObject authorobj = job.Value <JObject>("author");
                    if (authorobj != null)
                    {
                        robj.AuthorName = authorobj.Value <string>("login");
                        robj.AuthorUrl  = authorobj.Value <string>("html_url");
                    }

                    //Assets
                    JToken assets = job.Value <JToken>("assets");

                    foreach (JToken asset in assets.Children())
                    {
                        GitAsset newasset = new GitAsset();
                        newasset.Filename    = asset.Value <string>("name");
                        newasset.DownloadUrl = asset.Value <string>("browser_download_url");
                        newasset.Size        = asset.Value <float>("size");
                        robj.Assets.Add(newasset);
                    }

                    if (Settings.Ignored_Tags.Length > 0)
                    {
                        foreach (string ignoredtags in Settings.Ignored_Tags)
                        {
                            if (!Utils.HasWildcard(robj.Tag, ignoredtags))
                            {
                                idcount++;
                                Releases.Add(robj);
                            }
                        }
                    }
                    else
                    {
                        idcount++;
                        Releases.Add(robj);
                    }
                }

                _window.cb_versions.SelectedIndex = 0;
            }
            _window.prog_loading.IsIndeterminate = false;
            if (Releases.Count < 1)
            {
                MessageBox.Show("No releases found for this repository! Can't progress with the installation...", "Warning!", MessageBoxButton.OK, MessageBoxImage.Warning);
                Environment.Exit(2);
                return;
            }
            _window.bt_install.IsEnabled = true;
            _window.WriteLog("Done creating release objects, " + Releases.Count + " releases added...");

            _window.UpdateVersions(Settings.Preview);
            _window.UpdateChanges(Releases[0]);
        }