コード例 #1
0
        /// <summary>Get metadata about a mod.</summary>
        /// <param name="id">The CurseForge mod ID.</param>
        /// <returns>Returns the mod info if found, else <c>null</c>.</returns>
        public async Task <CurseForgeMod> GetModAsync(long id)
        {
            // get raw data
            ModModel mod = await this.Client
                           .GetAsync($"addon/{id}")
                           .As <ModModel>();

            if (mod == null)
            {
                return(null);
            }

            // get latest versions
            string           invalidVersion = null;
            ISemanticVersion latest         = null;

            foreach (ModFileModel file in mod.LatestFiles)
            {
                // extract version
                ISemanticVersion version;
                {
                    string raw = this.GetRawVersion(file);
                    if (raw == null)
                    {
                        continue;
                    }

                    if (!SemanticVersion.TryParse(raw, out version))
                    {
                        invalidVersion ??= raw;
                        continue;
                    }
                }

                // track latest version
                if (latest == null || version.IsNewerThan(latest))
                {
                    latest = version;
                }
            }

            // get error
            string error = null;

            if (latest == null && invalidVersion == null)
            {
                error = mod.LatestFiles.Any()
                    ? $"CurseForge mod {id} has no downloads which specify the version in a recognised format."
                    : $"CurseForge mod {id} has no downloads.";
            }

            // generate result
            return(new CurseForgeMod
            {
                Name = mod.Name,
                LatestVersion = latest?.ToString() ?? invalidVersion,
                Url = mod.WebsiteUrl,
                Error = error
            });
        }
コード例 #2
0
        /// <summary>Get update check info about a mod.</summary>
        /// <param name="id">The mod ID.</param>
        public async Task <IModPage> GetModData(string id)
        {
            IModPage page = new GenericModPage(this.SiteKey, id);

            // get ID
            if (!uint.TryParse(id, out uint parsedId))
            {
                return(page.SetError(RemoteModStatus.DoesNotExist, $"The value '{id}' isn't a valid CurseForge mod ID, must be an integer ID."));
            }

            // get raw data
            ModModel mod = await this.Client
                           .GetAsync($"addon/{parsedId}")
                           .As <ModModel>();

            if (mod == null)
            {
                return(page.SetError(RemoteModStatus.DoesNotExist, "Found no CurseForge mod with this ID."));
            }

            // get downloads
            List <IModDownload> downloads = new List <IModDownload>();

            foreach (ModFileModel file in mod.LatestFiles)
            {
                downloads.Add(
                    new GenericModDownload(name: file.DisplayName ?? file.FileName, description: null, version: this.GetRawVersion(file))
                    );
            }

            // return info
            return(page.SetInfo(name: mod.Name, version: null, url: mod.WebsiteUrl, downloads: downloads));
        }
コード例 #3
0
        private void OnChange(Object e)
        {
            var tab    = (Telerik.Windows.Controls.RadSelectionChangedEventArgs)e;
            var source = tab.Source;

            switch (((System.Windows.Controls.Primitives.Selector)source).SelectedIndex)
            {
            case 0:
                Modelos       = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(null));
                FlashData.Key = FlashData.Types.error;
                break;

            case 1:
                Procesos      = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(1));
                FlashData.Key = FlashData.Types.success;
                break;

            case 2:
                Realizados = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(3));
                break;
            }

            //Message = "Mensaje desde Message => LoadList "+ ((System.Windows.Controls.Primitives.Selector)source).SelectedIndex.ToString();

            //FlashData.Message = Message;
        }
コード例 #4
0
        public static bool Install(ModModel mod)
        {
            if (!tDToolsExists)
            {
                CreateTDTools();
            }

            string table = "m" + mod.Id + " = {\n" +
                           "\t-- version: " + GetVersion(mod) + "\n";

            int count;

            foreach (KeyValuePair <string, List <ChangeModel> > kv in mod.Changes)
            {
                count = 1;
                foreach (ChangeModel change in kv.Value)
                {
                    table += "\t" + PathToFunctionName(kv.Key, count) + " = function()\n";

                    foreach (string code in change.Code)
                    {
                        table += "\t\t" + code + "\n";
                    }

                    table += "\tend,\n";

                    count++;
                }
            }

            return(true);
        }
コード例 #5
0
        private void OnSave(Object obj)
        {
            var e = (GridViewRowEditEndedEventArgs)obj;

            var item = (VW_MOD_POZO)e.NewData;

            CONFIGURACION_ADMINISTRADOR config = db.CONFIGURACION_ADMINISTRADOR.Where(w => w.IDMODPOZO == item.IDMODPOZO).SingleOrDefault();



            if (config == null)
            {
                config = new CONFIGURACION_ADMINISTRADOR()
                {
                    IDMODPOZO          = item.IDMODPOZO,
                    FECHA_PROGRAMACION = item.FECHA_PROGRAMACION.GetValueOrDefault(),
                    IDUSUARIO          = IdUsuario,
                    MAXREINTENTOS      = item.MAXREINTENTOS.GetValueOrDefault()
                };
                ModModel.Insert(config);
            }
            else
            {
                SVModel.ModeloClient server = new SVModel.ModeloClient();

                server.Reset(config.IDMODPOZO, item.MAXREINTENTOS.GetValueOrDefault());
            }
            MessageBox.Show("Configuración guardada, ahora lo podras ver en Proceso");

            Procesos = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(1));
            Modelos  = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(null));
        }
コード例 #6
0
        public ModsViewModel(MainWindowViewModel MainWindowVM)
        {
            this.MainWindowVM = MainWindowVM;
            HostScreen        = MainWindowVM;

            ModModel.LoadModList(this);
        }
コード例 #7
0
        public ModViewModel(ModModel model, IChangeModEnableState changeModEnableState)
        {
            _model = model;
            _changeModEnableState = changeModEnableState;

            var nameIndex = Source.IndexOf('/');

            if (nameIndex > 0)
            {
                Author = Source[0..nameIndex];
コード例 #8
0
        public virtual ActionResult Mod(string modAdı = "ayarlar-gelişmiş-mod")
        {
            var model = new ModModel()
            {
                ModAdı = modAdı,
                Etkin  = _workContext.MevcutKullanıcı.ÖznitelikAl <bool>(modAdı)
            };

            return(PartialView(model));
        }
コード例 #9
0
ファイル: Init.cs プロジェクト: ninis45/p3_mod_moddemon
        //Proximamente depreciado 09 Dic 2019
        private static void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
        {
            int cola = 0, proceso = 0;

            Dispose = Libraries.Settings.Get("open_server") == "1"?true:false;


            var list = ModModel.GetList();  // db.VW_MOD_POZO.Where(w => (w.ESTATUS == 1 || w.ESTATUS == 2) && w.FECHA_PROGRAMACION < DateTime.Now).OrderBy(o => o.FECHA_PROGRAMACION).ToList(); // db.VW_MOD_POZO.Where(w => w.ESTATUS ==1 &&  w.FECHA_PROGRAMACION >= tfrom && w.FECHA_PROGRAMACION< tto).OrderBy(o=>o.FECHA_PROGRAMACION).ToList();

            //var actives = db.VW_MOD_POZO.Where(w => w.ESTATUS == 2).OrderBy(o => o.FECHA_PROGRAMACION).ToList();//(from active in list where active.ESTATUS == 2  select active.ESTATUS).ToList();
            int licencias = Int32.Parse(Libraries.Settings.Get("no_licencias"));



            var tmp_tasks = tasks.ToArray();

            foreach (var task in tmp_tasks)
            {
                if (tasks[task.Key].IsAlive == false)
                {
                    tasks.Remove(task.Key);
                }
            }
            foreach (var mod in list)
            {
                if (tasks.Count < licencias && tasks.ContainsKey(mod.IDMODPOZO) == false)  // (tasks.Count < Int32.Parse(Settings.Get("no_licencias")))
                {
                    tasks[mod.IDMODPOZO] = new Thread(new ThreadStart(() => Execute(mod)));
                    proceso++;
                }



                if (mod.ESTATUS == 1)
                {
                    cola++;
                }
            }

            Console.WriteLine("En cola({0}), proceso({1}) {2} | Open Server: {3}", cola.ToString(), tasks.Count.ToString(), e.SignalTime, (Dispose?"Disponible":"Ocupado"));
            Console.WriteLine("*********************************************************************************");

            if (Dispose && tasks.Count > 0)
            {
                foreach (var task in tasks)
                {
                    if (tasks[task.Key].IsAlive == false)
                    {
                        tasks[task.Key].Start();
                        Console.WriteLine("Inicia tarea: " + task.Key);
                    }
                }
            }
        }
コード例 #10
0
        private async Task GetModReleaseFromGit(ModModel mod)
        {
            List <ModModel> modReleases;

            try
            {
                if (ModProcessor.Processing)
                {
                    return;
                }
                ModProcessor.Processing = true;
                // if selected mod has custom version skip loading assets
                ModModel release = mod;
                if (!mod.Is_custom_version)
                {
                    release = await ModProcessor.LoadLatestModRelease(mod.Dev_mod);

                    release.Name = mod.Name;
                }

                ModProcessor.Version     = release.Tag_name;
                ModProcessor.ModName     = release.Name;
                ModProcessor.AutoStart   = chkAutoStart.Checked;
                ModProcessor.AddShortcut = chkShortcut.Checked;

                AssetModel modAsset = null;
                if (release.Assets.Count <= 0)
                {
                    throw new Exception("No assets found");
                }
                else
                {
                    #region DownloadZip_Mod
                    modAsset = release.Assets.Where(x => x.Name.Contains(".zip")).FirstOrDefault();
                    if (modAsset == null)
                    {
                        throw new Exception("No zip file found!");
                    }
                    string steamPath      = txtPath.Text;
                    bool   didReqDownload = ModProcessor.DownloadModRelease(modAsset.Browser_download_url, steamPath);
                    #endregion DownloadZip_Mod

                    if (!didReqDownload)
                    {
                        throw new Exception("Error while downloading content");
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
コード例 #11
0
        private async Task GetModReleaseFromGit(ModModel selectedMod)
        {
            List <ModModel> modReleases;

            try
            {
                // if selected mod has custom version skip loading assets
                ModModel selectedItem = selectedMod;
                ModModel release      = selectedItem;
                if (selectedItem.Dev_mod.Equals("Streamblox"))
                {
                    string dev = txtDev.Text;
                    string mod = txtModName.Text;

                    if (dev.Length == 0 || dev.Length == 0)
                    {
                        MessageBox.Show("Please fill in the Developer and Mod name!");
                        return;
                    }
                    selectedItem.Dev_mod = $"{dev}/{mod}";
                }
                if (!selectedItem.Is_custom_version)
                {
                    #region Load_Mod
                    //modReleases = await ModProcessor.LoadModReleases(selectedItem.Dev_mod);
                    //release = modReleases[0];
                    #endregion Load_Mod
                }

                ModProcessor.Version = release.Tag_name;
                ModProcessor.ModName = release.Name;

                #region DownloadZip_Mod
                var zipData  = release.Assets.Count > 0 ? release.Assets[0] : null;
                var fileName = $"{release.Name}#{release.Tag_name}";
                if (zipData == null)
                {
                    throw new Exception("No zip file found!");
                }
                string steamPath      = txtSteamPath.Text;
                bool   didReqDownload = ModProcessor.DownloadModRelease(zipData.Browser_download_url, fileName, steamPath);
                #endregion DownloadZip_Mod

                if (!didReqDownload)
                {
                    throw new Exception("Error while downloading content");
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
コード例 #12
0
        public void LoadLists()
        {
            Modelos    = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(null));
            Procesos   = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(1));
            Realizados = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(3));


            foreach (var m in Modelos)
            {
                if (campos.Contains(m.IDCAMPO) == false)
                {
                    campos.Add(m.IDCAMPO);
                }
            }
        }
コード例 #13
0
ファイル: ModDropClient.cs プロジェクト: wxwssg/SMAPI
        /// <summary>Get update check info about a mod.</summary>
        /// <param name="id">The mod ID.</param>
        public async Task <IModPage> GetModData(string id)
        {
            var page = new GenericModPage(this.SiteKey, id);

            if (!long.TryParse(id, out long parsedId))
            {
                return(page.SetError(RemoteModStatus.DoesNotExist, $"The value '{id}' isn't a valid ModDrop mod ID, must be an integer ID."));
            }

            // get raw data
            ModListModel response = await this.Client
                                    .PostAsync("")
                                    .WithBody(new
            {
                ModIDs = new[] { parsedId },
                Files  = true,
                Mods   = true
            })
                                    .As <ModListModel>();

            ModModel mod = response.Mods[parsedId];

            if (mod.Mod?.Title == null || mod.Mod.ErrorCode.HasValue)
            {
                return(null);
            }

            // get files
            var downloads = new List <IModDownload>();

            foreach (FileDataModel file in mod.Files)
            {
                if (file.IsOld || file.IsDeleted || file.IsHidden)
                {
                    continue;
                }

                downloads.Add(
                    new GenericModDownload(file.Name, file.Description, file.Version)
                    );
            }

            // return info
            string name = mod.Mod?.Title;
            string url  = string.Format(this.ModUrlFormat, id);

            return(page.SetInfo(name: name, version: null, url: url, downloads: downloads));
        }
コード例 #14
0
 private void LoadCompatibleMods()
 {
     #region read_local_json
     string jsonFromFile;
     using (var reader = new StreamReader("CompatibleMods.json"))
     {
         jsonFromFile = reader.ReadToEnd();
     }
     var modsFromFile = JsonConvert.DeserializeObject <List <ModModel> >(jsonFromFile);
     mods.AddRange(modsFromFile);
     #endregion
     // Adding Custom mod capability
     var CustomMod = new ModModel();
     CustomMod.Name    = "Add custom mod";
     CustomMod.Dev_mod = "Custom";
     mods.Add(CustomMod);
 }
コード例 #15
0
        private void OnSave(Object obj)
        {
            var e = (GridViewRowEditEndedEventArgs)obj;

            try
            {
                if (e.EditAction != Telerik.Windows.Controls.GridView.GridViewEditAction.Cancel)
                {
                    var item = (VW_MOD_POZO)e.NewData;

                    CONFIGURACION_ADMINISTRADOR config = db.CONFIGURACION_ADMINISTRADOR.Where(w => w.IDMODPOZO == item.IDMODPOZO).SingleOrDefault();



                    if (config == null)
                    {
                        string now = item.FECHA_PROGRAMACION.Value.ToShortDateString() + " " + DateTime.Now.TimeOfDay.ToString();
                        config = new CONFIGURACION_ADMINISTRADOR()
                        {
                            IDMODPOZO          = item.IDMODPOZO,
                            FECHA_PROGRAMACION = DateTime.Parse(now), //item.FECHA_PROGRAMACION.GetValueOrDefault(),
                            IDUSUARIO          = IdUsuario,
                            MAXREINTENTOS      = item.MAXREINTENTOS == null ? 1 : item.MAXREINTENTOS.GetValueOrDefault()
                        };
                        ModModel.Insert(config);
                    }
                    else
                    {
                        SVModel.ModeloClient server = new SVModel.ModeloClient();
                        server.Endpoint.Address = Address;
                        server.Reset(config.IDMODPOZO, item.MAXREINTENTOS.GetValueOrDefault());
                    }
                    MessageBox.Show("Configuración guardada, ahora lo podras ver en Proceso");

                    Procesos = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(1));
                    Modelos  = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(null));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
コード例 #16
0
        private void OnChange(Object e)
        {
            var tab    = (Telerik.Windows.Controls.RadSelectionChangedEventArgs)e;
            var source = tab.Source;

            switch (((System.Windows.Controls.Primitives.Selector)source).SelectedIndex)
            {
            case 0:
                Modelos = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(null));

                break;

            case 1:
                Procesos = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(1));

                break;

            case 2:
                Realizados = new ObservableCollection <VW_MOD_POZO>(ModModel.GetList(3));
                break;
            }
        }
コード例 #17
0
        public async Task Process(TimeSpan interval, CancellationToken cancellationToken)
        {
            while (true)
            {
                bool Disposed = false;
                List <VW_MOD_POZO> ListModelos = new List <VW_MOD_POZO>();

                try
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    if (Local)
                    {
                        Disposed    = ModeloProsper.Modelo.Dispose();
                        ListModelos = ModModel.GetList();
                    }
                    else
                    {
                        List <string> JsonModelos = Server.GetList(1);
                        Disposed = Server.Dispose();
                        if (JsonModelos.Count > 0)
                        {
                            foreach (var vwModPozo in JsonModelos)
                            {
                                ListModelos.Add(JsonConvert.DeserializeObject <VW_MOD_POZO>(vwModPozo));
                            }
                        }
                    }
                    var tmp_tasks = LTasks.Keys.ToArray();

                    foreach (var task in tmp_tasks)
                    {
                        if (LTasks[task].IsCompleted || LTasks[task].IsFaulted)
                        {
                            LTasks.Remove(task);
                        }
                    }

                    foreach (var mod in ListModelos)
                    {
                        if (LTasks.ContainsKey(mod.IDMODPOZO) == false)
                        {
                            if (Local)
                            {
                                LTasks.Add(mod.IDMODPOZO, new Task(() => ExecLocal(db, mod, ModeMessage)));
                            }
                            else
                            {
                                LTasks.Add(mod.IDMODPOZO, new Task(() => ExecRemote(db, mod, Server, ModeMessage)));
                            }
                        }
                        if (mod.ESTATUS == 1)
                        {
                            //cola++;
                        }
                        if (mod.ESTATUS == 2)
                        {
                            // proceso++;
                        }
                    }

                    if (Disposed == true && LTasks.Count > 0)
                    {
                        string[] KTasks = LTasks.Keys.ToArray();
                        string   id     = KTasks[0];

                        if (LTasks[id].Status != TaskStatus.Running && LTasks[id].Status != TaskStatus.WaitingToRun)
                        {
                            LTasks[id].Start();
                        }
                    }
                    await Task.Delay(interval, cancellationToken);
                }
                catch (Exception ex)
                {
                    WriteEventLogEntry(System.Diagnostics.EventLogEntryType.Error, 1, ex.Message, ModeMessage);
                }
            }
        }
コード例 #18
0
 public static bool CheckInstalled(ModModel mod)
 {
     return(true);
 }
コード例 #19
0
 public static bool Uninstall(ModModel mod)
 {
     return(true);
 }
コード例 #20
0
ファイル: Init.cs プロジェクト: ninis45/p3_mod_moddemon
        public static async Task TimerTask(TimeSpan interval, CancellationToken cancellationToken)
        {
            int licencias = Int32.Parse(Libraries.Settings.Get("no_licencias"));

            while (true)
            {
                try
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }



                    int cola = 0, proceso = 0;
                    Dispose = Libraries.Settings.Get("open_server") == "1" ? true : false;


                    //Verificar que pasa caundo se cierra el programa y reinicia con el estatus 2
                    List <VW_MOD_POZO> list = ModModel.GetList();  //db.VW_MOD_POZO.Where(w => (w.ESTATUS == 1 || w.ESTATUS == 2) && w.FECHA_PROGRAMACION < DateTime.Now).OrderBy(o => o.FECHA_PROGRAMACION).ToList();

                    var tmp_tasks           = LTasks.Keys.ToArray();

                    foreach (var task in tmp_tasks)
                    {
                        if (LTasks[task].IsCompleted || LTasks[task].IsFaulted)
                        {
                            LTasks.Remove(task);
                        }
                    }

                    foreach (var mod in list)
                    {
                        if (LTasks.ContainsKey(mod.IDMODPOZO) == false)
                        {
                            LTasks.Add(mod.IDMODPOZO, new Task(() => Execute(mod)));
                        }
                        if (mod.ESTATUS == 1)
                        {
                            cola++;
                        }
                        if (mod.ESTATUS == 2)
                        {
                            proceso++;
                        }
                    }

                    Console.WriteLine("En cola({0}), proceso({1}) {2} | Open Server: {3}", cola.ToString(), proceso.ToString(), DateTime.Now, (Dispose ? "Disponible" : "Ocupado"));
                    Console.WriteLine("*********************************************************************************");


                    if (Modelo.Dispose() == true && LTasks.Count > 0)
                    {
                        string[] KTasks = LTasks.Keys.ToArray();
                        string   id     = KTasks[0];

                        if (LTasks[id].Status != TaskStatus.Running)
                        {
                            LTasks[id].Start();
                        }
                    }

                    await Task.Delay(interval, cancellationToken);
                }
                catch (Exception ex)
                {
                    WriteLineText(ex.Message, "danger");
                }
            }
        }
コード例 #21
0
 private static float GetVersion(ModModel mod)
 {
     return(1.0f);
 }
コード例 #22
0
        public void Process(object sender, ElapsedEventArgs e)
        {
            bool Disposed = false;

            try
            {
                List <VW_MOD_POZO> ListModelos = new List <VW_MOD_POZO>();
                if (Local)
                {
                    Disposed    = ModeloProsper.Modelo.Dispose();
                    ListModelos = ModModel.GetList();
                }
                else
                {
                    Disposed = Server.Dispose();
                    var JsonModelos = Server.GetList(1);
                    foreach (var vwModPozo in JsonModelos)
                    {
                        ListModelos.Add(JsonConvert.DeserializeObject <VW_MOD_POZO>(vwModPozo));
                    }
                }

                foreach (var mod in ListModelos)
                {
                    if (LTasks.ContainsKey(mod.IDMODPOZO) == false)
                    {
                        if (Local)
                        {
                            LTasks.Add(mod.IDMODPOZO, new Task(() => ExecLocal(db, mod, ModeMessage)));
                        }
                        else
                        {
                            LTasks.Add(mod.IDMODPOZO, new Task(() => ExecRemote(db, mod, Server, ModeMessage)));
                        }
                    }
                    //if (mod.ESTATUS == 1)
                    //{
                    //    //cola++;
                    //}
                    //if (mod.ESTATUS == 2)
                    //{
                    //    // proceso++;
                    //}
                }
                var tmp_tasks = LTasks.Keys.ToArray();

                foreach (var task in tmp_tasks)
                {
                    if (LTasks[task].IsCompleted || LTasks[task].IsFaulted)
                    {
                        LTasks.Remove(task);
                    }
                }

                if (Disposed == true && LTasks.Count > 0)
                {
                    string[] KTasks = LTasks.Keys.ToArray();
                    string   id     = KTasks[0];

                    if (LTasks[id].Status != TaskStatus.Running && LTasks[id].Status != TaskStatus.WaitingToRun)
                    {
                        LTasks[id].Start();
                    }
                }
            }
            catch (Exception ex)
            {
                if (ModeMessage == Modo.defaults)
                {
                    throw new Exception(ex.Message);
                }
                else
                {
                    WriteEventLogEntry(System.Diagnostics.EventLogEntryType.Error, 1, ex.Message, ModeMessage);
                }
            }
        }
コード例 #23
0
        /// <summary>Get metadata about a mod.</summary>
        /// <param name="id">The ModDrop mod ID.</param>
        /// <returns>Returns the mod info if found, else <c>null</c>.</returns>
        public async Task <ModDropMod> GetModAsync(long id)
        {
            // get raw data
            ModListModel response = await this.Client
                                    .PostAsync("")
                                    .WithBody(new
            {
                ModIDs = new[] { id },
                Files  = true,
                Mods   = true
            })
                                    .As <ModListModel>();

            ModModel mod = response.Mods[id];

            if (mod.Mod?.Title == null || mod.Mod.ErrorCode.HasValue)
            {
                return(null);
            }

            // get latest versions
            ISemanticVersion latest   = null;
            ISemanticVersion optional = null;

            foreach (FileDataModel file in mod.Files)
            {
                if (file.IsOld || file.IsDeleted || file.IsHidden)
                {
                    continue;
                }

                if (!SemanticVersion.TryParse(file.Version, out ISemanticVersion version))
                {
                    continue;
                }

                if (file.IsDefault)
                {
                    if (latest == null || version.IsNewerThan(latest))
                    {
                        latest = version;
                    }
                }
                else if (optional == null || version.IsNewerThan(optional))
                {
                    optional = version;
                }
            }
            if (latest == null)
            {
                latest   = optional;
                optional = null;
            }
            if (optional != null && latest.IsNewerThan(optional))
            {
                optional = null;
            }

            // generate result
            return(new ModDropMod
            {
                Name = mod.Mod?.Title,
                LatestDefaultVersion = latest,
                LatestOptionalVersion = optional,
                Url = string.Format(this.ModUrlFormat, id)
            });
        }