List snaps command working

This commit is contained in:
Fergal Moran
2024-07-26 18:23:09 +01:00
parent 2daa52aa04
commit 9459b49518
9 changed files with 102 additions and 48 deletions

View File

@@ -7,7 +7,7 @@ namespace Snapp.Cli.Commands;
public class AddSnappsCommand : Command<AddSnappsCommand.Settings> {
public sealed class Settings : DefaultCommandSettings {
public Settings(IOptions<AppSettings> 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<AddSnappsCommand.Settings> {
.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}");

View File

@@ -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<DebugCommand.Settings> {
}
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings) {
Console.WriteLine($"Echoing: {settings.EchoText}");
Log.Debug($"Echoing: {settings.EchoText}");
return await Task.FromResult(3);
}
}

View File

@@ -9,8 +9,8 @@ namespace Snapp.Cli.Commands;
public class DefaultCommandSettings : CommandSettings {
public readonly AppSettings Config;
public DefaultCommandSettings(IOptions<AppSettings> settings) {
Config = settings.Value;
protected DefaultCommandSettings(AppSettings settings) {
Config = settings;
}
[Description("Path to search. Defaults to current directory.")]

View File

@@ -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<ListSnappsCommand.Settings> {
private readonly SnappService _snappService;
public ListSnappsCommand(SnappService snappService) {
_snappService = snappService;
}
public sealed class Settings : CommandSettings { }
// public sealed class Settings : CommandSettings {
// public Settings(IOptions<AppSettings> settings) : base(settings) { }
// }
public class ListSnappsCommand(SnappService snappService) :
AsyncCommand<ListSnappsCommand.Settings> {
public sealed class Settings(AppSettings settings) :
DefaultCommandSettings(settings);
public override async Task<int> 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;
}
}

View File

@@ -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<AppSettings>();
if (c is null) {
throw new NullReferenceException("Missing settings");
}
return c;
return config;
}
}

17
Helpers/Log.cs Normal file
View File

@@ -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
}
}

View File

@@ -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<SnappService>();
registrations.AddSingleton<AppSettingsHelper>();
registrations.AddHttpClient<ISnappService, SnappService>();
registrations.AddScoped<AppSettings>(sp => sp.GetRequiredService<IOptions<AppSettings>>().Value);
registrations.AddSingleton<AppSettingsHelper>();
registrations.AddOptions();
var registrar = new Snapp.Cli.Helpers.TypeRegistrar(registrations);
var registrar = new TypeRegistrar(registrations);
var app = new CommandApp<DebugCommand>(registrar);
app.Configure(config => {
config.CaseSensitivity(CaseSensitivity.None);
config.SetApplicationName("Snapp CLI");
config.ValidateExamples();
#if DEBUG
config.PropagateExceptions();
config.ValidateExamples();
#endif
config.AddCommand<DebugCommand>("debug");
config.AddCommand<ListSnappsCommand>("list");
config.AddCommand<AddSnappsCommand>("add");
});
return await app

View File

@@ -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<T> {
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<SnappApiResponse<List<Snapp>>?> 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<SnappApiResponse<List<Snapp>>?> 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<SnappApiResponse<List<Snapp>>>(content);
return JsonSerializer.Deserialize<SnappApiResponse<List<Snapp>>>(content, _jsonOptions);
}
}

View File

@@ -1,5 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AConfigurationBinder_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Ffergalm_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F5890bea1acfbf3fed68846cf88de417726aefd9611192c0103fe2da89fa41_003FConfigurationBinder_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Ffergalm_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fbf9021a960b74107a7e141aa06bc9d8a0a53c929178c2fb95b1597be8af8dc_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpClient_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Ffergalm_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F60038225224a9318597b3232280390933d3c3fe85d9ed859a7e4825915eb1c_003FHttpClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIConfigurator_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Ffergalm_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fb292bc073ef4ad0e85311a67c8972e3da13f217b81775ed3eb2fa38e4fa2d32_003FIConfigurator_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002ESerialization_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Ffergalm_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Ffdb8d9b3b165267805e3e95fc1e2a1d825f7e0eeeeb752f3468f145d3889a_003FThrowHelper_002ESerialization_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATypeRegistrar_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Ffergalm_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fef4e8f922fc4e26f8bd814dcaba442da850104c6523e517b0ac47e83c7e2da_003FTypeRegistrar_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>