mirror of
https://github.com/fergalmoran/snapp-cli.git
synced 2025-12-22 10:00:52 +00:00
List snaps command working
This commit is contained in:
@@ -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}");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.")]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
17
Helpers/Log.cs
Normal 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
|
||||
}
|
||||
}
|
||||
17
Program.cs
17
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<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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user