using System.Text.RegularExpressions; using Microsoft.Extensions.Options; namespace FrontOffice.Main.Utilities.Seo; public class SeoMetadataProvider { private readonly BlogPostService _blogPostService; private readonly SeoSettings _settings; private static readonly Dictionary StaticPages = new(StringComparer.OrdinalIgnoreCase) { ["/"] = ( "کارابازار سلامت | باشگاه مشتریان KBS", "باشگاه مشتریان کارابازار سلامت — رشد تیم، فروش واقعی و پاداش شفاف. فروشگاه محصولات سلامت، کیف پول و ثبت‌نام رایگان."), [RouteConstants.About.Index] = ( "درباره ما | کارابازار سلامت", "آشنایی با کارابازار سلامت، باشگاه مشتریان KBS و خدمات فروشگاه محصولات سلامت."), [RouteConstants.FAQ.Index] = ( "سوالات متداول | کارابازار سلامت", "پاسخ سوالات متداول درباره باشگاه مشتریان، کیف پول، پاداش‌ها و خرید از کارابازار سلامت."), [RouteConstants.Contact.Index] = ( "ارتباط با ما | کارابازار سلامت", "تماس با تیم پشتیبانی کارابازار سلامت — سوالات، پیشنهادات و پشتیبانی کاربران."), [RouteConstants.Licenses.Index] = ( "مجوزها و گواهینامه‌ها | کارابازار سلامت", "مجوزها، گواهینامه‌ها و مدارک رسمی کارابازار سلامت."), [RouteConstants.Blog.Index] = ( "بلاگ | کارابازار سلامت", "آخرین مقالات و اخبار باشگاه مشتریان کارابازار سلامت."), [RouteConstants.Store.Products] = ( "محصولات | کارابازار سلامت", "فروشگاه محصولات سلامت کارابازار — خرید آنلاین با پاداش باشگاه مشتریان."), [RouteConstants.Store.Categories] = ( "دسته‌بندی‌ها | کارابازار سلامت", "دسته‌بندی محصولات فروشگاه کارابازار سلامت."), [RouteConstants.Package.List] = ( "پکیج‌ها | کارابازار سلامت", "پکیج‌های عضویت باشگاه مشتریان کارابازار سلامت."), [RouteConstants.Club.Membership] = ( "عضویت باشگاه مشتریان | کارابازار سلامت", "عضویت در باشگاه مشتریان KBS و بهره‌مندی از مزایا و پاداش‌ها."), [RouteConstants.Club.Features] = ( "ویژگی‌های باشگاه مشتریان | کارابازار سلامت", "امکانات و ویژگی‌های باشگاه مشتریان کارابازار سلامت."), [RouteConstants.DiscountStore.Products] = ( "فروشگاه اعتباری | کارابازار سلامت", "خرید از فروشگاه اعتباری کارابازار سلامت با کیف پول تخفیفی."), [RouteConstants.Registration.Wizard] = ( "ثبت‌نام | کارابازار سلامت", "ثبت‌نام سریع در باشگاه مشتریان کارابازار سلامت."), [RouteConstants.Gateway.StoreChooser] = ( "فروشگاه‌ها | کارابازار سلامت", "انتخاب فروشگاه اصلی یا اعتباری در کارابازار سلامت."), }; private static readonly HashSet NoIndexPaths = new(StringComparer.OrdinalIgnoreCase) { "/wishlist", "/wp-admin", "/wp-login.php", "/feed", "/xmlrpc.php", }; private static readonly HashSet NoIndexPrefixes = new(StringComparer.OrdinalIgnoreCase) { RouteConstants.Profile.Index, "/profile/", RouteConstants.Checkout.Index, RouteConstants.Store.Cart, RouteConstants.Store.CheckoutSummary, RouteConstants.Store.Orders, "/order/", RouteConstants.DiscountStore.Cart, RouteConstants.DiscountStore.Checkout, RouteConstants.DiscountStore.Orders, "/discount-store/order/", RouteConstants.Gateway.OrdersChooser, RouteConstants.Gateway.CartChooser, RouteConstants.Commission.Dashboard, "/commission/", RouteConstants.Network.Statistics, "/network/", RouteConstants.Package.MyPackages, "/wp-content/", "/wp-includes/", }; private static readonly Regex ProductDetailPattern = new(@"^/product/\d+$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); private static readonly Regex DiscountProductPattern = new(@"^/discount-store/product/\d+$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); private static readonly Regex PackageDetailPattern = new(@"^/package/\d+$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); private static readonly Regex CheckoutPackagePattern = new(@"^/checkout/\d+$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); public SeoMetadataProvider(BlogPostService blogPostService, IOptions settings) { _blogPostService = blogPostService; _settings = settings.Value; } public async Task GetForPathAsync(string path, CancellationToken cancellationToken = default) { var normalizedPath = NormalizePath(path); var baseUrl = _settings.SiteUrl.TrimEnd('/'); if (IsNoIndexPath(normalizedPath)) { return new SeoPageMetadata { Title = _settings.SiteName, Description = _settings.DefaultDescription, CanonicalUrl = $"{baseUrl}{normalizedPath}", NoIndex = true }; } if (normalizedPath.StartsWith(RouteConstants.Blog.Post, StringComparison.OrdinalIgnoreCase) && normalizedPath.Length > RouteConstants.Blog.Post.Length) { var slug = normalizedPath[RouteConstants.Blog.Post.Length..].Trim('/'); if (!string.IsNullOrWhiteSpace(slug)) { var post = await _blogPostService.GetBySlugAsync(slug); if (post != null) { var description = !string.IsNullOrWhiteSpace(post.Summary) ? post.Summary : $"مقاله {post.Title} — بلاگ کارابازار سلامت"; return new SeoPageMetadata { Title = $"{post.Title} | بلاگ کارابازار سلامت", Description = description, CanonicalUrl = $"{baseUrl}{RouteConstants.Blog.Post}{post.Slug}", CrawlableContent = $"{post.Title}. {description}" }; } } } if (StaticPages.TryGetValue(normalizedPath, out var page)) { return new SeoPageMetadata { Title = page.Title, Description = page.Description, CanonicalUrl = $"{baseUrl}{normalizedPath}", CrawlableContent = normalizedPath == "/" ? GetHomeCrawlableContent() : null }; } if (IsIndexableDynamicRoute(normalizedPath)) { return new SeoPageMetadata { Title = _settings.SiteName, Description = _settings.DefaultDescription, CanonicalUrl = $"{baseUrl}{normalizedPath}" }; } return new SeoPageMetadata { Title = _settings.SiteName, Description = _settings.DefaultDescription, CanonicalUrl = $"{baseUrl}{normalizedPath}", NoIndex = true }; } private static bool IsIndexableDynamicRoute(string path) => ProductDetailPattern.IsMatch(path) || DiscountProductPattern.IsMatch(path) || PackageDetailPattern.IsMatch(path) || CheckoutPackagePattern.IsMatch(path); private static string NormalizePath(string path) { if (string.IsNullOrWhiteSpace(path)) return "/"; var normalized = path.Split('?', '#')[0].Trim(); if (!normalized.StartsWith('/')) normalized = "/" + normalized; if (normalized.Length > 1 && normalized.EndsWith('/')) normalized = normalized.TrimEnd('/'); return normalized; } private static bool IsNoIndexPath(string path) { if (NoIndexPaths.Contains(path)) return true; foreach (var prefix in NoIndexPrefixes) { if (path.Equals(prefix, StringComparison.OrdinalIgnoreCase) || path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static string GetHomeCrawlableContent() => "کارابازار سلامت (KBS) — باشگاه مشتریان و فروشگاه محصولات سلامت. " + "با عضویت در باشگاه مشتریان KBS از پاداش شفاف، کیف پول جادویی، فروشگاه اعتباری و شبکه فروش بهره‌مند شوید. " + "ثبت‌نام رایگان در kbs2.ir."; }