using ModVersionChecker.data.model; using ModVersionChecker.managers.interfaces; using ModVersionChecker.utils; using NuGet.Versioning; namespace ModVersionChecker { public class VersionChecker { private readonly IConfigManager _configManager; private readonly IAppsManager _appsManager; private readonly ISourcesDefManager _sourcesDefManager; private readonly INotifyIconService _notifyIconService; private readonly IFlightSimsManager _fsManager; private List errorMessages = new List(); private List updateMessages = new List(); private NotifyIcon? _notifyIcon; public event EventHandler? OnFinished; public VersionChecker( IConfigManager configManager, IAppsManager appsManager, ISourcesDefManager sourcesDefManager, INotifyIconService notifyIconService, IFlightSimsManager fsManager) { _configManager = configManager ?? throw new ArgumentNullException(nameof(configManager)); _appsManager = appsManager ?? throw new ArgumentNullException(nameof(appsManager)); _sourcesDefManager = sourcesDefManager ?? throw new ArgumentNullException(nameof(sourcesDefManager)); _notifyIconService = notifyIconService ?? throw new ArgumentNullException(nameof(notifyIconService)); _fsManager = fsManager ?? throw new ArgumentNullException(nameof(fsManager)); } private void HandleAppError(string message, AppConfig app) { errorMessages.Add(message); _appsManager.UpdateStatus(app, AppStatus.Error); } public void StartVersionChecking(NotifyIcon notifyIcon) { var config = _configManager.Load() ?? new GlobalConfig(); _notifyIcon = notifyIcon ?? throw new ArgumentNullException(nameof(notifyIcon)); // Run version checks in a background thread new Thread(async () => { while (true) { await CheckAsync(); Thread.Sleep(config.IntervalMinutes * 60 * 1000); } }) { IsBackground = true }.Start(); } public async Task CheckAsync() { var config = _configManager.Load() ?? new GlobalConfig(); var apps = _appsManager.Load() ?? new List(); var sources = _sourcesDefManager.List() ?? new List(); var fsMods = _fsManager.Load() ?? new List(); updateMessages = new List(); errorMessages = new List(); foreach (AppConfig app in apps) { if (app.Status != AppStatus.Error && app.LastCheckedAt != 0 && app.LastCheckedAt < TimeUtils.GetUnixTimeMillis(DateTime.Now.AddMinutes(-60))) continue; var status = AppStatus.None; var sourceId = app.Source; if (string.IsNullOrWhiteSpace(sourceId)) { HandleAppError($"{app.Name} has no source configured.", app); continue; } var source = sources.FirstOrDefault(s => s.Id == sourceId); if (source == null) { HandleAppError($"{app.Name} has an invalid source: {sourceId}", app); continue; } try { foreach (var fsVersion in app.MsfsVersions) { var fsConfig = _fsManager.GetByShortName(fsVersion); if (fsConfig == null) { HandleAppError($"{app.Name} has no FS mod path configured for version {fsVersion}.", app); continue; } var checker = CheckerFactory.CreateChecker(source.Type); var current = NuGetVersion.Parse(VersionUtils.GetCurrentVersion(app, fsConfig)); var latest = NuGetVersion.Parse(await checker.GetLatestVersion(app.Params, source)); app.CurrentVersion = current.ToString(); app.LatestVersion = latest.ToString(); if (latest.CompareTo(current) == 1) { updateMessages.Add($"{app.Name}: New version {latest} (current: {current})"); status = AppStatus.UpdateAvailable; } } _appsManager.UpdateStatus(app, status); } catch (Exception ex) { HandleAppError($"Failed for {app.Name}: {ex.Message}", app); } } if (updateMessages.Count > 0) { _notifyIconService.ShowBalloonTip( 10000, "Updates Available", string.Join("\n", updateMessages), ToolTipIcon.Info ); } if (errorMessages.Count > 0) { _notifyIconService.ShowBalloonTip( 10000, "Errors", string.Join("\n", errorMessages), ToolTipIcon.Error ); } OnFinished?.Invoke(this, "Version check completed."); } } }