Improved RSS feeds

This commit is contained in:
Mia Rose Winter 2024-03-14 11:36:48 +01:00
parent b3867fdcae
commit 9f6f3cb142
Signed by: miawinter
GPG key ID: 4B6F6A83178F595E
2 changed files with 40 additions and 19 deletions

View file

@ -1,4 +1,5 @@
using System.ServiceModel.Syndication; using System.Net;
using System.ServiceModel.Syndication;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -58,20 +59,44 @@ public class RssController(IOptions<Customization> customizations, ApplicationDb
} }
private SyndicationFeed CreateFeedAsync(IEnumerable<Article> articles, DateTimeOffset date, string? routeName, string? category) { private SyndicationFeed CreateFeedAsync(IEnumerable<Article> articles, DateTimeOffset date, string? routeName, string? category) {
string appName = Customizations.Value.AppName; var customizations = Customizations.Value;
var host = new Uri($"https://{Request.Host}{Request.PathBase}", UriKind.Absolute);
var link = new Uri(Url.RouteUrl(routeName, null, "https", host.Host) ?? host.AbsoluteUri);
var feed = new SyndicationFeed(appName, "Feed on " + appName, link, articles string appName = customizations.AppName;
.Select(article => { Uri host;
if (string.IsNullOrWhiteSpace(customizations.AppUrl)) {
host = new Uri(customizations.AppUrl);
} else {
host = new Uri($"https://{Request.Host}", UriKind.Absolute);
}
var feedLink = new Uri(Url.RouteUrl(routeName, null, "https", host.Host) ?? host.AbsoluteUri);
var htmlLink = host;
if (category is not null) {
feedLink = new Uri(feedLink.AbsoluteUri + "?category=" + WebUtility.HtmlEncode(category));
htmlLink = new Uri(host, "/category/" + WebUtility.HtmlEncode(category));
}
var feed = new SyndicationFeed(appName, "Feed on " + appName, htmlLink, host.AbsoluteUri, date) {
TimeToLive = TimeSpan.FromMinutes(15),
Generator = "Wave",
Links = { new SyndicationLink(feedLink) {RelationshipType = "self"} },
Items = GetItems(articles, host)
};
if (category != null) feed.Categories.Add(new SyndicationCategory(category));
return feed;
}
private static IEnumerable<SyndicationItem> GetItems(IEnumerable<Article> articles, Uri host) {
return articles.Select(article => {
var item = new SyndicationItem( var item = new SyndicationItem(
article.Title, article.Title,
new TextSyndicationContent(article.BodyHtml, TextSyndicationContentKind.Html), new TextSyndicationContent(article.BodyHtml, TextSyndicationContentKind.Html),
new Uri(ArticleUtilities.GenerateArticleLink(article, host)), new Uri(ArticleUtilities.GenerateArticleLink(article, host)),
new Uri(host, "article/" + article.Id).AbsoluteUri, new Uri(host, "article/" + article.Id).AbsoluteUri,
article.PublishDate) { article.LastPublicChange)
{
Authors = { Authors = {
new SyndicationPerson { Name = article.Author.FullName } new SyndicationPerson {Name = article.Author.FullName}
}, },
LastUpdatedTime = article.LastModified ?? article.PublishDate, LastUpdatedTime = article.LastModified ?? article.PublishDate,
PublishDate = article.PublishDate PublishDate = article.PublishDate
@ -80,18 +105,9 @@ public class RssController(IOptions<Customization> customizations, ApplicationDb
foreach (var category in article.Categories.OrderBy(c => c.Color)) { foreach (var category in article.Categories.OrderBy(c => c.Color)) {
item.Categories.Add(new SyndicationCategory(category.Name)); item.Categories.Add(new SyndicationCategory(category.Name));
} }
return item; return item;
}) })
.ToList()) { .ToList();
TimeToLive = TimeSpan.FromMinutes(15),
LastUpdatedTime = date,
Generator = "Wave",
Links = {
new SyndicationLink(link) { RelationshipType = "self" }
}
};
if (category != null) feed.Categories.Add(new SyndicationCategory(category));
return feed;
} }
} }

View file

@ -33,6 +33,11 @@ public class Article : ISoftDelete {
public DateTimeOffset PublishDate { get; set; } = DateTimeOffset.MaxValue; public DateTimeOffset PublishDate { get; set; } = DateTimeOffset.MaxValue;
public DateTimeOffset? LastModified { get; set; } public DateTimeOffset? LastModified { get; set; }
/// <summary>
/// Returns LastModified if it's after the articles PublishDate, otherwise gives you the PublishDate
/// </summary>
public DateTimeOffset LastPublicChange => LastModified > PublishDate ? LastModified.Value : PublishDate;
public IList<Category> Categories { get; } = []; public IList<Category> Categories { get; } = [];
public IList<ArticleImage> Images { get; } = []; public IList<ArticleImage> Images { get; } = [];
} }