All checks were successful
BCards Multi-Tenant Deployment Pipeline / Run Tests (push) Successful in 10s
BCards Multi-Tenant Deployment Pipeline / PR Validation (push) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Run Tests (pull_request) Successful in 5s
BCards Multi-Tenant Deployment Pipeline / PR Validation (pull_request) Successful in 1s
BCards Multi-Tenant Deployment Pipeline / Build and Push Image (push) Successful in 9m22s
BCards Multi-Tenant Deployment Pipeline / Build and Push Image (pull_request) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deploy bcards.site (pull_request) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deploy spicylinks.site (pull_request) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deploy luslinks.site (pull_request) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deploy to Release Swarm (ARM) (pull_request) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Cleanup Old Resources (pull_request) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deploy bcards.site (push) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deploy spicylinks.site (push) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deploy luslinks.site (push) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deployment Summary (pull_request) Successful in 0s
BCards Multi-Tenant Deployment Pipeline / Deploy to Release Swarm (ARM) (push) Successful in 2m11s
BCards Multi-Tenant Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Multi-Tenant Deployment Pipeline / Deployment Summary (push) Successful in 1s
142 lines
5.9 KiB
C#
142 lines
5.9 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using System.Text;
|
|
using System.Xml.Linq;
|
|
using BCards.Web.Services;
|
|
using BCards.Web.Areas.Tutoriais.Services;
|
|
using BCards.Web.Repositories;
|
|
|
|
namespace BCards.Web.Controllers;
|
|
|
|
public class SitemapController : Controller
|
|
{
|
|
private readonly IUserPageService _userPageService;
|
|
private readonly ILivePageService _livePageService;
|
|
private readonly IMarkdownService _markdownService;
|
|
private readonly ICategoryRepository _categoryRepository;
|
|
private readonly ILogger<SitemapController> _logger;
|
|
|
|
public SitemapController(
|
|
IUserPageService userPageService,
|
|
ILivePageService livePageService,
|
|
IMarkdownService markdownService,
|
|
ICategoryRepository categoryRepository,
|
|
ILogger<SitemapController> logger)
|
|
{
|
|
_userPageService = userPageService;
|
|
_livePageService = livePageService;
|
|
_markdownService = markdownService;
|
|
_categoryRepository = categoryRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
[Route("sitemap.xml")]
|
|
[ResponseCache(Duration = 86400)] // Cache for 24 hours
|
|
public async Task<IActionResult> Index()
|
|
{
|
|
try
|
|
{
|
|
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
|
|
|
|
var livePages = await _livePageService.GetAllActiveAsync();
|
|
|
|
// Artigos
|
|
var artigos = await _markdownService.GetAllArticlesAsync("Artigos", "pt-BR");
|
|
|
|
// Tutoriais por categoria
|
|
var categories = await _categoryRepository.GetAllActiveAsync();
|
|
var tutorialUrls = new List<XElement>();
|
|
foreach (var cat in categories)
|
|
{
|
|
var tutorials = await _markdownService.GetArticlesByCategoryAsync(cat.Slug, "pt-BR");
|
|
foreach (var t in tutorials)
|
|
{
|
|
tutorialUrls.Add(new XElement(ns + "url",
|
|
new XElement(ns + "loc", $"{Request.Scheme}://{Request.Host}/tutoriais/{cat.Slug}/{t.Slug}"),
|
|
new XElement(ns + "lastmod", t.LastMod.ToString("yyyy-MM-dd")),
|
|
new XElement(ns + "changefreq", "monthly"),
|
|
new XElement(ns + "priority", "0.7")
|
|
));
|
|
}
|
|
}
|
|
|
|
var dynamicUrls = livePages.Select(page =>
|
|
new XElement(ns + "url",
|
|
new XElement(ns + "loc", $"{Request.Scheme}://{Request.Host}/page/{page.Category?.Replace(" ", "-")?.ToLower()}/{page.Slug}"),
|
|
new XElement(ns + "lastmod", page.LastSyncAt.ToString("yyyy-MM-dd")),
|
|
new XElement(ns + "changefreq", "weekly"),
|
|
new XElement(ns + "priority", "0.8")
|
|
)
|
|
).ToList();
|
|
|
|
var artigoUrls = artigos.Select(a =>
|
|
new XElement(ns + "url",
|
|
new XElement(ns + "loc", $"{Request.Scheme}://{Request.Host}/artigos/{a.Slug}"),
|
|
new XElement(ns + "lastmod", a.LastMod.ToString("yyyy-MM-dd")),
|
|
new XElement(ns + "changefreq", "monthly"),
|
|
new XElement(ns + "priority", "0.7")
|
|
)
|
|
).ToList();
|
|
|
|
var sitemap = new XDocument(
|
|
new XDeclaration("1.0", "utf-8", "yes"),
|
|
new XElement(ns + "urlset",
|
|
new XElement(ns + "url",
|
|
new XElement(ns + "loc", $"{Request.Scheme}://{Request.Host}/"),
|
|
new XElement(ns + "lastmod", DateTime.UtcNow.ToString("yyyy-MM-dd")),
|
|
new XElement(ns + "changefreq", "daily"),
|
|
new XElement(ns + "priority", "1.0")
|
|
),
|
|
new XElement(ns + "url",
|
|
new XElement(ns + "loc", $"{Request.Scheme}://{Request.Host}/Home/Pricing"),
|
|
new XElement(ns + "lastmod", DateTime.UtcNow.ToString("yyyy-MM-dd")),
|
|
new XElement(ns + "changefreq", "weekly"),
|
|
new XElement(ns + "priority", "0.9")
|
|
),
|
|
new XElement(ns + "url",
|
|
new XElement(ns + "loc", $"{Request.Scheme}://{Request.Host}/artigos"),
|
|
new XElement(ns + "lastmod", DateTime.UtcNow.ToString("yyyy-MM-dd")),
|
|
new XElement(ns + "changefreq", "weekly"),
|
|
new XElement(ns + "priority", "0.8")
|
|
),
|
|
new XElement(ns + "url",
|
|
new XElement(ns + "loc", $"{Request.Scheme}://{Request.Host}/tutoriais"),
|
|
new XElement(ns + "lastmod", DateTime.UtcNow.ToString("yyyy-MM-dd")),
|
|
new XElement(ns + "changefreq", "weekly"),
|
|
new XElement(ns + "priority", "0.8")
|
|
),
|
|
artigoUrls,
|
|
tutorialUrls,
|
|
dynamicUrls
|
|
)
|
|
);
|
|
|
|
_logger.LogInformation("Generated sitemap with {LivePages} live pages, {Artigos} artigos, {Tutoriais} tutoriais",
|
|
livePages.Count, artigos.Count, tutorialUrls.Count);
|
|
|
|
return Content(sitemap.ToString(SaveOptions.DisableFormatting), "application/xml", Encoding.UTF8);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error generating sitemap");
|
|
return StatusCode(500, "Error generating sitemap");
|
|
}
|
|
}
|
|
|
|
[Route("robots.txt")]
|
|
[ResponseCache(Duration = 86400)] // Cache for 24 hours
|
|
public IActionResult RobotsTxt()
|
|
{
|
|
var robotsTxt = $@"User-agent: *
|
|
Allow: /
|
|
Allow: /page/
|
|
|
|
Disallow: /Admin/
|
|
Disallow: /Auth/
|
|
Disallow: /Payment/
|
|
Disallow: /api/
|
|
|
|
Sitemap: {Request.Scheme}://{Request.Host}/sitemap.xml";
|
|
|
|
return Content(robotsTxt, "text/plain", Encoding.UTF8);
|
|
}
|
|
} |