Esempio n. 1
0
        /// <summary>Parse version info for the given mod page info.</summary>
        /// <param name="page">The mod page info.</param>
        /// <param name="subkey">The optional update subkey to match in available files. (If no file names or descriptions contain the subkey, it'll be ignored.)</param>
        /// <param name="mapRemoteVersions">The changes to apply to remote versions for update checks.</param>
        /// <param name="allowNonStandardVersions">Whether to allow non-standard versions.</param>
        public ModInfoModel GetPageVersions(IModPage page, string subkey, bool allowNonStandardVersions, ChangeDescriptor mapRemoteVersions)
        {
            // get base model
            ModInfoModel model = new ModInfoModel()
                                 .SetBasicInfo(page.Name, page.Url)
                                 .SetError(page.Status, page.Error);

            if (page.Status != RemoteModStatus.Ok)
            {
                return(model);
            }

            // fetch versions
            bool hasVersions = this.TryGetLatestVersions(page, subkey, allowNonStandardVersions, mapRemoteVersions, out ISemanticVersion mainVersion, out ISemanticVersion previewVersion);

            if (!hasVersions && subkey != null)
            {
                hasVersions = this.TryGetLatestVersions(page, null, allowNonStandardVersions, mapRemoteVersions, out mainVersion, out previewVersion);
            }
            if (!hasVersions)
            {
                return(model.SetError(RemoteModStatus.InvalidData, $"The {page.Site} mod with ID '{page.Id}' has no valid versions."));
            }

            // return info
            return(model.SetVersions(mainVersion, previewVersion));
        }
Esempio n. 2
0
        /*********
        ** Private methods
        *********/
        /// <summary>Get the mod version numbers for the given mod.</summary>
        /// <param name="mod">The mod to check.</param>
        /// <param name="subkey">The optional update subkey to match in available files. (If no file names or descriptions contain the subkey, it'll be ignored.)</param>
        /// <param name="allowNonStandardVersions">Whether to allow non-standard versions.</param>
        /// <param name="mapRemoteVersions">Maps remote versions to a semantic version for update checks.</param>
        /// <param name="main">The main mod version.</param>
        /// <param name="preview">The latest prerelease version, if newer than <paramref name="main"/>.</param>
        private bool TryGetLatestVersions(IModPage mod, string subkey, bool allowNonStandardVersions, IDictionary <string, string> mapRemoteVersions, out ISemanticVersion main, out ISemanticVersion preview)
        {
            main    = null;
            preview = null;

            ISemanticVersion ParseVersion(string raw)
            {
                raw = this.NormalizeVersion(raw);
                return(this.GetMappedVersion(raw, mapRemoteVersions, allowNonStandardVersions));
            }

            if (mod != null)
            {
                // get mod version
                if (subkey == null)
                {
                    main = ParseVersion(mod.Version);
                }

                // get file versions
                foreach (IModDownload download in mod.Downloads)
                {
                    // check for subkey if specified
                    if (subkey != null && download.Name?.Contains(subkey, StringComparison.OrdinalIgnoreCase) != true && download.Description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) != true)
                    {
                        continue;
                    }

                    // parse version
                    ISemanticVersion cur = ParseVersion(download.Version);
                    if (cur == null)
                    {
                        continue;
                    }

                    // track highest versions
                    if (main == null || cur.IsNewerThan(main))
                    {
                        main = cur;
                    }
                    if (cur.IsPrerelease() && (preview == null || cur.IsNewerThan(preview)))
                    {
                        preview = cur;
                    }
                }

                if (preview != null && !preview.IsNewerThan(main))
                {
                    preview = null;
                }
            }

            return(main != null);
        }
Esempio n. 3
0
        /// <summary>Save data fetched for a mod.</summary>
        /// <param name="site">The mod site on which the mod is found.</param>
        /// <param name="id">The mod's unique ID within the <paramref name="site"/>.</param>
        /// <param name="mod">The mod data.</param>
        public void SaveMod(ModSiteKey site, string id, IModPage mod)
        {
            string key = this.GetKey(site, id);

            this.Mods[key] = new Cached <IModPage>(mod);
        }
Esempio n. 4
0
        /*********
        ** Private methods
        *********/
        /// <summary>Get the mod version numbers for the given mod.</summary>
        /// <param name="mod">The mod to check.</param>
        /// <param name="subkey">The optional update subkey to match in available files. (If no file names or descriptions contain the subkey, it'll be ignored.)</param>
        /// <param name="allowNonStandardVersions">Whether to allow non-standard versions.</param>
        /// <param name="mapRemoteVersions">The changes to apply to remote versions for update checks.</param>
        /// <param name="main">The main mod version.</param>
        /// <param name="preview">The latest prerelease version, if newer than <paramref name="main"/>.</param>
        private bool TryGetLatestVersions(IModPage mod, string subkey, bool allowNonStandardVersions, ChangeDescriptor mapRemoteVersions, out ISemanticVersion main, out ISemanticVersion preview)
        {
            main    = null;
            preview = null;

            // parse all versions from the mod page
            IEnumerable <(string name, string description, ISemanticVersion version)> GetAllVersions()
            {
                if (mod != null)
                {
                    ISemanticVersion ParseAndMapVersion(string raw)
                    {
                        raw = this.NormalizeVersion(raw);
                        return(this.GetMappedVersion(raw, mapRemoteVersions, allowNonStandardVersions));
                    }

                    // get mod version
                    ISemanticVersion modVersion = ParseAndMapVersion(mod.Version);
                    if (modVersion != null)
                    {
                        yield return(name : null, description : null, version : ParseAndMapVersion(mod.Version));
                    }

                    // get file versions
                    foreach (IModDownload download in mod.Downloads)
                    {
                        ISemanticVersion cur = ParseAndMapVersion(download.Version);
                        if (cur != null)
                        {
                            yield return(download.Name, download.Description, cur);
                        }
                    }
                }
            }

            var versions = GetAllVersions()
                           .OrderByDescending(p => p.version, SemanticVersionComparer.Instance)
                           .ToArray();

            // get main + preview versions
            void TryGetVersions(out ISemanticVersion mainVersion, out ISemanticVersion previewVersion, Func <(string name, string description, ISemanticVersion version), bool> filter = null)
            {
                mainVersion    = null;
                previewVersion = null;

                // get latest main + preview version
                foreach (var entry in versions)
                {
                    if (filter?.Invoke(entry) == false)
                    {
                        continue;
                    }

                    if (entry.version.IsPrerelease())
                    {
                        previewVersion ??= entry.version;
                    }
                    else
                    {
                        mainVersion ??= entry.version;
                    }

                    if (mainVersion != null)
                    {
                        break; // any other values will be older
                    }
                }

                // normalize values
                if (previewVersion is not null)
                {
                    mainVersion ??= previewVersion; // if every version is prerelease, latest one is the main version
                    if (!previewVersion.IsNewerThan(mainVersion))
                    {
                        previewVersion = null;
                    }
                }
            }

            if (subkey is not null)
            {
                TryGetVersions(out main, out preview, entry => entry.name?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true || entry.description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true);
            }
            if (main is null)
            {
                TryGetVersions(out main, out preview);
            }

            return(main != null);
        }