91 lines
3.2 KiB
C#
91 lines
3.2 KiB
C#
using System.Text;
|
|
using System.Xml;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using PlotLine.Models;
|
|
using PlotLine.Services;
|
|
|
|
namespace PlotLine.Controllers;
|
|
|
|
[AllowAnonymous]
|
|
public sealed class SitemapController(IHelpService help, IConfiguration configuration) : Controller
|
|
{
|
|
[HttpGet("/sitemap.xml")]
|
|
public IActionResult Index()
|
|
{
|
|
var urls = new List<SitemapUrl>
|
|
{
|
|
new("/", "weekly", "1.0"),
|
|
new("/pricing", "weekly", "0.8"),
|
|
new("/help", "weekly", "0.7"),
|
|
new("/about", "monthly", "0.6"),
|
|
new("/contact", "monthly", "0.5"),
|
|
new("/privacy", "yearly", "0.3"),
|
|
new("/terms", "yearly", "0.3")
|
|
};
|
|
|
|
var articles = help.GetAllArticles();
|
|
urls.AddRange(articles
|
|
.Where(article => !string.IsNullOrWhiteSpace(article.CategorySlug))
|
|
.GroupBy(article => article.CategorySlug, StringComparer.OrdinalIgnoreCase)
|
|
.OrderBy(group => group.Key, StringComparer.OrdinalIgnoreCase)
|
|
.Select(group => new SitemapUrl(
|
|
$"/help/{group.Key}",
|
|
"monthly",
|
|
"0.6",
|
|
group.Max(article => article.LastModifiedUtc))));
|
|
|
|
urls.AddRange(articles
|
|
.Where(article => !string.IsNullOrWhiteSpace(article.CategorySlug) && !string.IsNullOrWhiteSpace(article.Slug))
|
|
.OrderBy(article => article.CategorySlug, StringComparer.OrdinalIgnoreCase)
|
|
.ThenBy(article => article.Slug, StringComparer.OrdinalIgnoreCase)
|
|
.Select(article => new SitemapUrl(
|
|
article.Url,
|
|
"monthly",
|
|
"0.5",
|
|
article.LastModifiedUtc)));
|
|
|
|
return Content(BuildXml(urls), "application/xml", Encoding.UTF8);
|
|
}
|
|
|
|
private string BuildXml(IEnumerable<SitemapUrl> urls)
|
|
{
|
|
var settings = new XmlWriterSettings
|
|
{
|
|
Encoding = new UTF8Encoding(false),
|
|
Indent = true,
|
|
OmitXmlDeclaration = false
|
|
};
|
|
using var writer = new Utf8StringWriter();
|
|
using var xml = XmlWriter.Create(writer, settings);
|
|
xml.WriteStartDocument();
|
|
xml.WriteStartElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9");
|
|
|
|
foreach (var url in urls)
|
|
{
|
|
xml.WriteStartElement("url");
|
|
xml.WriteElementString("loc", PublicSeo.AbsoluteUrl(configuration, url.Path));
|
|
if (url.LastModifiedUtc is DateTime lastModifiedUtc && lastModifiedUtc != default)
|
|
{
|
|
xml.WriteElementString("lastmod", lastModifiedUtc.ToString("yyyy-MM-dd"));
|
|
}
|
|
|
|
xml.WriteElementString("changefreq", url.ChangeFrequency);
|
|
xml.WriteElementString("priority", url.Priority);
|
|
xml.WriteEndElement();
|
|
}
|
|
|
|
xml.WriteEndElement();
|
|
xml.WriteEndDocument();
|
|
xml.Flush();
|
|
return writer.ToString();
|
|
}
|
|
|
|
private sealed record SitemapUrl(string Path, string ChangeFrequency, string Priority, DateTime? LastModifiedUtc = null);
|
|
|
|
private sealed class Utf8StringWriter : StringWriter
|
|
{
|
|
public override Encoding Encoding => Encoding.UTF8;
|
|
}
|
|
}
|