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 _logger; public SitemapController( IUserPageService userPageService, ILivePageService livePageService, IMarkdownService markdownService, ICategoryRepository categoryRepository, ILogger logger) { _userPageService = userPageService; _livePageService = livePageService; _markdownService = markdownService; _categoryRepository = categoryRepository; _logger = logger; } [Route("sitemap.xml")] [ResponseCache(Duration = 86400)] // Cache for 24 hours public async Task 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(); 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); } }