From 279d8247724cec556f9d4d267220a46c54b2ff6c Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Fri, 23 Feb 2024 03:23:57 +0000 Subject: [PATCH] feat: add mastodon status card --- OliverBooth/Data/IMastodonStatus.cs | 22 ++++++++++++++++++ OliverBooth/Data/MastodonStatus.cs | 18 +++++++++++++++ OliverBooth/Pages/Blog/Index.cshtml | 16 +++++++++++++ OliverBooth/Program.cs | 2 ++ OliverBooth/Services/IMastodonService.cs | 12 ++++++++++ OliverBooth/Services/MastodonService.cs | 29 ++++++++++++++++++++++++ docker-compose.yml | 2 ++ src/scss/app.scss | 13 +++++++++++ 8 files changed, 114 insertions(+) create mode 100644 OliverBooth/Data/IMastodonStatus.cs create mode 100644 OliverBooth/Data/MastodonStatus.cs create mode 100644 OliverBooth/Services/IMastodonService.cs create mode 100644 OliverBooth/Services/MastodonService.cs diff --git a/OliverBooth/Data/IMastodonStatus.cs b/OliverBooth/Data/IMastodonStatus.cs new file mode 100644 index 0000000..0ef875d --- /dev/null +++ b/OliverBooth/Data/IMastodonStatus.cs @@ -0,0 +1,22 @@ +namespace OliverBooth.Data; + +public interface IMastodonStatus +{ + /// + /// Gets the content of the status. + /// + /// The content. + string Content { get; } + + /// + /// Gets the date and time at which this status was posted. + /// + /// The post timestamp. + DateTimeOffset CreatedAt { get; } + + /// + /// Gets the original URI of the status. + /// + /// The original URI. + Uri OriginalUri { get; } +} \ No newline at end of file diff --git a/OliverBooth/Data/MastodonStatus.cs b/OliverBooth/Data/MastodonStatus.cs new file mode 100644 index 0000000..bb02662 --- /dev/null +++ b/OliverBooth/Data/MastodonStatus.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; + +namespace OliverBooth.Data; + +internal sealed class MastodonStatus : IMastodonStatus +{ + /// + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; + + /// + [JsonPropertyName("created_at")] + public DateTimeOffset CreatedAt { get; set; } + + /// + [JsonPropertyName("url")] + public Uri OriginalUri { get; set; } = null!; +} diff --git a/OliverBooth/Pages/Blog/Index.cshtml b/OliverBooth/Pages/Blog/Index.cshtml index d558cdf..6d7d37b 100644 --- a/OliverBooth/Pages/Blog/Index.cshtml +++ b/OliverBooth/Pages/Blog/Index.cshtml @@ -1,10 +1,26 @@ @page +@using Humanizer +@using OliverBooth.Data +@using OliverBooth.Services @model Index +@inject IMastodonService MastodonService @{ ViewData["Title"] = "Blog"; + IMastodonStatus latestStatus = MastodonService.GetLatestStatus(); } +
+
+ @Html.Raw(latestStatus.Content) +
+ +
+
@await Html.PartialAsync("_LoadingSpinner")
diff --git a/OliverBooth/Program.cs b/OliverBooth/Program.cs index b471977..afef81e 100644 --- a/OliverBooth/Program.cs +++ b/OliverBooth/Program.cs @@ -32,11 +32,13 @@ builder.Services.AddSingleton(provider => new MarkdownPipelineBuilder() builder.Services.AddDbContextFactory(); builder.Services.AddDbContextFactory(); +builder.Services.AddHttpClient(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddRazorPages().AddRazorRuntimeCompilation(); builder.Services.AddControllersWithViews(); diff --git a/OliverBooth/Services/IMastodonService.cs b/OliverBooth/Services/IMastodonService.cs new file mode 100644 index 0000000..57dc9d3 --- /dev/null +++ b/OliverBooth/Services/IMastodonService.cs @@ -0,0 +1,12 @@ +using OliverBooth.Data; + +namespace OliverBooth.Services; + +public interface IMastodonService +{ + /// + /// Gets the latest status posted to Mastodon. + /// + /// The latest status. + IMastodonStatus GetLatestStatus(); +} \ No newline at end of file diff --git a/OliverBooth/Services/MastodonService.cs b/OliverBooth/Services/MastodonService.cs new file mode 100644 index 0000000..3a561a8 --- /dev/null +++ b/OliverBooth/Services/MastodonService.cs @@ -0,0 +1,29 @@ +using System.Text.Json; +using OliverBooth.Data; + +namespace OliverBooth.Services; + +internal sealed class MastodonService : IMastodonService +{ + private readonly HttpClient _httpClient; + + public MastodonService(HttpClient httpClient) + { + _httpClient = httpClient; + } + + /// + public IMastodonStatus GetLatestStatus() + { + string token = Environment.GetEnvironmentVariable("MASTODON_TOKEN") ?? string.Empty; + string account = Environment.GetEnvironmentVariable("MASTODON_ACCOUNT") ?? string.Empty; + using var request = new HttpRequestMessage(); + request.Headers.Add("Authorization", $"Bearer {token}"); + request.RequestUri = new Uri($"https://mastodon.olivr.me/api/v1/accounts/{account}/statuses"); + + using HttpResponseMessage response = _httpClient.Send(request); + using var stream = response.Content.ReadAsStream(); + var statuses = JsonSerializer.Deserialize(stream) ?? Array.Empty(); + return statuses[0]; + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 9668736..3a9ace9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,3 +19,5 @@ services: environment: - SSL_CERT_PATH=${SSL_CERT_PATH} - SSL_KEY_PATH=${SSL_KEY_PATH} + - MASTODON_TOKEN=${MASTODON_TOKEN} + - MASTODON_ACCOUNT=${MASTODON_ACCOUNT} diff --git a/src/scss/app.scss b/src/scss/app.scss index 7e0c9aa..19e3129 100644 --- a/src/scss/app.scss +++ b/src/scss/app.scss @@ -402,4 +402,17 @@ td.trim-p p:last-child { color: #03A9F4; background-color: #1E1E1E !important; } +} + +.mastodon-update-card.card { + background-color: desaturate(darken(#6364FF, 50%), 50%); + margin-bottom: 50px; + + p:last-child { + margin-bottom: 0; + } + + button.btn.btn-mastodon { + background-color: #6364FF; + } } \ No newline at end of file