PancakesWeb/PancakesWeb/Controllers/FeedController.cs

171 lines
No EOL
6.1 KiB
C#

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;
[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");
}
[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<JsonFeedAuthor>? Authors { get; set; }
[J("language")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Language { get; set; }
[J("items")] public List<JsonFeedItem> 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<string>? Tags { get; set; }
}
}