refactors

This commit is contained in:
Jose Conde
2025-09-30 15:57:56 +02:00
parent 5e16f781b4
commit 4c76f04d0e
31 changed files with 403 additions and 293 deletions

View File

@@ -31,16 +31,16 @@ namespace ModVersionChecker.service
public Task<List<SourceResponse>> GetSources()
=> _apiRepository.GetSources();
public async Task<List<App>> GetAppsByIds(App[] apps)
public async Task<List<App>> GetAppsByIds(List<App> apps)
{
var appResponses = await _apiRepository.GetAppsByIds(apps);
return appResponses.Select(AppResponse.toModel).ToList();
}
public Task<List<App>?> SearchApps(string searchText)
public async Task<List<App>> SearchApps(string searchText)
{
var appResponses = _apiRepository.SearchApps(searchText);
return appResponses.ContinueWith(t => t.Result?.Select(AppResponse.toModel).ToList());
var appResponses = await _apiRepository.SearchApps(searchText);
return appResponses.Select(AppResponse.toModel).ToList();
}
}

View File

@@ -0,0 +1,203 @@
using ModVersionChecker.enums;
using ModVersionChecker.managers.interfaces;
using ModVersionChecker.model;
using ModVersionChecker.service.interfaces;
using ModVersionChecker.utils;
namespace ModVersionChecker.service
{
public class AppService: IAppService
{
private readonly IApiService _apiService;
private readonly IAppRepository _appRepository;
private readonly IVersionService _versionService;
private readonly IStateService _stateService;
private readonly INotificationService _notificationService;
private readonly Config _config;
public AppService(
IApiService apiService,
IVersionService versionService,
IAppRepository appManager,
IStateService stateService,
INotificationService notificationService
) {
_apiService = apiService;
_appRepository = appManager;
_versionService = versionService;
_stateService = stateService;
_notificationService = notificationService;
_config = _stateService.GetConfig();
}
public bool CreateApp(App? app)
{
if (app != null)
{
_appRepository.Insert(app);
return true;
}
return false;
}
public bool DeleteApp(App? app)
{
if (app !=null)
{
_appRepository.Delete(app.Id);
return true;
}
return false;
}
public bool UpdateApp(App? app)
{
if (app != null)
{
_appRepository.Update(app);
return true;
}
return false;
}
public async Task<List<App>> GetAndUpdateCurrentApps()
{
try
{
List<App> apps = _appRepository.Load();
if (apps == null) throw new InvalidOperationException("Failed to load apps: repository returned null.");
if (apps.Count == 0) return new List<App>();
List<App> updatedApps = await _apiService.GetAppsByIds(apps);
if (updatedApps == null) throw new InvalidOperationException("Failed to load apps: repository returned null.");
if (updatedApps.Count == 0) return apps;
foreach (App app in updatedApps)
{
app.CurrentVersion = _versionService.GetCurrentVersion(app);
CheckAppStatus(app);
_appRepository.Update(app);
}
_stateService.SetApps(updatedApps);
return updatedApps;
}
catch (Exception ex)
{
Console.WriteLine(ex);
return new List<App>();
}
}
public App CheckAppStatus(App app)
{
var status = AppStatus.NONE;
if (app.LatestVersion == null)
{
app.Status = AppStatus.ERROR;
_appRepository.Update(app);
return app;
}
var currentVersion = app.CurrentVersion;
var updateMessage = "";
if (_versionService.IsUpdateAvailable(currentVersion, app.LatestVersion))
{
updateMessage = $"{app.Name}: New version {app.LatestVersion} (current: {currentVersion})";
status = AppStatus.UPDATE_AVAILABLE;
}
app.Status = status;
app.LastCheckedAt = TimeUtils.GetUnixTimeMillis(null);
return app;
}
public void CheckAllApps()
{
var apps = _appRepository.Load();
var sources = _stateService.GetSources();
List<string> errorMessages = new List<string>();
List<string> updateMessages = new List<string>();
if (apps == null || apps.Count == 0)
{
return;
}
foreach (App app in apps)
{
var sourceId = app.Source;
if (
app.Status != AppStatus.ERROR && app.LastCheckedAt != 0 &&
app.LastCheckedAt < TimeUtils.GetUnixTimeMillis(DateTime.UtcNow.AddMinutes(-60)) ||
string.IsNullOrWhiteSpace(sourceId)
)
{
continue;
}
try
{
var latesstVersion = app.LatestVersion;
var source = sources.FirstOrDefault(s => s.Id == sourceId);
if (source == null)
{
errorMessages.Add($"{app.Name} has an invalid source: {sourceId}");
continue;
}
var typeConfig = _config.Types.FirstOrDefault(t => t.ShortName == app.Type);
if (typeConfig == null)
{
errorMessages.Add($"{app.Name} has no valid type config.");
continue;
}
app.CurrentVersion = VersionUtils.GetCurrentVersion(app, typeConfig);
var updatedApp = CheckAppStatus(app);
_appRepository.Update(updatedApp);
if (updatedApp.Status == AppStatus.UPDATE_AVAILABLE)
{
updateMessages.Add($"{app.Name}: New version {app.LatestVersion} (current: {app.CurrentVersion})");
}
}
catch (Exception ex)
{
errorMessages.Add($"Failed to check {app.Name}: {ex.Message}");
}
}
if (updateMessages.Count > 0)
{
_notificationService.ShowBalloonTip(
10000,
"Updates Available",
string.Join("\n", updateMessages),
ToolTipIcon.Info
);
}
if (errorMessages.Count > 0)
{
_notificationService.ShowBalloonTip(
10000,
"Errors",
string.Join("\n", errorMessages),
ToolTipIcon.Error
);
}
}
public List<App> PurgeExisitingApps(List<App> apps)
{
var _existingApps = _stateService.GetApps();
if (_existingApps == null || _existingApps.Count == 0)
{
return apps;
}
return apps.Where(a => !_existingApps.Any(e => e.Id == a.Id)).ToList();
}
}
}

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace ModVersionChecker.service
{
public class NotifyIconService : INotifyIconService
public class NotificationService : INotificationService
{
private NotifyIcon? _notifyIcon;
public void SetNotifyIcon(NotifyIcon icon)

View File

@@ -0,0 +1,41 @@
using ModVersionChecker.managers.interfaces;
using ModVersionChecker.model;
using ModVersionChecker.repository.api.dto;
using ModVersionChecker.service.interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModVersionChecker.service
{
public class StateService: IStateService
{
private List<App> apps = new List<App>();
private List<SourceResponse> sources = new List<SourceResponse>();
private List<TypeResponse> types = new List<TypeResponse>();
private Config config = new Config();
private readonly IAppRepository _appRepository;
public StateService(
IAppRepository appRepository
) {
_appRepository = appRepository;
}
public List<App> GetApps() => apps;
public void SetApps(List<App> apps) => this.apps = apps;
public List<SourceResponse> GetSources() => sources;
public void SetSources(List<SourceResponse> sources) => this.sources = sources;
public List<TypeResponse> GetTypes() => types;
public void SetTypes(List<TypeResponse> types) => this.types = types;
public Config GetConfig() => config;
public void SetConfig(Config config) => this.config = config;
public void UpdateApps() => this.apps = _appRepository.Load();
}
}

View File

@@ -9,121 +9,25 @@ namespace ModVersionChecker.service
{
public class VersionService: IVersionService
{
private readonly IApiService _apiService;
private readonly IAppsManager _appsManager;
private readonly INotifyIconService _notifyIconService;
private readonly Config _globalConfig;
public VersionService(
IApiService apiVersionService,
IAppsManager appsManager,
IConfigManager configManager,
INotifyIconService notifyIconService)
{
_apiService = apiVersionService;
_appsManager = appsManager ?? throw new ArgumentNullException(nameof(appsManager));
_notifyIconService = notifyIconService ?? throw new ArgumentNullException(nameof(notifyIconService));
IConfigRepository configManager
) {
_globalConfig = configManager.Load() ?? new Config();
}
public App CheckApp(App app)
public string GetCurrentVersion(App app)
{
var status = AppStatus.NONE;
if (app.LatestVersion== null)
var typeConfig = _globalConfig.Types.FirstOrDefault(t => t.ShortName == app.Type);
if (typeConfig == null)
{
app.Status = AppStatus.ERROR;
_appsManager.Update(app);
return app;
throw new InvalidOperationException($"No type config found for app type: {app.Type}");
}
var currentVersion = app.CurrentVersion;
var updateMessage = "";
if (isUpdateAvailable(currentVersion, app.LatestVersion))
{
updateMessage = $"{app.Name}: New version {app.LatestVersion} (current: {currentVersion})";
status = AppStatus.UPDATE_AVAILABLE;
}
app.Status = status;
app.LastCheckedAt = TimeUtils.GetUnixTimeMillis(null);
_appsManager.Update(app);
return app;
return VersionUtils.GetCurrentVersion(app, typeConfig);
}
public async Task CheckAllApps()
{
var apps = _appsManager.Load();
var sources = await _apiService.GetSources();
var appVersionsMap = await _apiService.GetAppVersionsAsync(apps);
List<string> errorMessages = new List<string>();
List<string> updateMessages = new List<string>();
if (apps == null || apps.Count == 0)
{
return;
}
foreach (App app in apps)
{
var sourceId = app.Source;
if (
app.Status != AppStatus.ERROR && app.LastCheckedAt != 0 && app.LastCheckedAt < TimeUtils.GetUnixTimeMillis(DateTime.UtcNow.AddMinutes(-60)) ||
!app.Active || string.IsNullOrWhiteSpace(sourceId)
)
{
continue;
}
try
{
var latesstVersion = appVersionsMap.FirstOrDefault(a => a.Id == app.Id)?.LatestVersion;
var source = sources.FirstOrDefault(s => s.Id == sourceId);
if (source == null)
{
errorMessages.Add($"{app.Name} has an invalid source: {sourceId}");
continue;
}
var typeConfig = _globalConfig.Types.FirstOrDefault(t => t.ShortName == app.Type);
if (typeConfig == null)
{
errorMessages.Add($"{app.Name} has no valid type config.");
continue;
}
app.CurrentVersion = VersionUtils.GetCurrentVersion(app, typeConfig);
var updatedApp = CheckApp(app);
if (updatedApp.Status == AppStatus.UPDATE_AVAILABLE)
{
updateMessages.Add($"{app.Name}: New version {app.LatestVersion} (current: {app.CurrentVersion})");
}
}
catch (Exception ex)
{
errorMessages.Add($"Failed to check {app.Name}: {ex.Message}");
}
}
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
);
}
}
private bool isUpdateAvailable(string currentVersion, string latestVersion)
public bool IsUpdateAvailable(string currentVersion, string latestVersion)
{
try
{

View File

@@ -12,8 +12,7 @@ namespace ModVersionChecker.service.interfaces
Task<List<SourceResponse>> GetSources();
Task<AppVersionsResponse?> GetAppLatestVersionAsync(App app);
Task<bool> AuthenticateAsync(string username, string password);
Task<List<App>> GetAppsByIds(App[] apps);
Task<List<App>?> SearchApps(string searchText);
Task<List<App>> GetAppsByIds(List<App> apps);
Task<List<App>> SearchApps(string searchText);
}
}

View File

@@ -0,0 +1,20 @@
namespace ModVersionChecker.service.interfaces
{
public interface IAppService
{
// List<App> GetAppsById(List<App> apps);
// bool SaveApps(List<App> apps);
// App? GetAppById(string id);
bool CreateApp(App? app);
bool UpdateApp(App? app);
bool DeleteApp(App? app);
Task<List<App>> GetAndUpdateCurrentApps();
App CheckAppStatus(App app);
void CheckAllApps();
List<App> PurgeExisitingApps(List<App> apps);
}
}

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace ModVersionChecker.service.interfaces
{
public interface INotifyIconService
public interface INotificationService
{
void SetNotifyIcon(NotifyIcon icon);
void ShowBalloonTip(int millis, string title, string message, ToolTipIcon icon);

View File

@@ -0,0 +1,20 @@
using ModVersionChecker.repository.api.dto;
using ModVersionChecker.model;
namespace ModVersionChecker.service.interfaces
{
public interface IStateService
{
List<App> GetApps();
void SetApps(List<App> apps);
void UpdateApps();
List<SourceResponse> GetSources();
void SetSources(List<SourceResponse> sources);
List<TypeResponse> GetTypes();
void SetTypes(List<TypeResponse> types);
Config GetConfig();
void SetConfig(Config config);
}
}

View File

@@ -8,8 +8,12 @@ namespace ModVersionChecker.service.interfaces
{
public interface IVersionService
{
App CheckApp(App app);
//App CheckAppStatus(App app);
Task CheckAllApps();
//Task CheckAllApps();
string GetCurrentVersion(App app);
bool IsUpdateAvailable(string currentVersion, string latestVersion);
}
}