diff --git a/Commands/AddSnapCommand.cs b/Commands/AddSnapCommand.cs index c830dca..4d4a82f 100644 --- a/Commands/AddSnapCommand.cs +++ b/Commands/AddSnapCommand.cs @@ -7,7 +7,7 @@ namespace Snapp.Cli.Commands; public class AddSnappsCommand : Command { public sealed class Settings : DefaultCommandSettings { - public Settings(IOptions settings) : base(settings) { } + public Settings(AppSettings settings) : base(settings) { } } public override int Execute(CommandContext context, Settings settings) { @@ -23,8 +23,9 @@ public class AddSnappsCommand : Command { .PromptStyle("green")); } - Console.WriteLine( - $"Executing list snapps command with server address: {settings.ServerUrl} and API key: {settings.ApiKey}"); + + Log.Debug( + $"Executing add snapps command with server address: {settings.ServerUrl} and API key: {settings.ApiKey}"); // var snaps = await service.GetSnaps(); // foreach (var snap in snaps.Results) { // Console.WriteLine($"{snap.Id}: {snap.Title}"); diff --git a/Commands/DebugCommand.cs b/Commands/DebugCommand.cs index 50713ee..9dccd86 100644 --- a/Commands/DebugCommand.cs +++ b/Commands/DebugCommand.cs @@ -1,4 +1,5 @@ using System.ComponentModel; +using Snapp.Cli.Helpers; using Spectre.Console.Cli; namespace Snapp.Cli.Commands; @@ -11,7 +12,7 @@ public class DebugCommand : AsyncCommand { } public override async Task ExecuteAsync(CommandContext context, Settings settings) { - Console.WriteLine($"Echoing: {settings.EchoText}"); + Log.Debug($"Echoing: {settings.EchoText}"); return await Task.FromResult(3); } } diff --git a/Commands/DefaultCommandSettings.cs b/Commands/DefaultCommandSettings.cs index 4b12568..2e12647 100644 --- a/Commands/DefaultCommandSettings.cs +++ b/Commands/DefaultCommandSettings.cs @@ -9,8 +9,8 @@ namespace Snapp.Cli.Commands; public class DefaultCommandSettings : CommandSettings { public readonly AppSettings Config; - public DefaultCommandSettings(IOptions settings) { - Config = settings.Value; + protected DefaultCommandSettings(AppSettings settings) { + Config = settings; } [Description("Path to search. Defaults to current directory.")] diff --git a/Commands/ListSnappsCommand.cs b/Commands/ListSnappsCommand.cs index c33814d..a3f7bc1 100644 --- a/Commands/ListSnappsCommand.cs +++ b/Commands/ListSnappsCommand.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using Microsoft.Extensions.Options; using Snapp.Cli.Helpers; using Snapp.Cli.Services; @@ -5,20 +6,31 @@ using Spectre.Console.Cli; namespace Snapp.Cli.Commands; -public class ListSnappsCommand : AsyncCommand { - private readonly SnappService _snappService; - - public ListSnappsCommand(SnappService snappService) { - _snappService = snappService; - } - - public sealed class Settings : CommandSettings { } - // public sealed class Settings : CommandSettings { - // public Settings(IOptions settings) : base(settings) { } - // } +public class ListSnappsCommand(SnappService snappService) : + AsyncCommand { + public sealed class Settings(AppSettings settings) : + DefaultCommandSettings(settings); public override async Task ExecuteAsync(CommandContext context, Settings settings) { - Console.WriteLine($"Listing shit"); - return 1; + var server = DefaultCommandSettings.AskServerIfMissing( + settings.ServerUrl ?? + settings.Config.ServerUrl); + var apiKey = DefaultCommandSettings.AskApiKeyIfMissing( + settings.ApiKey ?? + settings.Config.ApiKey); + + Log.Debug( + $"Executing list snapps command with server address: {server} and API key: {apiKey}"); + var snaps = await snappService.GetSnaps(); + if (snaps?.Data == null) { + Log.Debug("No snaps found"); + return -1; + } + + foreach (var snap in snaps.Data) { + Log.Debug($"{snap.Url}: {snap.Slug} ({snap.VisitCount})"); + } + + return snaps.Data.Count; } } diff --git a/Helpers/AppSettingsHelper.cs b/Helpers/AppSettingsHelper.cs index 595b734..aec1f73 100644 --- a/Helpers/AppSettingsHelper.cs +++ b/Helpers/AppSettingsHelper.cs @@ -3,15 +3,21 @@ using Microsoft.Extensions.Configuration; namespace Snapp.Cli.Helpers; public class AppSettings { - public string? ApiKey { get; set; } - public string? ServerUrl { get; set; } + public IConfiguration Config { get; set; } + + public AppSettings() { + Config = AppSettingsHelper.InitialiseSettings(); + } + + public string? ServerUrl { get => Config.GetSection("ServerUrl").Value; } + public string? ApiKey { get => Config.GetSection("ApiKey").Value; } } public class AppSettingsHelper { - private readonly AppSettings _config; - - public string? ApiKey { get => _config.ApiKey; } - public string? ServerUrl { get => _config.ServerUrl; } + // private readonly AppSettings _config; + // + // public string? ApiKey { get => _config?.ApiKey; } + // public string? ServerUrl { get => _config?.ServerUrl; } private static string SettingsFile { get => Path.Combine( @@ -19,11 +25,7 @@ public class AppSettingsHelper { "snapp-cli/config.json"); } - public AppSettingsHelper() { - _config = _initialiseSettings(); - } - - private AppSettings _initialiseSettings() { + public static IConfiguration InitialiseSettings() { var config = new ConfigurationBuilder() .SetBasePath(AppContext.BaseDirectory) .AddJsonFile(SettingsFile, false, true) @@ -33,11 +35,6 @@ public class AppSettingsHelper { throw new NullReferenceException("Missing settings file"); } - var c = config.Get(); - if (c is null) { - throw new NullReferenceException("Missing settings"); - } - - return c; + return config; } } diff --git a/Helpers/Log.cs b/Helpers/Log.cs new file mode 100644 index 0000000..378099a --- /dev/null +++ b/Helpers/Log.cs @@ -0,0 +1,17 @@ +using Spectre.Console; + +namespace Snapp.Cli.Helpers; + +public static class Log { + private static readonly object _lock = new(); + + public static void Debug(string message) { +#if DEBUG + lock (_lock) { + Console.ForegroundColor = ConsoleColor.DarkGray; + Console.WriteLine($"{message}"); + Console.ResetColor(); + } +#endif + } +} diff --git a/Program.cs b/Program.cs index ae1fda1..461b84f 100644 --- a/Program.cs +++ b/Program.cs @@ -1,27 +1,36 @@ -using System; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Spectre.Console.Cli; using Snapp.Cli.Commands; using Snapp.Cli.Helpers; using Snapp.Cli.Services; -using Spectre.Console.Cli; var registrations = new ServiceCollection(); registrations.AddSingleton(); -registrations.AddSingleton(); registrations.AddHttpClient(); +registrations.AddScoped(sp => sp.GetRequiredService>().Value); +registrations.AddSingleton(); +registrations.AddOptions(); -var registrar = new Snapp.Cli.Helpers.TypeRegistrar(registrations); + +var registrar = new TypeRegistrar(registrations); var app = new CommandApp(registrar); app.Configure(config => { + config.CaseSensitivity(CaseSensitivity.None); + config.SetApplicationName("Snapp CLI"); + config.ValidateExamples(); + #if DEBUG config.PropagateExceptions(); config.ValidateExamples(); #endif + config.AddCommand("debug"); config.AddCommand("list"); + config.AddCommand("add"); }); return await app diff --git a/Services/SnappService.cs b/Services/SnappService.cs index f7af3aa..d9f48d2 100644 --- a/Services/SnappService.cs +++ b/Services/SnappService.cs @@ -1,4 +1,5 @@ using System.Text.Json; +using System.Text.Json.Serialization; using Snapp.Cli.Helpers; namespace Snapp.Cli.Services; @@ -8,10 +9,19 @@ public class SnappApiResponse { public int Page; public int Limit; public string? SortDirection; - public T? Results { get; set; } + public T? Data { get; set; } } -public record Snapp(string Id, string Title, string Description); +public record Snapp( + string Id, + [property: JsonPropertyName("shortcode")] + string Slug, + [property: JsonPropertyName("created")] + DateTime CreatedAt, + [property: JsonPropertyName("original_url")] + string Url, + [property: JsonPropertyName("used")] + int VisitCount); public interface ISnappService { public Task>?> GetSnaps(); @@ -19,19 +29,24 @@ public interface ISnappService { public class SnappService : ISnappService { private readonly HttpClient _httpClient; - private readonly AppSettingsHelper _settingsHelper; + private readonly AppSettings _settings; - public SnappService(HttpClient httpClient, AppSettingsHelper settingsHelper) { + private readonly JsonSerializerOptions _jsonOptions = new() { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + + public SnappService(HttpClient httpClient, AppSettings settings) { _httpClient = httpClient; - _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {settingsHelper.ApiKey}"); - _settingsHelper = settingsHelper; + _settings = settings; + _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_settings.ApiKey}"); + _httpClient.BaseAddress = new Uri(Flurl.Url.Combine(_settings.ServerUrl, "api", "/")); } public async Task>?> GetSnaps() { - var url = Flurl.Url.Combine(_settingsHelper.ServerUrl, "/snapps"); + var url = "snapps"; var response = await _httpClient.GetAsync(url); var content = await response.Content.ReadAsStringAsync(); - return JsonSerializer.Deserialize>>(content); + return JsonSerializer.Deserialize>>(content, _jsonOptions); } } diff --git a/snapp-cli.sln.DotSettings.user b/snapp-cli.sln.DotSettings.user index e59f8c0..094e491 100644 --- a/snapp-cli.sln.DotSettings.user +++ b/snapp-cli.sln.DotSettings.user @@ -1,5 +1,7 @@  ForceIncluded ForceIncluded + ForceIncluded ForceIncluded + ForceIncluded ForceIncluded \ No newline at end of file