From fb4d9fa0aa842151bc043a2b4f405701a5a65c8b Mon Sep 17 00:00:00 2001 From: pancakes
Date: Tue, 16 Sep 2025 13:50:08 +1000
Subject: [PATCH] Add Atom 1.0 feed syndication
---
PancakesWeb/Controllers/FeedController.cs | 48 ++++++++++++++++++
PancakesWeb/Data/Button.cs | 6 +++
PancakesWeb/PancakesWeb.csproj | 1 +
PancakesWeb/Program.cs | 2 +
.../wwwroot/imgs/buttons/valid_atom.webp | Bin 0 -> 2060 bytes
5 files changed, 57 insertions(+)
create mode 100644 PancakesWeb/Controllers/FeedController.cs
create mode 100644 PancakesWeb/wwwroot/imgs/buttons/valid_atom.webp
diff --git a/PancakesWeb/Controllers/FeedController.cs b/PancakesWeb/Controllers/FeedController.cs
new file mode 100644
index 0000000..ee35304
--- /dev/null
+++ b/PancakesWeb/Controllers/FeedController.cs
@@ -0,0 +1,48 @@
+using System.Net.Mime;
+using System.ServiceModel.Syndication;
+using System.Xml;
+using Microsoft.AspNetCore.Mvc;
+using PancakesWeb.Components.UI;
+
+namespace PancakesWeb.Controllers;
+
+[ApiController]
+public class FeedController : ControllerBase
+{
+ [HttpGet("/feed.atom")]
+ [Produces("application/atom+xml")]
+ public ContentResult GetAtomFeed()
+ {
+ var feed = new SyndicationFeed
+ {
+ Title = new TextSyndicationContent("pancakes' blog"),
+ Description = new TextSyndicationContent("🐈⬛"),
+ Id = "https://pancakes.gay/feed.atom",
+ BaseUri = new Uri("https://pancakes.gay/feed.atom"),
+ Authors = { new SyndicationPerson("p@pancakes.gay", "pancakes", "https://pancakes.gay") },
+ Items = BlogPosts.Posts.OrderByDescending(post => post.Published).Select(post =>
+ new SyndicationItem(post.Title, SyndicationContent.CreateHtmlContent(post.Content),
+ new Uri($"https://pancakes.gay/{post.Slug}"), $"https://pancakes.gay/{post.Slug}",
+ new DateTimeOffset(post.Edited ?? post.Published))
+ {
+ Copyright = post.Footer is BlogPosts.PostFooter.CcBy
+ ? new TextSyndicationContent(
+ $"{post.Title} © {post.Published.Year} by pancakes is licensed under CC BY 4.0")
+ : null,
+ PublishDate = new DateTimeOffset(post.Published),
+ Summary = new TextSyndicationContent(post.Description)
+ }),
+ Links =
+ {
+ SyndicationLink.CreateSelfLink(new Uri("https://pancakes.gay/feed.atom")),
+ SyndicationLink.CreateAlternateLink(new Uri("https://pancakes.gay"), MediaTypeNames.Text.Html),
+ }
+ };
+
+ var stringWriter = new StringWriter();
+ var writer = new XmlTextWriter(stringWriter);
+ feed.SaveAsAtom10(writer);
+
+ return Content(stringWriter.ToString(), "application/atom+xml");
+ }
+}
\ No newline at end of file
diff --git a/PancakesWeb/Data/Button.cs b/PancakesWeb/Data/Button.cs
index fe50183..442b8e5 100644
--- a/PancakesWeb/Data/Button.cs
+++ b/PancakesWeb/Data/Button.cs
@@ -187,6 +187,12 @@ public static class Buttons
{
Image = "wii.webp",
Title = "Wii"
+ },
+ new Button
+ {
+ Image = "valid_atom.webp",
+ Title = "Valid Atom 1.0",
+ Href = "/feed.atom"
}
];
}
\ No newline at end of file
diff --git a/PancakesWeb/PancakesWeb.csproj b/PancakesWeb/PancakesWeb.csproj
index 13d4c41..224fc7f 100644
--- a/PancakesWeb/PancakesWeb.csproj
+++ b/PancakesWeb/PancakesWeb.csproj
@@ -8,6 +8,7 @@
}-@&kJzya0r&|GY2=-!HV|a`+$a#N`TqJUm>!kLUk>
ze9W$2es18ebDsPD%=sVk13-cRu#2lGtEwnN9{=VLZUR90qpK(@Lnyx!K@b3VD8Cc2
O+&{d3_^(#y&i?{^O2C=`
literal 0
HcmV?d00001
DXU)pVjh30uT5`k>36PU2E7bF@#a({6GMV45ZglUoc6spf+knQ{WRv-@
z)y0hq!TBfr5ITLUrPVQU1=W!np$hdAL6QLM;8GWXF(>R)k9S!f6xC}9