diff --git a/Newsbot.Cli.sln b/Newsbot.Cli.sln
new file mode 100644
index 0000000..f3d9890
--- /dev/null
+++ b/Newsbot.Cli.sln
@@ -0,0 +1,35 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+#
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newsbot.Cli", "Newsbot.Cli\Newsbot.Cli.csproj", "{1566F59D-6BFA-4F98-B4B0-F2A5D92B182B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newsbot.Domain", "Newsbot.Domain\Newsbot.Domain.csproj", "{71C391A5-9A94-449C-896E-8D6AB79CE44B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newsbot.Services", "Newsbot.Services\Newsbot.Services.csproj", "{B82F77EA-64FF-40AD-BD8B-6EAFAB2062BA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newsbot.Tests", "Newsbot.Tests\Newsbot.Tests.csproj", "{04B65EE4-E65C-4AA6-A27C-9400BE74FC31}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1566F59D-6BFA-4F98-B4B0-F2A5D92B182B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1566F59D-6BFA-4F98-B4B0-F2A5D92B182B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1566F59D-6BFA-4F98-B4B0-F2A5D92B182B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1566F59D-6BFA-4F98-B4B0-F2A5D92B182B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {71C391A5-9A94-449C-896E-8D6AB79CE44B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {71C391A5-9A94-449C-896E-8D6AB79CE44B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {71C391A5-9A94-449C-896E-8D6AB79CE44B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {71C391A5-9A94-449C-896E-8D6AB79CE44B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B82F77EA-64FF-40AD-BD8B-6EAFAB2062BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B82F77EA-64FF-40AD-BD8B-6EAFAB2062BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B82F77EA-64FF-40AD-BD8B-6EAFAB2062BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B82F77EA-64FF-40AD-BD8B-6EAFAB2062BA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {04B65EE4-E65C-4AA6-A27C-9400BE74FC31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {04B65EE4-E65C-4AA6-A27C-9400BE74FC31}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {04B65EE4-E65C-4AA6-A27C-9400BE74FC31}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {04B65EE4-E65C-4AA6-A27C-9400BE74FC31}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Newsbot.Cli/Commands/ArticlesListCommand.cs b/Newsbot.Cli/Commands/ArticlesListCommand.cs
new file mode 100644
index 0000000..ef5f040
--- /dev/null
+++ b/Newsbot.Cli/Commands/ArticlesListCommand.cs
@@ -0,0 +1,35 @@
+using System.Runtime.CompilerServices;
+using CliFx;
+using CliFx.Attributes;
+using CliFx.Infrastructure;
+using jtom38.Newsbot.Services;
+using jtom38.Newsbot.Services.Terminal;
+using Newsbot.Services.Collector;
+
+namespace jtom38.Newsbot.Cli.Commands;
+
+[Command("articles list", Description = "List the newest articles")]
+public class ArticlesListCommand : ICommand
+{
+ public async ValueTask ExecuteAsync(IConsole console)
+ {
+ var cfg = ConfigClient.LoadAsync();
+ var client = new ArticlesClient(cfg.Result.Uri);
+ var r = await client.ListArticles();
+
+ var count = 0;
+ foreach (var item in r)
+ {
+ var title = item.Title ?? "";
+ title = title.ReplaceLineEndings("");
+
+ var msg = $"[{count}] = {title}";
+ await console.Output.WriteLineAsync(msg);
+ count++;
+ }
+
+
+ //var resp = UserInputService.WaitForInput("Enter the number to read the article");
+
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Cli/Commands/Config/SetAuthKey.cs b/Newsbot.Cli/Commands/Config/SetAuthKey.cs
new file mode 100644
index 0000000..a7f5bcb
--- /dev/null
+++ b/Newsbot.Cli/Commands/Config/SetAuthKey.cs
@@ -0,0 +1,15 @@
+using CliFx;
+using CliFx.Attributes;
+using CliFx.Infrastructure;
+
+namespace jtom38.Newsbot.Cli.Commands.Config;
+
+[Command("config set token")]
+public class SetAuthKey : ICommand
+{
+ public ValueTask ExecuteAsync(IConsole console)
+ {
+ //await SetInstanceService.Save(Uri);
+ return default;
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Cli/Commands/Config/SetInstance.cs b/Newsbot.Cli/Commands/Config/SetInstance.cs
new file mode 100644
index 0000000..76aa6d1
--- /dev/null
+++ b/Newsbot.Cli/Commands/Config/SetInstance.cs
@@ -0,0 +1,18 @@
+using CliFx;
+using CliFx.Attributes;
+using CliFx.Infrastructure;
+using jtom38.Newsbot.Services.Config;
+
+namespace jtom38.Newsbot.Cli.Commands.Config;
+
+[Command("config set instance")]
+public class SetInstance: ICommand
+{
+ [CommandParameter(0, Description = "URI of the instance", Name = "uri")]
+ public required string Uri { get; set; }
+
+ public async ValueTask ExecuteAsync(IConsole console)
+ {
+ await SetInstanceService.Save(Uri);
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Cli/Commands/Config/ShowInstance.cs b/Newsbot.Cli/Commands/Config/ShowInstance.cs
new file mode 100644
index 0000000..5692807
--- /dev/null
+++ b/Newsbot.Cli/Commands/Config/ShowInstance.cs
@@ -0,0 +1,16 @@
+using CliFx;
+using CliFx.Attributes;
+using CliFx.Infrastructure;
+using jtom38.Newsbot.Services;
+
+namespace jtom38.Newsbot.Cli.Commands.Config;
+
+[Command("config show instance")]
+public class ShowInstance : ICommand
+{
+ public async ValueTask ExecuteAsync(IConsole console)
+ {
+ var res = await ConfigClient.LoadAsync();
+ await console.Output.WriteLineAsync(res.Uri);
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Cli/Commands/SourcesList.cs b/Newsbot.Cli/Commands/SourcesList.cs
new file mode 100644
index 0000000..7e0c53c
--- /dev/null
+++ b/Newsbot.Cli/Commands/SourcesList.cs
@@ -0,0 +1,14 @@
+using CliFx;
+using CliFx.Attributes;
+using CliFx.Infrastructure;
+
+namespace jtom38.Newsbot.Cli.Commands;
+
+[Command("sources list", Description = "Lists the known sources")]
+public class SourcesList : ICommand
+{
+ public async ValueTask ExecuteAsync(IConsole console)
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Cli/Newsbot.Cli b/Newsbot.Cli/Newsbot.Cli
new file mode 100755
index 0000000..4a2ee73
Binary files /dev/null and b/Newsbot.Cli/Newsbot.Cli differ
diff --git a/Newsbot.Cli/Newsbot.Cli.csproj b/Newsbot.Cli/Newsbot.Cli.csproj
new file mode 100644
index 0000000..027b9d1
--- /dev/null
+++ b/Newsbot.Cli/Newsbot.Cli.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+ true
+ true
+ jtom38.Newsbot.Cli
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Newsbot.Cli/Program.cs b/Newsbot.Cli/Program.cs
new file mode 100644
index 0000000..f2b3e2e
--- /dev/null
+++ b/Newsbot.Cli/Program.cs
@@ -0,0 +1,7 @@
+using CliFx;
+
+await new CliApplicationBuilder()
+ .AddCommandsFromThisAssembly()
+ .SetExecutableName("Newsbot.Cli")
+ .Build()
+ .RunAsync();
\ No newline at end of file
diff --git a/Newsbot.Domain/Models/Collector/ArticleDetailsDto.cs b/Newsbot.Domain/Models/Collector/ArticleDetailsDto.cs
new file mode 100644
index 0000000..870ae86
--- /dev/null
+++ b/Newsbot.Domain/Models/Collector/ArticleDetailsDto.cs
@@ -0,0 +1,20 @@
+namespace jtom38.Newsbot.Domain.Models.Collector;
+
+public class ArticleDetailsDto
+{
+ public Guid ID { get; set; }
+ public string[]? Tags { get; set; }
+ public string? Title { get; set; }
+ public string? Url { get; set; }
+ public DateTime PubDate { get; set; }
+ public string? Video { get; set; }
+ public int VideoHeight { get; set; }
+ public int VideoWidth { get; set; }
+ public string? Thumbnail { get; set; }
+ public string? Description { get; set; }
+ public string? AuthorName { get; set; }
+ public string? AuthorImage { get; set; }
+
+ public SourceDto? Source { get; set; }
+
+}
\ No newline at end of file
diff --git a/Newsbot.Domain/Models/Collector/ArticlesDto.cs b/Newsbot.Domain/Models/Collector/ArticlesDto.cs
new file mode 100644
index 0000000..d9273e4
--- /dev/null
+++ b/Newsbot.Domain/Models/Collector/ArticlesDto.cs
@@ -0,0 +1,45 @@
+using Newtonsoft.Json;
+
+namespace jtom38.Newsbot.Domain.Models.Collector;
+
+public class ArticlesDto
+{
+ [JsonProperty("id")]
+ public Guid Id { get; set; }
+
+ [JsonProperty("sourceId")]
+ public Guid SourceId { get; set; }
+
+ [JsonProperty("tags")]
+ public List? Tags { get; set; }
+
+ [JsonProperty("title")]
+ public string? Title { get; set; }
+
+ [JsonProperty("url")]
+ public string? Url { get; set; }
+
+ [JsonProperty("pubDate")]
+ public DateTime PubDate { get; set; }
+
+ [JsonProperty("video")]
+ public string? Video { get; set; }
+
+ [JsonProperty("videoHeight")]
+ public int VideoHeight { get; set; }
+
+ [JsonProperty("videoWidth")]
+ public int VideoWidth { get; set; }
+
+ [JsonProperty("thumbnail")]
+ public string? Thumbnail { get; set; }
+
+ [JsonProperty("description")]
+ public string? Description { get; set; }
+
+ [JsonProperty("authorName")]
+ public string? AuthorName { get; set; }
+
+ [JsonProperty("authorImage")]
+ public string? AuthorImage { get; set; }
+}
\ No newline at end of file
diff --git a/Newsbot.Domain/Models/Collector/DiscordWebHookDto.cs b/Newsbot.Domain/Models/Collector/DiscordWebHookDto.cs
new file mode 100644
index 0000000..e038877
--- /dev/null
+++ b/Newsbot.Domain/Models/Collector/DiscordWebHookDto.cs
@@ -0,0 +1,10 @@
+namespace jtom38.Newsbot.Domain.Models.Collector;
+
+public class DiscordWebHookDto
+{
+ public Guid ID { get; set; }
+ public string? Url { get; set; }
+ public string? Server { get; set; }
+ public string? Channel { get; set; }
+ public bool Enabled { get; set; }
+}
\ No newline at end of file
diff --git a/Newsbot.Domain/Models/Collector/SourceDto.cs b/Newsbot.Domain/Models/Collector/SourceDto.cs
new file mode 100644
index 0000000..c153aa9
--- /dev/null
+++ b/Newsbot.Domain/Models/Collector/SourceDto.cs
@@ -0,0 +1,15 @@
+namespace jtom38.Newsbot.Domain.Models.Collector;
+
+public class SourceDto
+{
+ public Guid ID { get; set; }
+ public string? Site { get; set; }
+ public string? Name { get; set; }
+ public string? Source { get; set; }
+ public string? Type { get; set; }
+ public string? Value { get; set; }
+ public bool Enabled { get; set; }
+ public string? Url { get; set; }
+ public string[]? Tags { get; set; }
+ public bool Deleted { get; set; }
+}
\ No newline at end of file
diff --git a/Newsbot.Domain/Models/Collector/SubscriptionDetailsDto.cs b/Newsbot.Domain/Models/Collector/SubscriptionDetailsDto.cs
new file mode 100644
index 0000000..ada7dec
--- /dev/null
+++ b/Newsbot.Domain/Models/Collector/SubscriptionDetailsDto.cs
@@ -0,0 +1,11 @@
+namespace jtom38.Newsbot.Domain.Models.Collector;
+
+public class SubscriptionDetailsDto
+{
+ public Guid Id { get; set; }
+ public bool CodeAllowReleases { get; set; }
+ public bool CodeAllowCommits { get; set; }
+ public SourceDto? Source { get; set; }
+ public DiscordWebHookDto? DiscordWebHook { get; set; }
+
+}
\ No newline at end of file
diff --git a/Newsbot.Domain/Models/Collector/SubscriptionDto.cs b/Newsbot.Domain/Models/Collector/SubscriptionDto.cs
new file mode 100644
index 0000000..cefd2be
--- /dev/null
+++ b/Newsbot.Domain/Models/Collector/SubscriptionDto.cs
@@ -0,0 +1,10 @@
+namespace jtom38.Newsbot.Domain.Models.Collector;
+
+public class SubscriptionDto
+{
+ public Guid Id { get; set; }
+ public Guid SourceId { get; set; }
+ public Guid DiscordWebHookId { get; set; }
+ public bool CodeAllowReleases { get; set; }
+ public bool CodeAllowCommits { get; set; }
+}
\ No newline at end of file
diff --git a/Newsbot.Domain/Models/Config.cs b/Newsbot.Domain/Models/Config.cs
new file mode 100644
index 0000000..15de88f
--- /dev/null
+++ b/Newsbot.Domain/Models/Config.cs
@@ -0,0 +1,7 @@
+namespace jtom38.Newsbot.Domain.Models;
+
+public class ConfigModel
+{
+ public string? Uri { get; set; }
+ public string? ApiToken { get; set; }
+}
\ No newline at end of file
diff --git a/Newsbot.Domain/Newsbot.Domain.csproj b/Newsbot.Domain/Newsbot.Domain.csproj
new file mode 100644
index 0000000..0964c6e
--- /dev/null
+++ b/Newsbot.Domain/Newsbot.Domain.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net7.0
+ enable
+ enable
+ jtom38.Newsbot.Domain
+
+
+
+
+
+
+
diff --git a/Newsbot.Services/Collector/ArticlesClient.cs b/Newsbot.Services/Collector/ArticlesClient.cs
new file mode 100644
index 0000000..51c29f1
--- /dev/null
+++ b/Newsbot.Services/Collector/ArticlesClient.cs
@@ -0,0 +1,27 @@
+using Newtonsoft.Json;
+using jtom38.Newsbot.Domain.Models.Collector;
+
+namespace Newsbot.Services.Collector;
+
+public class ArticlesClient
+{
+ private readonly HttpClient _client;
+ private string? InstanceUri { get; set; }
+
+ public ArticlesClient(string? instanceUri)
+ {
+ _client = new HttpClient();
+ InstanceUri = instanceUri;
+ }
+
+ public async Task> ListArticles()
+ {
+ var resp = await _client.GetAsync($"{InstanceUri}/api/articles");
+ var content = await resp.Content.ReadAsStringAsync();
+ var res = JsonConvert.DeserializeObject>(content);
+
+ res ??= new List();
+
+ return res;
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Services/Config/SetInstanceService.cs b/Newsbot.Services/Config/SetInstanceService.cs
new file mode 100644
index 0000000..21fe492
--- /dev/null
+++ b/Newsbot.Services/Config/SetInstanceService.cs
@@ -0,0 +1,25 @@
+using jtom38.Newsbot.Domain.Models;
+
+namespace jtom38.Newsbot.Services.Config;
+
+public class SetInstanceService
+{
+ public static async Task Save(string uri)
+ {
+ var containsHttp = uri.Contains("http://");
+ var containsHttps = uri.Contains("https://");
+ if (!containsHttp && !containsHttps)
+ {
+ throw new Exception("Uri does not define http or https.");
+ }
+
+ Console.WriteLine($"Instance Set to '{uri}'");
+
+ var cfg = await ConfigClient.LoadAsync();
+
+ cfg ??= new ConfigModel();
+ cfg.Uri = uri ?? "";
+
+ await ConfigClient.SaveAsync(cfg);
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Services/ConfigClient.cs b/Newsbot.Services/ConfigClient.cs
new file mode 100644
index 0000000..c466ebb
--- /dev/null
+++ b/Newsbot.Services/ConfigClient.cs
@@ -0,0 +1,55 @@
+using System.Text.Json;
+using jtom38.Newsbot.Domain.Models;
+
+namespace jtom38.Newsbot.Services;
+
+public static class ConfigClient
+{
+ public static async Task LoadAsync()
+ {
+ var blank = new ConfigModel();
+ try
+ {
+ var cfg = await LoadFileAsync();
+ return cfg;
+ }
+ catch (DirectoryNotFoundException)
+ {
+ Directory.CreateDirectory(GetConfigPath());
+ await SaveAsync(blank);
+ return blank;
+ }
+ catch (FileNotFoundException)
+ {
+ await SaveAsync(blank);
+ return blank;
+ }
+ }
+
+ public static async Task SaveAsync(ConfigModel config)
+ {
+ var jsonString = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true});
+ await File.WriteAllTextAsync(GetConfigPath(), jsonString);
+ }
+
+ private static string GetConfigDirectory()
+ {
+ var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ var path = Path.Join(appDataPath, "newsbot-cli");
+
+ return path;
+ }
+
+ private static string GetConfigPath()
+ {
+ var path = Path.Join(GetConfigDirectory(), "config.json");
+ return path;
+ }
+
+ private static async Task LoadFileAsync()
+ {
+ var content = await File.ReadAllTextAsync(GetConfigPath());
+ var res = JsonSerializer.Deserialize(content);
+ return res ?? new ConfigModel();
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Services/Newsbot.Services.csproj b/Newsbot.Services/Newsbot.Services.csproj
new file mode 100644
index 0000000..e0cc086
--- /dev/null
+++ b/Newsbot.Services/Newsbot.Services.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net7.0
+ enable
+ enable
+ jtom38.Newsbot.Services
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Newsbot.Services/Terminal/UserInputService.cs b/Newsbot.Services/Terminal/UserInputService.cs
new file mode 100644
index 0000000..1e7d597
--- /dev/null
+++ b/Newsbot.Services/Terminal/UserInputService.cs
@@ -0,0 +1,18 @@
+namespace jtom38.Newsbot.Services.Terminal;
+
+public class UserInputService
+{
+ public UserInputService()
+ {
+
+ }
+
+ public static async Task WaitForInput(string message)
+ {
+ await Task.Delay(1);
+ Console.WriteLine(message);
+ Console.WriteLine("Enter your selection or press 'q' to exit");
+ var input = Console.ReadLine();
+ return input ?? "";
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Tests/Clients/ArticlesClientTests.cs b/Newsbot.Tests/Clients/ArticlesClientTests.cs
new file mode 100644
index 0000000..8cf7d74
--- /dev/null
+++ b/Newsbot.Tests/Clients/ArticlesClientTests.cs
@@ -0,0 +1,20 @@
+using jtom38.Newsbot.Domain.Models.Collector;
+using Newsbot.Services.Collector;
+
+namespace Newsbot.Tests.Clients;
+
+public class ArticlesClientTests
+{
+ [Fact]
+ public async Task ArticlesAreReturned()
+ {
+ var c = new ArticlesClient("http://192.168.1.225:5001");
+ var res = await c.ListArticles();
+ res ??= new List();
+
+ if (res.Count == 0)
+ {
+ Assert.Fail("No results came back");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Tests/Commands/SetAuthKeyTest.cs b/Newsbot.Tests/Commands/SetAuthKeyTest.cs
new file mode 100644
index 0000000..3051e7d
--- /dev/null
+++ b/Newsbot.Tests/Commands/SetAuthKeyTest.cs
@@ -0,0 +1,6 @@
+namespace Newsbot.Services.Config;
+
+public class SetAuthKeyTest
+{
+
+}
\ No newline at end of file
diff --git a/Newsbot.Tests/Commands/SetInstanceTest.cs b/Newsbot.Tests/Commands/SetInstanceTest.cs
new file mode 100644
index 0000000..6860a28
--- /dev/null
+++ b/Newsbot.Tests/Commands/SetInstanceTest.cs
@@ -0,0 +1,30 @@
+using jtom38.Newsbot.Domain.Models;
+using jtom38.Newsbot.Services;
+using jtom38.Newsbot.Services.Config;
+using Xunit.Abstractions;
+
+namespace Newsbot.Tests.Commands;
+
+public class SetInstanceTest
+{
+ private readonly ITestOutputHelper _testOutputHelper;
+
+ public SetInstanceTest(ITestOutputHelper testOutputHelper)
+ {
+ _testOutputHelper = testOutputHelper;
+ }
+
+ [Fact]
+ public async Task SetInstanceSavesTheUri()
+ {
+ var uri = "http://localhost:5001";
+ try
+ {
+ await SetInstanceService.Save(uri);
+ }
+ catch(Exception ex)
+ {
+ Assert.Fail(ex.Message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Tests/Newsbot.Tests.csproj b/Newsbot.Tests/Newsbot.Tests.csproj
new file mode 100644
index 0000000..30afcc3
--- /dev/null
+++ b/Newsbot.Tests/Newsbot.Tests.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Newsbot.Tests/Services/ConfigClientTests.cs b/Newsbot.Tests/Services/ConfigClientTests.cs
new file mode 100644
index 0000000..0f3d532
--- /dev/null
+++ b/Newsbot.Tests/Services/ConfigClientTests.cs
@@ -0,0 +1,18 @@
+using jtom38.Newsbot.Domain.Models;
+using jtom38.Newsbot.Services;
+
+namespace Newsbot.Tests.Services;
+
+public class ConfigClientTests
+{
+ [Fact]
+ public async Task CanLoadConfig()
+ {
+ var cfg = await ConfigClient.LoadAsync();
+ cfg = cfg ??= new ConfigModel();
+ if (cfg.Uri == "")
+ {
+ Assert.Fail("Uri was missing");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Newsbot.Tests/Usings.cs b/Newsbot.Tests/Usings.cs
new file mode 100644
index 0000000..8c927eb
--- /dev/null
+++ b/Newsbot.Tests/Usings.cs
@@ -0,0 +1 @@
+global using Xunit;
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index 53882a8..0000000
--- a/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Newsbot.Cli
-
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..140322d
--- /dev/null
+++ b/makefile
@@ -0,0 +1,12 @@
+.PHONY: help
+help: ## Shows this help command
+ @egrep -h '\s##\s' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
+
+build: ## builds the application with the current go runtime
+ dotnet restore
+ dotnet build
+
+pub: ## Generate artifacts
+ dotnet restore
+ dotnet publish
+ cp ./Newsbot.Cli/bin/Debug/net7.0/osx-arm64/publish/Newsbot.Cli ./newsbot
\ No newline at end of file