diff --git a/PancakesWeb/Controllers/FeedController.cs b/PancakesWeb/Controllers/FeedController.cs index ee35304..a4d7efd 100644 --- a/PancakesWeb/Controllers/FeedController.cs +++ b/PancakesWeb/Controllers/FeedController.cs @@ -1,8 +1,11 @@ using System.Net.Mime; using System.ServiceModel.Syndication; +using System.Text.Json.Serialization; using System.Xml; using Microsoft.AspNetCore.Mvc; using PancakesWeb.Components.UI; +using J = System.Text.Json.Serialization.JsonPropertyNameAttribute; +using JI = System.Text.Json.Serialization.JsonIgnoreAttribute; namespace PancakesWeb.Controllers; @@ -45,4 +48,124 @@ public class FeedController : ControllerBase return Content(stringWriter.ToString(), "application/atom+xml"); } + + [HttpGet("/feed.json")] + [Produces("application/feed+json", MediaTypeNames.Application.Json)] + public JsonFeed GetJsonFeed() => new JsonFeed + { + Title = "pancakes' blog", + HomePageUrl = "https://pancakes.gay", + FeedUrl = "https://pancakes.gay/feed.json", + Description = "🐈‍⬛", + Icon = "https://pancakes.gay/icon.webp", + Favicon = "https://pancakes.gay/favicon.ico", + Authors = + [ + new JsonFeedAuthor + { + Name = "pancakes", + Url = "https://pancakes.gay", + Avatar = "https://pancakes.gay/icon.webp" + } + ], + Language = "en", + Items = BlogPosts.Posts.OrderByDescending(post => post.Published).Select(post => new JsonFeedItem + { + Id = $"https://pancakes.gay/{post.Slug}", + Url = $"https://pancakes.gay/{post.Slug}", + Title = post.Title, + ContentHtml = post.Content, + Summary = post.Description, + BannerImage = $"https://pancakes.gay/post-assets/{post.Slug}/{post.HeaderFilename}", + DatePublished = post.Published, + DateModified = post.Edited, + Tags = null + }).ToList() + }; + + public class JsonFeed + { + [J("version")] public string Version => "https://jsonfeed.org/version/1.1"; + [J("title")] public required string Title { get; set; } + + [J("home_page_url")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? HomePageUrl { get; set; } + + [J("feed_url")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? FeedUrl { get; set; } + + [J("description")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Description { get; set; } + + [J("icon")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Icon { get; set; } + + [J("favicon")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Favicon { get; set; } + + [J("authors")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? Authors { get; set; } + + [J("language")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Language { get; set; } + + [J("items")] public List Items { get; set; } = []; + } + + public class JsonFeedAuthor + { + [J("name")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Name { get; set; } + + [J("url")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Url { get; set; } + + [J("avatar")] + [JI(Condition = JsonIgnoreCondition.Never)] + public string? Avatar { get; set; } + } + + public class JsonFeedItem + { + [J("id")] public required string Id { get; set; } + + [J("url")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Url { get; set; } + + [J("title")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Title { get; set; } + + [J("content_html")] public required string ContentHtml { get; set; } + + [J("summary")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Summary { get; set; } + + [J("banner_image")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? BannerImage { get; set; } + + [J("date_published")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public DateTime? DatePublished { get; set; } + + [J("date_modified")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public DateTime? DateModified { get; set; } + + [J("tags")] + [JI(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List? Tags { get; set; } + } } \ No newline at end of file