From 7cd24d29f7813bdd6c98472a5790f85e3e3d12b2 Mon Sep 17 00:00:00 2001 From: Mia Winter Date: Thu, 14 Mar 2024 12:17:30 +0100 Subject: [PATCH] Implemented RSS feed with Author filter --- Wave/Components/Pages/UserView.razor | 10 +++++++ Wave/Controllers/RssController.cs | 43 +++++++++++++++++++--------- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/Wave/Components/Pages/UserView.razor b/Wave/Components/Pages/UserView.razor index 611e08a..e354ef8 100644 --- a/Wave/Components/Pages/UserView.razor +++ b/Wave/Components/Pages/UserView.razor @@ -1,12 +1,22 @@ @page "/profile/{id:guid}" @using Wave.Data @using Microsoft.EntityFrameworkCore +@using Microsoft.Extensions.Options @using Wave.Utilities @inject IDbContextFactory ContextFactory +@inject IOptions Customizations +@inject IOptions Features @inject IStringLocalizer Localizer @inject IMessageDisplay Message + + @if (Features.Value.Rss && User is not null) { + + + } + + @(TitlePrefix + @Localizer["Title"] + " | " + (User?.FullName ?? Localizer["NotFound_Title"])) @if (User is null) { diff --git a/Wave/Controllers/RssController.cs b/Wave/Controllers/RssController.cs index 26be12a..55df620 100644 --- a/Wave/Controllers/RssController.cs +++ b/Wave/Controllers/RssController.cs @@ -1,5 +1,6 @@ using System.Net; using System.ServiceModel.Syndication; +using System.Web; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; @@ -18,10 +19,10 @@ public class RssController(IOptions customizations, ApplicationDb [HttpGet("rss.xml", Name = "RssFeed")] [Produces("application/rss+xml")] [ResponseCache(Duration = 60*15, Location = ResponseCacheLocation.Any)] - public async Task GetRssFeedAsync(string? category = null) { + public async Task GetRssFeedAsync(string? category = null, Guid? author = null) { if (!Features.Value.Rss) return new JsonResult("RSS is disabled") {StatusCode = StatusCodes.Status401Unauthorized}; - var feed = await CreateFeedAll("RssFeed", category); + var feed = await CreateFeedAll("RssFeed", category, author); if (feed is null) return NotFound(); Response.ContentType = "application/atom+xml"; return Ok(feed); @@ -29,16 +30,16 @@ public class RssController(IOptions customizations, ApplicationDb [HttpGet("atom.xml", Name = "AtomFeed")] [Produces("application/atom+xml")] [ResponseCache(Duration = 60*15, Location = ResponseCacheLocation.Any)] - public async Task GetAtomFeedAsync(string? category = null) { + public async Task GetAtomFeedAsync(string? category = null, Guid? author = null) { if (!Features.Value.Rss) return new JsonResult("RSS is disabled") {StatusCode = StatusCodes.Status401Unauthorized}; - var feed = await CreateFeedAll("AtomFeed", category); + var feed = await CreateFeedAll("AtomFeed", category, author); if (feed is null) return NotFound(); Response.ContentType = "application/atom+xml"; return Ok(feed); } - private async Task CreateFeedAll(string? routeName, string? category) { + private async Task CreateFeedAll(string? routeName, string? category, Guid? author) { var now = DateTimeOffset.UtcNow; IQueryable
query = Context.Set
() .Include(a => a.Author) @@ -49,16 +50,21 @@ public class RssController(IOptions customizations, ApplicationDb if (!string.IsNullOrWhiteSpace(category)) { query = query.Where(a => a.Categories.Any(c => c.Name == category)); } + if (author is { } a1) { + string authorString = a1.ToString(); + query = query.Where(a => a.Author.Id == authorString); + } query = query.Take(15); var articles = await query.ToListAsync(); if (articles.Count < 1) return null; var date = query.Max(a => a.PublishDate); - return CreateFeedAsync(articles, date, routeName, category); + return CreateFeedAsync(articles, date, routeName, category, author); } - private SyndicationFeed CreateFeedAsync(IEnumerable
articles, DateTimeOffset date, string? routeName, string? category) { + private SyndicationFeed CreateFeedAsync(IEnumerable
articles, DateTimeOffset date, + string? routeName, string? category, Guid? author) { var customizations = Customizations.Value; string appName = customizations.AppName; @@ -68,17 +74,28 @@ public class RssController(IOptions customizations, ApplicationDb } 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; + var feedLink = new UriBuilder(Url.RouteUrl(routeName, null, "https", host.Host) ?? host.AbsoluteUri); + var htmlLink = new UriBuilder(host); if (category is not null) { - feedLink = new Uri(feedLink.AbsoluteUri + "?category=" + WebUtility.HtmlEncode(category)); - htmlLink = new Uri(host, "/category/" + WebUtility.HtmlEncode(category)); + feedLink.Query = "category=" + WebUtility.HtmlEncode(category); + htmlLink.Path = "/category/" + WebUtility.HtmlEncode(category); + } + if (author is not null) { + var query = HttpUtility.ParseQueryString(feedLink.Query); + query.Add("author", author.ToString()); + feedLink.Query = query.ToString(); + + if (htmlLink.Path.Length < 2) { + htmlLink.Path = "/profile/" + author; + } else { + htmlLink.Query = "?author=" + author; + } } - var feed = new SyndicationFeed(appName, "Feed on " + appName, htmlLink, host.AbsoluteUri, date) { + var feed = new SyndicationFeed(appName, "Feed on " + appName, htmlLink.Uri, host.AbsoluteUri, date) { TimeToLive = TimeSpan.FromMinutes(15), Generator = "Wave", - Links = { new SyndicationLink(feedLink) {RelationshipType = "self"} }, + Links = { new SyndicationLink(feedLink.Uri) {RelationshipType = "self"} }, Items = GetItems(articles, host) }; if (category != null) feed.Categories.Add(new SyndicationCategory(category));