diff --git a/src/AltGen.Console/AltGen.Console.csproj b/src/AltGen.Console/AltGen.Console.csproj index 089a558..f4841cf 100644 --- a/src/AltGen.Console/AltGen.Console.csproj +++ b/src/AltGen.Console/AltGen.Console.csproj @@ -24,7 +24,7 @@ Generated $(GeneratedCodeDirectory)\Constants.cs - http://localhost:7297 + https://localhost:7297 diff --git a/src/AltGen.Console/Common/HostBuilderExtensions.cs b/src/AltGen.Console/Common/HostBuilderExtensions.cs index 8a08ab1..b1077e2 100644 --- a/src/AltGen.Console/Common/HostBuilderExtensions.cs +++ b/src/AltGen.Console/Common/HostBuilderExtensions.cs @@ -9,6 +9,13 @@ static class HostBuilderExtensions app.Configure(static c => { + c.SetExceptionHandler(static (ex, resolver) => + { + var console = resolver?.Resolve(typeof(IAnsiConsole)) as IAnsiConsole; + console?.WriteException(ex, ExceptionFormats.ShortenEverything); + return -99; + }); + c.AddBranch("config", static c => { c.AddCommand("add"); diff --git a/src/AltGen.Console/Common/Providers.cs b/src/AltGen.Console/Common/Providers.cs new file mode 100644 index 0000000..a4801de --- /dev/null +++ b/src/AltGen.Console/Common/Providers.cs @@ -0,0 +1,17 @@ +using System.Globalization; + +namespace AltGen.Console.Common; + +static class Providers +{ + const string Gemini = "gemini"; + + public static bool IsSupported(string provider) + { + return provider.ToLower(CultureInfo.InvariantCulture) switch + { + Gemini => true, + _ => false + }; + } +} \ No newline at end of file diff --git a/src/AltGen.Console/Config/AddConfigCommand.cs b/src/AltGen.Console/Config/AddConfigCommand.cs index 5d69f08..277b947 100644 --- a/src/AltGen.Console/Config/AddConfigCommand.cs +++ b/src/AltGen.Console/Config/AddConfigCommand.cs @@ -21,6 +21,16 @@ sealed class AddConfigCommand( [CommandOption("-d|--default")] [Description("Set the provider as the default.")] public bool Default { get; init; } + + public override ValidationResult Validate() + { + if (Providers.IsSupported(Provider) is false) + { + return ValidationResult.Error($"The provider '{Provider}' is not supported."); + } + + return ValidationResult.Success(); + } } public override async Task ExecuteAsync(CommandContext context, Settings settings) diff --git a/src/AltGen.Console/Config/AppSettings.cs b/src/AltGen.Console/Config/AppSettings.cs index a808f97..3863325 100644 --- a/src/AltGen.Console/Config/AppSettings.cs +++ b/src/AltGen.Console/Config/AppSettings.cs @@ -44,4 +44,19 @@ record AppSettings var updatedProviders = Providers.Where(p => p.Provider != settings.Provider); return this with { Providers = [.. updatedProviders] }; } + + public ProviderSettings[] GetProviders() + { + return Providers; + } + + public ProviderSettings? GetProvider(string provider) + { + return Providers.FirstOrDefault(p => p.Provider == provider); + } + + public ProviderSettings? GetDefaultProvider() + { + return Providers.FirstOrDefault(static p => p.Default); + } } \ No newline at end of file diff --git a/src/AltGen.Console/Config/ListConfigCommand.cs b/src/AltGen.Console/Config/ListConfigCommand.cs index 8f42182..972c638 100644 --- a/src/AltGen.Console/Config/ListConfigCommand.cs +++ b/src/AltGen.Console/Config/ListConfigCommand.cs @@ -19,7 +19,7 @@ sealed class ListConfigCommand( var appSettings = await _settingsManager.GetAppSettingsAsync(); - foreach (var provider in appSettings.Providers) + foreach (var provider in appSettings.GetProviders()) { var providerName = provider.Provider; var providerKey = provider.Key; diff --git a/src/AltGen.Console/Generate/AltGenService.cs b/src/AltGen.Console/Generate/AltGenService.cs index 9576aee..f782c7c 100644 --- a/src/AltGen.Console/Generate/AltGenService.cs +++ b/src/AltGen.Console/Generate/AltGenService.cs @@ -19,7 +19,7 @@ sealed class AltGenService(HttpClient client) : IAltGenService { { new StringContent(req.Provider), "provider" }, { new StringContent(req.ProviderKey), "providerKey" }, - { new ByteArrayContent(req.Image), "file", req.FileName } + { byteContent, "file", req.FileName } } }; @@ -41,4 +41,4 @@ record AltTextResponse(string AltText); class AltTextException(string message) : Exception(message) { -} +} \ No newline at end of file diff --git a/src/AltGen.Console/Generate/GenerateCommand.cs b/src/AltGen.Console/Generate/GenerateCommand.cs index d4b7259..c076088 100644 --- a/src/AltGen.Console/Generate/GenerateCommand.cs +++ b/src/AltGen.Console/Generate/GenerateCommand.cs @@ -3,13 +3,15 @@ namespace AltGen.Console.Generate; sealed class GenerateCommand( IAnsiConsole console, IFileSystem fileSystem, - IAltGenService altGenService + IAltGenService altGenService, + IAppSettingsManager settingsManager ) : AsyncCommand { readonly IAnsiConsole _console = console; readonly IFileSystem _fileSystem = fileSystem; readonly IAltGenService _altGenService = altGenService; + readonly IAppSettingsManager _settingsManager = settingsManager; public class Settings(IFileSystem fileSystem) : CommandSettings { @@ -20,21 +22,17 @@ sealed class GenerateCommand( [".png"] = "image/png" }; - readonly List _providers = [ - "gemini", - ]; - readonly IFileSystem _fileSystem = fileSystem; - [CommandArgument(1, "")] + [CommandOption("-p|--provider")] [Description("The provider to use for generating alt text.")] public string Provider { get; init; } = string.Empty; - [CommandArgument(2, "")] + [CommandOption("-k|--key")] [Description("The key for the provider.")] public string Key { get; init; } = string.Empty; - [CommandArgument(3, "")] + [CommandArgument(1, "")] [Description("The path to the image to generate alt text for.")] public string Path { get; init; } = string.Empty; @@ -42,13 +40,6 @@ sealed class GenerateCommand( public override ValidationResult Validate() { - // TODO: We should allow provider and key to be optional - // if they are not passed on the command line then - // we should try to resolve them from configuration - if (_providers.Contains(Provider) is false) - { - return ValidationResult.Error($"The provider '{Provider}' is not supported."); - } var pathExists = _fileSystem.File.Exists(Path); @@ -70,12 +61,36 @@ sealed class GenerateCommand( public override async Task ExecuteAsync(CommandContext context, Settings settings) { + var appSettings = await _settingsManager.GetAppSettingsAsync(); + var provider = settings.Provider; + var key = settings.Key; + + if (string.IsNullOrWhiteSpace(provider)) + { + var defaultProvider = appSettings.GetDefaultProvider() + ?? throw new AltTextException("Please specify a provider or set a default provider."); + provider = defaultProvider.Provider; + } + + if (Providers.IsSupported(provider) is false) + { + throw new AltTextException($"The provider '{provider}' is not supported."); + } + + if (string.IsNullOrWhiteSpace(key)) + { + var selectedProvider = appSettings.GetProvider(provider) + ?? throw new AltTextException("Please specify a key or set a default provider."); + key = selectedProvider.Key; + } + + var fileName = _fileSystem.Path.GetFileName(settings.Path); var image = await _fileSystem.File.ReadAllBytesAsync(settings.Path); var altText = await _altGenService.GenerateAltTextAsync(new( - settings.Provider, - settings.Key, + provider, + key, fileName, image, settings.ContentType diff --git a/src/AltGen.Console/Generated/Constants.cs b/src/AltGen.Console/Generated/Constants.cs index c9ed236..6066b7a 100644 --- a/src/AltGen.Console/Generated/Constants.cs +++ b/src/AltGen.Console/Generated/Constants.cs @@ -2,5 +2,5 @@ namespace AltGen.Console.Generated; static class Constants { - public const string AltGenApiUri = "http://localhost:7297"; + public const string AltGenApiUri = "https://localhost:7297"; }