This commit is contained in:
2025-05-15 00:48:26 +08:00
parent e13dcbb553
commit b689c013d7
8 changed files with 244 additions and 2 deletions

View File

@@ -51,4 +51,5 @@ global using Yes.Infrastructure.Migrator.Migrations;
global using System.Security;
global using System.Security.Cryptography;
global using Yes.Infrastructure.Helpers;
global using Microsoft.AspNetCore.Authentication.JwtBearer;
global using Microsoft.AspNetCore.Authentication.JwtBearer;
global using System.Xml.Linq;

View File

@@ -0,0 +1,21 @@
namespace Yes.Infrastructure.Rss
{
public class Channel
{
public string Title { get; set; }
public string Link { get; set; }
public string Description { get; set; }
public string Language { get; set; } = "zh-CN";
// 时间信息
public DateTime LastBuildDate { get; set; } = DateTime.Now;
public DateTime PubDate { get; set; } = DateTime.Now;
// Atom 链接
public string FeedUrl { get; set; }
// 扩展能力
public List<XElement> Extensions { get; } = new List<XElement>();
}
}

View File

@@ -0,0 +1,15 @@
namespace Yes.Infrastructure.Rss
{
public class Item
{
public string Title { get; set; }
public string Url { get; set; }
public DateTime PublishDate { get; set; }
public string Creator { get; set; }
public string Description { get; set; } // 简短描述
public string Content { get; set; } // 完整HTML内容
public int CommentsCount { get; set; }
public string CommentsUrl { get; set; }
public string CommentRssUrl { get; set; }
}
}

View File

@@ -0,0 +1,80 @@

namespace Yes.Infrastructure.Rss
{
public class RssGenerator
{
private readonly XNamespace _contentNs = XNamespace.Get("http://purl.org/rss/1.0/modules/content/");
private readonly XNamespace _dcNs = XNamespace.Get("http://purl.org/dc/elements/1.1/");
private readonly XNamespace _slashNs = XNamespace.Get("http://purl.org/rss/1.0/modules/slash/");
private readonly XNamespace _wfwNs = XNamespace.Get("http://wellformedweb.org/CommentAPI/");
public string GenerateRss(Channel channel, IEnumerable<Item> items)
{
var doc = new XDocument(
new XDeclaration("1.0", "UTF-8", null),
new XElement("rss",
new XAttribute("version", "2.0"),
GetNamespaceAttributes(),
new XElement("channel",
RequiredChannelElements(channel),
GenerateItems(items)
)
)
);
return doc.ToStringWithDeclaration();
}
private IEnumerable<XAttribute> GetNamespaceAttributes()
{
yield return new XAttribute(XNamespace.Xmlns + "content", "http://purl.org/rss/1.0/modules/content/");
yield return new XAttribute(XNamespace.Xmlns + "dc", "http://purl.org/dc/elements/1.1/");
yield return new XAttribute(XNamespace.Xmlns + "atom", "http://www.w3.org/2005/Atom");
yield return new XAttribute(XNamespace.Xmlns + "wfw", "http://wellformedweb.org/CommentAPI/");
yield return new XAttribute(XNamespace.Xmlns + "slash", "http://purl.org/rss/1.0/modules/slash/");
}
private IEnumerable<XElement> RequiredChannelElements(Channel channel)
{
yield return new XElement("title", channel.Title);
yield return new XElement("link", channel.Link);
yield return new XElement("description", channel.Description);
yield return new XElement("language", channel.Language);
yield return new XElement("lastBuildDate", FormatRfc1123(channel.LastBuildDate));
yield return new XElement("pubDate", FormatRfc1123(channel.PubDate));
yield return new XElement(XNamespace.Get("http://www.w3.org/2005/Atom") + "link",
new XAttribute("href", channel.FeedUrl),
new XAttribute("rel", "self"),
new XAttribute("type", "application/rss+xml"));
}
private static string FormatRfc1123(DateTimeOffset date)
{
return date.ToString("r", System.Globalization.CultureInfo.InvariantCulture);
}
private IEnumerable<XElement> GenerateItems(IEnumerable<Item> items)
{
foreach (var item in items)
{
yield return new XElement("item",
new XElement("title", item.Title),
new XElement("link", item.Url),
new XElement("guid", new XAttribute("isPermaLink", "true"), item.Url),
new XElement("pubDate", item.PublishDate.ToString("ddd, dd MMM yyyy HH:mm:ss zzz")),
new XElement(_dcNs + "creator", item.Creator),
new XElement("description",
new XCData(item.Description)),
new XElement(_contentNs + "encoded",
new XAttribute(XNamespace.Xml + "lang", "zh-CN"),
new XCData(item.Content)),
new XElement(_slashNs + "comments", item.CommentsCount),
new XElement("comments", item.CommentsUrl),
new XElement(_wfwNs + "commentRss", item.CommentRssUrl)
);
}
}
}
}

View File

@@ -0,0 +1,15 @@
namespace Yes.Infrastructure.Rss
{
public static class XDocumentExtensions
{
public static string ToStringWithDeclaration(this XDocument doc)
{
if (doc.Declaration == null)
return doc.ToString();
using var writer = new StringWriter();
doc.Save(writer);
return writer.ToString();
}
}
}