From 3cba0d598a6455743128dda02634a568e0e2d78c Mon Sep 17 00:00:00 2001 From: "Amir.H Khademi" Date: Fri, 12 Apr 2024 18:30:10 +0330 Subject: [PATCH] feat : complete create sitemap --- .../Production/appsettings.Production.json | 8 +- .../AppSettings/appsettings.Development.json | 8 +- NetinaShop.Api/Controller/HealthController.cs | 2 +- .../BaseServices/Abstracts/ISiteMapService.cs | 269 +------------ .../BaseServices/SiteMapService.cs | 364 ++++++++++++++++++ NetinaShop.Core/Models/SiteMapUIds.cs | 3 +- NetinaShop.Domain/Dtos/SmallDtos/BlogSDto.cs | 3 +- .../Dtos/SmallDtos/ProductSDto.cs | 1 + .../Mappers/BlogCategoryMapper.g.cs | 22 +- NetinaShop.Domain/Mappers/BlogMapper.g.cs | 17 +- NetinaShop.Domain/Mappers/BrandMapper.g.cs | 13 - NetinaShop.Domain/Mappers/ProductMapper.g.cs | 7 +- NetinaShop.Domain/MapsterRegister.cs | 4 +- .../Models/Settings/SiteSettings.cs | 8 + .../Services/StorageService.cs | 14 +- 15 files changed, 437 insertions(+), 306 deletions(-) create mode 100644 NetinaShop.Core/BaseServices/SiteMapService.cs diff --git a/NetinaShop.Api/AppSettings/Production/appsettings.Production.json b/NetinaShop.Api/AppSettings/Production/appsettings.Production.json index 2351434..6b90490 100644 --- a/NetinaShop.Api/AppSettings/Production/appsettings.Production.json +++ b/NetinaShop.Api/AppSettings/Production/appsettings.Production.json @@ -18,8 +18,9 @@ }, "SiteSettings": { "BaseUrl": "https://api.vesmeh.com", + "WebSiteUrl": "https://vesmeh.com", "AdminPanelBaseUrl": "https://admin.vesmeh.com", - "StorageBaseUrl": "https://storage.vesmeh.ir", + "StorageBaseUrl": "https://storage.vesmeh.com", "KaveNegarApiKey": "3735494B4143727A794346457461576A2B4B6668414973424E333561505A694B", "UserSetting": { "Username": "09214802813", @@ -30,6 +31,11 @@ "FirstName": "همه کاره", "LastName": "سیستم" }, + "StorageSetting": { + "AccessKey": "d37a1cc6acfea3a6f92c538ef0f6601f1edcdc9143942b6470e5d1032aa6bfe2", + "SecretKey": "979313b7-30fb-40ff-94d8-d0390d3fa876", + "BucketKey": "vesmeh-content" + }, "JwtSettings": { "SecretKey": "YAEMAMZAMAN_KHODET_NEGAHDAR_IN_KEY_BASH_nw+8E0EABj0Wg8c4mHg/bDBf5qGMhmBPb6u16DVe9/MzYva1e+/J1zImyIoQX2Lmra2kvzsIjGiwP7r3Znd_YA_JADE_NASABE_v+Ro/CDixScDv6EkpZnkBv9MFdPnSmFXNGMH9gA1BzQUoC1iSX9Aq+pMIw/cMKXI9WA==_YA_HUSEIN_SEYED_SHOHADA_BE_OMID_KHODET", "Issuer": "Brizco", diff --git a/NetinaShop.Api/AppSettings/appsettings.Development.json b/NetinaShop.Api/AppSettings/appsettings.Development.json index e6623bd..339b09e 100644 --- a/NetinaShop.Api/AppSettings/appsettings.Development.json +++ b/NetinaShop.Api/AppSettings/appsettings.Development.json @@ -18,8 +18,9 @@ }, "SiteSettings": { "BaseUrl": "http://localhost:32770", + "WebSiteUrl": "https://vesmeh.com", "AdminPanelBaseUrl": "https://admin.vesmeh.com", - "StorageBaseUrl": "https://storage.vesmeh.ir", + "StorageBaseUrl": "https://storage.vesmeh.com", "KaveNegarApiKey": "3735494B4143727A794346457461576A2B4B6668414973424E333561505A694B", "UserSetting": { "Username": "netinashop", @@ -30,6 +31,11 @@ "FirstName": "همه کاره", "LastName": "سیستم" }, + "StorageSetting": { + "AccessKey": "d37a1cc6acfea3a6f92c538ef0f6601f1edcdc9143942b6470e5d1032aa6bfe2", + "SecretKey": "979313b7-30fb-40ff-94d8-d0390d3fa876", + "BucketKey": "vesmeh-content" + }, "JwtSettings": { "SecretKey": "YAEMAMZAMAN_KHODET_NEGAHDAR_IN_KEY_BASH_nw+8E0EABj0Wg8c4mHg/bDBf5qGMhmBPb6u16DVe9/MzYva1e+/J1zImyIoQX2Lmra2kvzsIjGiwP7r3Znd_YA_JADE_NASABE_v+Ro/CDixScDv6EkpZnkBv9MFdPnSmFXNGMH9gA1BzQUoC1iSX9Aq+pMIw/cMKXI9WA==_YA_HUSEIN_SEYED_SHOHADA_BE_OMID_KHODET", "Issuer": "Brizco", diff --git a/NetinaShop.Api/Controller/HealthController.cs b/NetinaShop.Api/Controller/HealthController.cs index 3d93e35..a7298f6 100644 --- a/NetinaShop.Api/Controller/HealthController.cs +++ b/NetinaShop.Api/Controller/HealthController.cs @@ -15,7 +15,7 @@ public class HealthController : ICarterModule public async Task GetHealth([FromServices]ISiteMapService siteMapService) { - await siteMapService.CreateSiteMapAsync(); + //await siteMapService.CreateSiteMapAsync(); var version = typeof(Program)?.Assembly.GetName()?.Version?.ToString(); var check = new HealthCheck { diff --git a/NetinaShop.Core/BaseServices/Abstracts/ISiteMapService.cs b/NetinaShop.Core/BaseServices/Abstracts/ISiteMapService.cs index 896abba..5f1bdb3 100644 --- a/NetinaShop.Core/BaseServices/Abstracts/ISiteMapService.cs +++ b/NetinaShop.Core/BaseServices/Abstracts/ISiteMapService.cs @@ -1,273 +1,6 @@ -using System.IO; -using System.IO.Compression; -using System.IO.Pipes; -using System.Xml; -using NetinaShop.Core.Models; -using NetinaShop.Domain.Entities.Blogs; -using NetinaShop.Domain.Entities.ProductCategories; - -namespace NetinaShop.Core.BaseServices.Abstracts; +namespace NetinaShop.Core.BaseServices.Abstracts; public interface ISiteMapService : IScopedDependency { public Task CreateSiteMapAsync(); } - -public class SiteMapService : ISiteMapService -{ - private readonly IUploadFileService _uploadFileService; - private readonly IRepositoryWrapper _repositoryWrapper; - private readonly SiteSettings _siteSetting; - - public SiteMapService(IOptionsSnapshot snapshot, IUploadFileService uploadFileService,IRepositoryWrapper repositoryWrapper) - { - _uploadFileService = uploadFileService; - _repositoryWrapper = repositoryWrapper; - _siteSetting = snapshot.Value; - } - public async Task CreateSiteMapAsync() - { - XmlDocument doc = new XmlDocument(); - - // XML declaration - XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null); - doc.AppendChild(declaration); - - // Root element: Catalog - XmlElement root = doc.CreateElement("sitemapindex", "http://www.sitemaps.org/schemas/sitemap/0.9"); - doc.AppendChild(root); - - - foreach (var siteMapsUId in SiteMapUIds.AllSiteMapsUIds) - { - XmlElement siteMapElement = doc.CreateElement("sitemap", doc.DocumentElement?.NamespaceURI); - root.AppendChild(siteMapElement); - - XmlElement id = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); - id.InnerText = Path.Combine(_siteSetting.StorageBaseUrl, "site-maps", $"{siteMapsUId}.gz"); - siteMapElement.AppendChild(id); - - XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); - lastmod.InnerText = DateTime.Today.ToString("yyyy-MM-dd"); - siteMapElement.AppendChild(lastmod); - } - - System.IO.MemoryStream stream = new System.IO.MemoryStream(); - XmlTextWriter writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8); - - doc.WriteTo(writer); - writer.Flush(); - byte[] byteArray = stream.ToArray(); - await _uploadFileService.UploadFileByteAsync(new FileUploadRequest - { - FileBytes = byteArray, - ContentType = "text/xml", - FileName = "site-map.xml", - FileUploadType = FileUploadType.SiteMap, - }); - - await CreateCategoriesSiteMapsAsync(); - await CreateProductsSiteMapsAsync(); - await CreateBlogsSiteMapsAsync(); - - - } - - private async Task CreateCategoriesSiteMapsAsync() - { - var siteMapsUId = SiteMapUIds.Categories; - - var categories = await _repositoryWrapper.SetRepository() - .TableNoTracking - .ToListAsync(); - - XmlDocument doc = new XmlDocument(); - - XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null); - doc.AppendChild(declaration); - - XmlElement root = doc.CreateElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9"); - root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1"); - doc.AppendChild(root); - - foreach (var productCategory in categories) - { - XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); - root.AppendChild(urlElement); - - XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); - loc.InnerText = Path.Combine(productCategory.Name); - urlElement.AppendChild(loc); - - XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); - lastmod.InnerText = productCategory.ModifiedAt == DateTime.MinValue ? productCategory.CreatedAt.ToString("yyyy-MM-dd") : productCategory.ModifiedAt.ToString("yyyy-MM-dd"); - urlElement.AppendChild(lastmod); - - - XmlElement changeFeq = doc.CreateElement("changefreq", doc.DocumentElement?.NamespaceURI); - changeFeq.InnerText = "daily"; - urlElement.AppendChild(changeFeq); - - - XmlElement priority = doc.CreateElement("priority", doc.DocumentElement?.NamespaceURI); - priority.InnerText = "0.9"; - urlElement.AppendChild(priority); - - } - - using var siteMapStream = new MemoryStream(); - await using var siteMapWriter = new XmlTextWriter(siteMapStream, Encoding.UTF8); - doc.WriteTo(siteMapWriter); - siteMapWriter.Flush(); - byte[] unZipBytes = siteMapStream.ToArray(); - - using (var compressedStream = new MemoryStream()) - await using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) - { - zipStream.Write(unZipBytes, 0, unZipBytes.Length); - zipStream.Close(); - var siteMapArray = compressedStream.ToArray(); - - await _uploadFileService.UploadFileByteAsync(new FileUploadRequest - { - FileBytes = siteMapArray, - ContentType = "text/plain", - FileName = $"{siteMapsUId}.gz", - FileUploadType = FileUploadType.SiteMap, - }); - } - - } - - private async Task CreateProductsSiteMapsAsync() - { - var siteMapsUId = SiteMapUIds.Products; - - var products = await _repositoryWrapper.SetRepository() - .TableNoTracking - .ToListAsync(); - - XmlDocument doc = new XmlDocument(); - - XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null); - doc.AppendChild(declaration); - - XmlElement root = doc.CreateElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9"); - root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1"); - doc.AppendChild(root); - - foreach (var product in products) - { - XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); - root.AppendChild(urlElement); - - XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); - loc.InnerText = Path.Combine(product.PersianName); - urlElement.AppendChild(loc); - - XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); - lastmod.InnerText = product.ModifiedAt == DateTime.MinValue ? product.CreatedAt.ToString("yyyy-MM-dd") : product.ModifiedAt.ToString("yyyy-MM-dd"); - urlElement.AppendChild(lastmod); - - - XmlElement changeFeq = doc.CreateElement("changefreq", doc.DocumentElement?.NamespaceURI); - changeFeq.InnerText = "daily"; - urlElement.AppendChild(changeFeq); - - - XmlElement priority = doc.CreateElement("priority", doc.DocumentElement?.NamespaceURI); - priority.InnerText = "0.9"; - urlElement.AppendChild(priority); - - } - - using var siteMapStream = new MemoryStream(); - await using var siteMapWriter = new XmlTextWriter(siteMapStream, Encoding.UTF8); - doc.WriteTo(siteMapWriter); - siteMapWriter.Flush(); - byte[] unZipBytes = siteMapStream.ToArray(); - - using (var compressedStream = new MemoryStream()) - await using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) - { - zipStream.Write(unZipBytes, 0, unZipBytes.Length); - zipStream.Close(); - var siteMapArray = compressedStream.ToArray(); - - await _uploadFileService.UploadFileByteAsync(new FileUploadRequest - { - FileBytes = siteMapArray, - ContentType = "text/plain", - FileName = $"{siteMapsUId}.gz", - FileUploadType = FileUploadType.SiteMap, - }); - } - - } - - private async Task CreateBlogsSiteMapsAsync() - { - var siteMapsUId = SiteMapUIds.Blogs; - - var categories = await _repositoryWrapper.SetRepository() - .TableNoTracking - .ToListAsync(); - - XmlDocument doc = new XmlDocument(); - - XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null); - doc.AppendChild(declaration); - - XmlElement root = doc.CreateElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9"); - root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1"); - doc.AppendChild(root); - - foreach (var productCategory in categories) - { - XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); - root.AppendChild(urlElement); - - XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); - loc.InnerText = Path.Combine(productCategory.Title); - urlElement.AppendChild(loc); - - XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); - lastmod.InnerText = productCategory.ModifiedAt == DateTime.MinValue ? productCategory.CreatedAt.ToString("yyyy-MM-dd") : productCategory.ModifiedAt.ToString("yyyy-MM-dd"); - urlElement.AppendChild(lastmod); - - - XmlElement changeFeq = doc.CreateElement("changefreq", doc.DocumentElement?.NamespaceURI); - changeFeq.InnerText = "daily"; - urlElement.AppendChild(changeFeq); - - - XmlElement priority = doc.CreateElement("priority", doc.DocumentElement?.NamespaceURI); - priority.InnerText = "0.9"; - urlElement.AppendChild(priority); - - } - - using var siteMapStream = new MemoryStream(); - await using var siteMapWriter = new XmlTextWriter(siteMapStream, Encoding.UTF8); - doc.WriteTo(siteMapWriter); - siteMapWriter.Flush(); - byte[] unZipBytes = siteMapStream.ToArray(); - - using (var compressedStream = new MemoryStream()) - await using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) - { - zipStream.Write(unZipBytes, 0, unZipBytes.Length); - zipStream.Close(); - var siteMapArray = compressedStream.ToArray(); - - await _uploadFileService.UploadFileByteAsync(new FileUploadRequest - { - FileBytes = siteMapArray, - ContentType = "text/plain", - FileName = $"{siteMapsUId}.gz", - FileUploadType = FileUploadType.SiteMap, - }); - } - - } -} \ No newline at end of file diff --git a/NetinaShop.Core/BaseServices/SiteMapService.cs b/NetinaShop.Core/BaseServices/SiteMapService.cs new file mode 100644 index 0000000..fe43d9d --- /dev/null +++ b/NetinaShop.Core/BaseServices/SiteMapService.cs @@ -0,0 +1,364 @@ +using NetinaShop.Core.Models; +using NetinaShop.Domain.Entities.Blogs; +using NetinaShop.Domain.Entities.ProductCategories; +using System.IO.Compression; +using System.Web; +using System.Xml; + +namespace NetinaShop.Core.BaseServices; + + +public class SiteMapService : ISiteMapService +{ + private readonly IUploadFileService _uploadFileService; + private readonly IRepositoryWrapper _repositoryWrapper; + private readonly SiteSettings _siteSetting; + + public SiteMapService(IOptionsSnapshot snapshot, IUploadFileService uploadFileService, IRepositoryWrapper repositoryWrapper) + { + _uploadFileService = uploadFileService; + _repositoryWrapper = repositoryWrapper; + _siteSetting = snapshot.Value; + } + public async Task CreateSiteMapAsync() + { + XmlDocument doc = new XmlDocument(); + XmlDeclaration documentType = doc.CreateXmlDeclaration("1.0", "utf-8", null); + doc.AppendChild(documentType); + + // XML declaration + //XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null); + //doc.AppendChild(declaration); + + // Root element: Catalog + XmlElement root = doc.CreateElement("sitemapindex", "http://www.sitemaps.org/schemas/sitemap/0.9"); + doc.AppendChild(root); + + + var categories = await _repositoryWrapper.SetRepository() + .TableNoTracking + .ToListAsync(); + + foreach (var siteMapsUId in SiteMapUIds.AllSiteMapsUIds) + { + XmlElement siteMapElement = doc.CreateElement("sitemap", doc.DocumentElement?.NamespaceURI); + root.AppendChild(siteMapElement); + + XmlElement id = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); + id.InnerText = Path.Combine(_siteSetting.StorageBaseUrl, "site-maps", $"{siteMapsUId}.gz"); + siteMapElement.AppendChild(id); + + XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); + lastmod.InnerText = DateTime.Today.ToString("yyyy-MM-dd"); + siteMapElement.AppendChild(lastmod); + } + + foreach (var category in categories) + { + + XmlElement siteMapElement = doc.CreateElement("sitemap", doc.DocumentElement?.NamespaceURI); + root.AppendChild(siteMapElement); + + XmlElement id = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); + id.InnerText = Path.Combine(_siteSetting.StorageBaseUrl, "site-maps", $"{category.Id.ToString().ToUpper()}.gz"); + siteMapElement.AppendChild(id); + + XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); + lastmod.InnerText = DateTime.Today.ToString("yyyy-MM-dd"); + siteMapElement.AppendChild(lastmod); + } + + System.IO.MemoryStream stream = new System.IO.MemoryStream(); + XmlTextWriter writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8); + + doc.WriteTo(writer); + writer.Flush(); + byte[] byteArray = stream.ToArray(); + await _uploadFileService.UploadFileByteAsync(new FileUploadRequest + { + FileBytes = byteArray, + ContentType = "text/xml", + FileName = "site-map.xml", + FileUploadType = FileUploadType.SiteMap, + }); + + await CreateCategoriesSiteMapsAsync(); + await CreateProductsSiteMapsAsync(); + await CreateBlogsSiteMapsAsync(); + + + } + + private async Task CreateCategoriesSiteMapsAsync() + { + var siteMapsUId = SiteMapUIds.Categories; + + var categories = await _repositoryWrapper.SetRepository() + .TableNoTracking + .ToListAsync(); + + XmlDocument doc = new XmlDocument(); + XmlDeclaration documentType = doc.CreateXmlDeclaration("1.0", "utf-8", null); + doc.AppendChild(documentType); + + //XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null); + //doc.AppendChild(declaration); + + XmlElement root = doc.CreateElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9"); + root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1"); + doc.AppendChild(root); + + foreach (var productCategory in categories) + { + var productUrl = $"{_siteSetting.WebSiteUrl}/categories/{productCategory.Id}/{HttpUtility.UrlEncode(productCategory.Name.Replace(' ', '-'))}"; + XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); + root.AppendChild(urlElement); + + XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); + loc.InnerText = Path.Combine(productCategory.Name); + urlElement.AppendChild(loc); + + XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); + lastmod.InnerText = productCategory.ModifiedAt == DateTime.MinValue ? productCategory.CreatedAt.ToString("yyyy-MM-dd") : productCategory.ModifiedAt.ToString("yyyy-MM-dd"); + urlElement.AppendChild(lastmod); + + + XmlElement changeFeq = doc.CreateElement("changefreq", doc.DocumentElement?.NamespaceURI); + changeFeq.InnerText = "daily"; + urlElement.AppendChild(changeFeq); + + + XmlElement priority = doc.CreateElement("priority", doc.DocumentElement?.NamespaceURI); + priority.InnerText = "0.9"; + urlElement.AppendChild(priority); + + } + + using var siteMapStream = new MemoryStream(); + await using var siteMapWriter = new XmlTextWriter(siteMapStream, Encoding.UTF8); + doc.WriteTo(siteMapWriter); + siteMapWriter.Flush(); + byte[] unZipBytes = siteMapStream.ToArray(); + + using (var compressedStream = new MemoryStream()) + await using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) + { + zipStream.Write(unZipBytes, 0, unZipBytes.Length); + zipStream.Close(); + var siteMapArray = compressedStream.ToArray(); + + await _uploadFileService.UploadFileByteAsync(new FileUploadRequest + { + FileBytes = siteMapArray, + ContentType = "text/plain", + FileName = $"{siteMapsUId}.gz", + FileUploadType = FileUploadType.SiteMap, + }); + } + + } + + private async Task CreateProductsSiteMapsAsync() + { + + var products = await _repositoryWrapper.SetRepository() + .TableNoTracking + .Select(ProductMapper.ProjectToSDto) + .ToListAsync(); + + var groupedProducts = products.GroupBy(p => p.CategoryId); + + foreach (var group in groupedProducts) + { + XmlDocument doc = new XmlDocument(); + XmlDeclaration documentType = doc.CreateXmlDeclaration("1.0", "utf-8", null); + doc.AppendChild(documentType); + + //XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null); + //doc.AppendChild(declaration); + + XmlElement root = doc.CreateElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9"); + root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1"); + doc.AppendChild(root); + + foreach (var product in group) + { + + var productUrl = $"{_siteSetting.WebSiteUrl}/products/{product.Id}/{HttpUtility.UrlEncode(product.PersianName.Replace(' ', '-'))}"; + XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); + root.AppendChild(urlElement); + + XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); + loc.InnerText = Path.Combine(productUrl); + urlElement.AppendChild(loc); + + XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); + lastmod.InnerText = product.ModifiedAt == DateTime.MinValue ? product.CreatedAt.ToString("yyyy-MM-dd") : product.ModifiedAt.ToString("yyyy-MM-dd"); + urlElement.AppendChild(lastmod); + + + XmlElement changeFeq = doc.CreateElement("changefreq", doc.DocumentElement?.NamespaceURI); + changeFeq.InnerText = "daily"; + urlElement.AppendChild(changeFeq); + + + XmlElement priority = doc.CreateElement("priority", doc.DocumentElement?.NamespaceURI); + priority.InnerText = "0.9"; + urlElement.AppendChild(priority); + + if (product.MainImage != string.Empty) + { + XmlElement image = doc.CreateElement("image:image", "http://www.google.com/schemas/sitemap-image/1.1"); + urlElement.AppendChild(image); + + + XmlElement imageLoc = doc.CreateElement("image:loc", "http://www.google.com/schemas/sitemap-image/1.1"); + imageLoc.InnerText = $"{_siteSetting.StorageBaseUrl}/{product.MainImage.Replace("Med", "Thumb")}"; + image.AppendChild(imageLoc); + + + XmlElement imageCaption = doc.CreateElement("image:caption", "http://www.google.com/schemas/sitemap-image/1.1"); + imageCaption.InnerText = product.PersianName; + image.AppendChild(imageCaption); + } + + } + + using var siteMapStream = new MemoryStream(); + await using var siteMapWriter = new XmlTextWriter(siteMapStream, Encoding.UTF8); + doc.WriteTo(siteMapWriter); + siteMapWriter.Flush(); + byte[] unZipBytes = siteMapStream.ToArray(); + + using (var compressedStream = new MemoryStream()) + await using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) + { + zipStream.Write(unZipBytes, 0, unZipBytes.Length); + zipStream.Close(); + var siteMapArray = compressedStream.ToArray(); + + await _uploadFileService.UploadFileByteAsync(new FileUploadRequest + { + FileBytes = siteMapArray, + ContentType = "text/plain", + FileName = $"{group.Key.ToString().ToUpper()}.gz", + FileUploadType = FileUploadType.SiteMap, + }); + } + } + + + + } + + private async Task CreateBlogsSiteMapsAsync() + { + var siteMapsUId = SiteMapUIds.Blogs; + + var blogs = await _repositoryWrapper.SetRepository() + .TableNoTracking + .Select(BlogMapper.ProjectToSDto) + .ToListAsync(); + + XmlDocument doc = new XmlDocument(); + XmlDeclaration documentType = doc.CreateXmlDeclaration("1.0", "utf-8", null); + doc.AppendChild(documentType); + + //XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null); + //doc.AppendChild(declaration); + + XmlElement root = doc.CreateElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9"); + root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1"); + root.SetAttribute("xmlns:news", "http://www.google.com/schemas/sitemap-news/0.9"); + doc.AppendChild(root); + + foreach (var blog in blogs) + { + XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); + root.AppendChild(urlElement); + + XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); + loc.InnerText = Path.Combine(blog.Title); + urlElement.AppendChild(loc); + + XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); + lastmod.InnerText = blog.ModifiedAt == DateTime.MinValue ? blog.CreatedAt.ToString("yyyy-MM-dd") : blog.ModifiedAt.ToString("yyyy-MM-dd"); + urlElement.AppendChild(lastmod); + + + XmlElement changeFeq = doc.CreateElement("changefreq", doc.DocumentElement?.NamespaceURI); + changeFeq.InnerText = "daily"; + urlElement.AppendChild(changeFeq); + + + XmlElement priority = doc.CreateElement("priority", doc.DocumentElement?.NamespaceURI); + priority.InnerText = "0.9"; + urlElement.AppendChild(priority); + + //Image + + XmlElement image = doc.CreateElement("image:image", "http://www.google.com/schemas/sitemap-image/1.1"); + urlElement.AppendChild(image); + + + XmlElement imageLoc = doc.CreateElement("image:loc", "http://www.google.com/schemas/sitemap-image/1.1"); + imageLoc.InnerText = $"{_siteSetting.StorageBaseUrl}/{blog.MainImage.Replace("Med", "Thumb")}"; + image.AppendChild(imageLoc); + + + XmlElement imageCaption = doc.CreateElement("image:caption", "http://www.google.com/schemas/sitemap-image/1.1"); + imageCaption.InnerText = blog.Title; + image.AppendChild(imageCaption); + + ////News + + //XmlElement news = doc.CreateElement("news:news", "http://www.google.com/schemas/sitemap-news/0.9"); + //urlElement.AppendChild(news); + + //XmlElement newTitle = doc.CreateElement("news:title", "http://www.google.com/schemas/sitemap-news/0.9"); + //newTitle.InnerText = blog.Title; + //news.AppendChild(newTitle); + + //XmlElement newPublificationDate = doc.CreateElement("news:publication_date", "http://www.google.com/schemas/sitemap-news/0.9"); + //newPublificationDate.InnerText = blog.CreatedAt.ToString("yyyy-MM-dd"); + //news.AppendChild(newPublificationDate); + + + + //XmlElement newsPublification = doc.CreateElement("news:publication", "http://www.google.com/schemas/sitemap-news/0.9"); + //news.AppendChild(newsPublification); + + //XmlElement newsPublicationName = doc.CreateElement("news:name", "http://www.google.com/schemas/sitemap-news/0.9"); + //newsPublicationName.InnerText = blog.Title; + //newsPublification.AppendChild(newsPublicationName); + + //XmlElement newsPublicationLanq = doc.CreateElement("news:language", "http://www.google.com/schemas/sitemap-news/0.9"); + //newsPublicationLanq.InnerText = blog.CreatedAt.ToString("yyyy-MM-dd"); + //newsPublification.AppendChild(newsPublicationLanq); + + } + + using var siteMapStream = new MemoryStream(); + await using var siteMapWriter = new XmlTextWriter(siteMapStream, Encoding.UTF8); + doc.WriteTo(siteMapWriter); + siteMapWriter.Flush(); + byte[] unZipBytes = siteMapStream.ToArray(); + + using (var compressedStream = new MemoryStream()) + await using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) + { + zipStream.Write(unZipBytes, 0, unZipBytes.Length); + zipStream.Close(); + var siteMapArray = compressedStream.ToArray(); + + await _uploadFileService.UploadFileByteAsync(new FileUploadRequest + { + FileBytes = siteMapArray, + ContentType = "text/plain", + FileName = $"{siteMapsUId}.gz", + FileUploadType = FileUploadType.SiteMap, + }); + } + + } +} \ No newline at end of file diff --git a/NetinaShop.Core/Models/SiteMapUIds.cs b/NetinaShop.Core/Models/SiteMapUIds.cs index 12d64f5..d74f74c 100644 --- a/NetinaShop.Core/Models/SiteMapUIds.cs +++ b/NetinaShop.Core/Models/SiteMapUIds.cs @@ -3,11 +3,10 @@ public static class SiteMapUIds { public const string Categories = "5709ACC29A4D42E5B6F2DFFAD2FB0018"; public const string Blogs = "4C2F0C2A7A3E41268702D12FDDDB837F"; - public const string Products = "E95AB3C0C4DD44FA82D77D55BD91696F"; public static List AllSiteMapsUIds => new List { Categories, - Blogs, Products + Blogs }; } diff --git a/NetinaShop.Domain/Dtos/SmallDtos/BlogSDto.cs b/NetinaShop.Domain/Dtos/SmallDtos/BlogSDto.cs index 96c2c01..29340a6 100644 --- a/NetinaShop.Domain/Dtos/SmallDtos/BlogSDto.cs +++ b/NetinaShop.Domain/Dtos/SmallDtos/BlogSDto.cs @@ -10,5 +10,6 @@ public class BlogSDto : BaseDto public bool IsSuggested { get; set; } public Guid CategoryId { get; set; } public string CategoryName { get; set; } = string.Empty; - public string HeaderFileName { get; set; } = string.Empty; + public string MainImage { get; set; } = string.Empty; + public DateTime ModifiedAt { get; set; } } \ No newline at end of file diff --git a/NetinaShop.Domain/Dtos/SmallDtos/ProductSDto.cs b/NetinaShop.Domain/Dtos/SmallDtos/ProductSDto.cs index 625b676..1322a64 100644 --- a/NetinaShop.Domain/Dtos/SmallDtos/ProductSDto.cs +++ b/NetinaShop.Domain/Dtos/SmallDtos/ProductSDto.cs @@ -28,4 +28,5 @@ public class ProductSDto : BaseDto public Guid BrandId { get; set; } public string BrandName { get; set; } = string.Empty; public string CategoryName { get; set; } = string.Empty; + public DateTime ModifiedAt { get; set; } } \ No newline at end of file diff --git a/NetinaShop.Domain/Mappers/BlogCategoryMapper.g.cs b/NetinaShop.Domain/Mappers/BlogCategoryMapper.g.cs index 0795821..622a658 100644 --- a/NetinaShop.Domain/Mappers/BlogCategoryMapper.g.cs +++ b/NetinaShop.Domain/Mappers/BlogCategoryMapper.g.cs @@ -56,7 +56,8 @@ namespace NetinaShop.Domain.Mappers Id = p8.CategoryId }, Id = p8.Id, - CreatedAt = p8.CreatedAt + CreatedAt = p8.CreatedAt, + ModifiedAt = p8.ModifiedAt }).ToList(), Id = p7.Id, CreatedAt = p7.CreatedAt @@ -102,7 +103,8 @@ namespace NetinaShop.Domain.Mappers IsSuggested = p16.IsSuggested, CategoryId = p16.CategoryId, CategoryName = p16.Category.Name, - HeaderFileName = p16.Files.Count > 0 && p16.Files.Any(f => f.IsHeader) ? p16.Files.FirstOrDefault(f => f.IsHeader).FileName : string.Empty, + MainImage = p16.Files.Count > 0 && p16.Files.Any(f => f.IsPrimary) ? p16.Files.FirstOrDefault(f => f.IsPrimary).FileName : string.Empty, + ModifiedAt = p16.ModifiedAt, Id = p16.Id, CreatedAt = p16.CreatedAt }).ToList(), @@ -196,7 +198,8 @@ namespace NetinaShop.Domain.Mappers Id = item.CategoryId }, Id = item.Id, - CreatedAt = item.CreatedAt + CreatedAt = item.CreatedAt, + ModifiedAt = item.ModifiedAt }); i++; } @@ -233,7 +236,8 @@ namespace NetinaShop.Domain.Mappers Id = item.CategoryId }, Id = item.Id, - CreatedAt = item.CreatedAt + CreatedAt = item.CreatedAt, + ModifiedAt = item.ModifiedAt }); i++; } @@ -265,7 +269,8 @@ namespace NetinaShop.Domain.Mappers IsSuggested = item.IsSuggested, CategoryId = item.CategoryId, CategoryName = item.Category == null ? null : item.Category.Name, - HeaderFileName = item.Files.Count > 0 && item.Files.Any(funcMain4) ? item.Files.FirstOrDefault(funcMain5).FileName : string.Empty, + MainImage = item.Files.Count > 0 && item.Files.Any(funcMain4) ? item.Files.FirstOrDefault(funcMain5).FileName : string.Empty, + ModifiedAt = item.ModifiedAt, Id = item.Id, CreatedAt = item.CreatedAt }); @@ -299,7 +304,8 @@ namespace NetinaShop.Domain.Mappers IsSuggested = item.IsSuggested, CategoryId = item.CategoryId, CategoryName = item.Category == null ? null : item.Category.Name, - HeaderFileName = item.Files.Count > 0 && item.Files.Any(funcMain4) ? item.Files.FirstOrDefault(funcMain5).FileName : string.Empty, + MainImage = item.Files.Count > 0 && item.Files.Any(funcMain4) ? item.Files.FirstOrDefault(funcMain5).FileName : string.Empty, + ModifiedAt = item.ModifiedAt, Id = item.Id, CreatedAt = item.CreatedAt }); @@ -311,12 +317,12 @@ namespace NetinaShop.Domain.Mappers private static bool funcMain4(BlogStorageFile f) { - return f.IsHeader; + return f.IsPrimary; } private static bool funcMain5(BlogStorageFile f) { - return f.IsHeader; + return f.IsPrimary; } } } \ No newline at end of file diff --git a/NetinaShop.Domain/Mappers/BlogMapper.g.cs b/NetinaShop.Domain/Mappers/BlogMapper.g.cs index c4674db..357793a 100644 --- a/NetinaShop.Domain/Mappers/BlogMapper.g.cs +++ b/NetinaShop.Domain/Mappers/BlogMapper.g.cs @@ -150,7 +150,8 @@ namespace NetinaShop.Domain.Mappers Id = p17.CategoryId }, Id = p17.Id, - CreatedAt = p17.CreatedAt + CreatedAt = p17.CreatedAt, + ModifiedAt = p17.ModifiedAt }; } public static Blog AdaptTo(this BlogSDto p18, Blog p19) @@ -171,6 +172,7 @@ namespace NetinaShop.Domain.Mappers result.Category = funcMain5(new Never(), result.Category, p18); result.Id = p18.Id; result.CreatedAt = p18.CreatedAt; + result.ModifiedAt = p18.ModifiedAt; return result; } @@ -186,7 +188,8 @@ namespace NetinaShop.Domain.Mappers IsSuggested = p22.IsSuggested, CategoryId = p22.CategoryId, CategoryName = p22.Category == null ? null : p22.Category.Name, - HeaderFileName = p22.Files.Count > 0 && p22.Files.Any(funcMain6) ? p22.Files.FirstOrDefault(funcMain7).FileName : string.Empty, + MainImage = p22.Files.Count > 0 && p22.Files.Any(funcMain6) ? p22.Files.FirstOrDefault(funcMain7).FileName : string.Empty, + ModifiedAt = p22.ModifiedAt, Id = p22.Id, CreatedAt = p22.CreatedAt }; @@ -207,7 +210,8 @@ namespace NetinaShop.Domain.Mappers result.IsSuggested = p23.IsSuggested; result.CategoryId = p23.CategoryId; result.CategoryName = p23.Category == null ? null : p23.Category.Name; - result.HeaderFileName = p23.Files.Count > 0 && p23.Files.Any(funcMain6) ? p23.Files.FirstOrDefault(funcMain7).FileName : string.Empty; + result.MainImage = p23.Files.Count > 0 && p23.Files.Any(funcMain6) ? p23.Files.FirstOrDefault(funcMain7).FileName : string.Empty; + result.ModifiedAt = p23.ModifiedAt; result.Id = p23.Id; result.CreatedAt = p23.CreatedAt; return result; @@ -223,7 +227,8 @@ namespace NetinaShop.Domain.Mappers IsSuggested = p25.IsSuggested, CategoryId = p25.CategoryId, CategoryName = p25.Category.Name, - HeaderFileName = p25.Files.Count > 0 && p25.Files.Any(f => f.IsHeader) ? p25.Files.FirstOrDefault(f => f.IsHeader).FileName : string.Empty, + MainImage = p25.Files.Count > 0 && p25.Files.Any(f => f.IsPrimary) ? p25.Files.FirstOrDefault(f => f.IsPrimary).FileName : string.Empty, + ModifiedAt = p25.ModifiedAt, Id = p25.Id, CreatedAt = p25.CreatedAt }; @@ -362,12 +367,12 @@ namespace NetinaShop.Domain.Mappers private static bool funcMain6(BlogStorageFile f) { - return f.IsHeader; + return f.IsPrimary; } private static bool funcMain7(BlogStorageFile f) { - return f.IsHeader; + return f.IsPrimary; } } } \ No newline at end of file diff --git a/NetinaShop.Domain/Mappers/BrandMapper.g.cs b/NetinaShop.Domain/Mappers/BrandMapper.g.cs index f6f618e..3ee7710 100644 --- a/NetinaShop.Domain/Mappers/BrandMapper.g.cs +++ b/NetinaShop.Domain/Mappers/BrandMapper.g.cs @@ -157,7 +157,6 @@ namespace NetinaShop.Domain.Mappers Description = p20.Description, HasSpecialPage = p20.HasSpecialPage, PageUrl = p20.PageUrl, - HeaderFileName = p20.Files.Count > 0 && p20.Files.Any(funcMain5) ? p20.Files.FirstOrDefault(funcMain6).FileName : string.Empty, Id = p20.Id, CreatedAt = p20.CreatedAt }; @@ -175,7 +174,6 @@ namespace NetinaShop.Domain.Mappers result.Description = p21.Description; result.HasSpecialPage = p21.HasSpecialPage; result.PageUrl = p21.PageUrl; - result.HeaderFileName = p21.Files.Count > 0 && p21.Files.Any(funcMain5) ? p21.Files.FirstOrDefault(funcMain6).FileName : string.Empty; result.Id = p21.Id; result.CreatedAt = p21.CreatedAt; return result; @@ -188,7 +186,6 @@ namespace NetinaShop.Domain.Mappers Description = p23.Description, HasSpecialPage = p23.HasSpecialPage, PageUrl = p23.PageUrl, - HeaderFileName = p23.Files.Count > 0 && p23.Files.Any(f => f.IsHeader) ? p23.Files.FirstOrDefault(f => f.IsHeader).FileName : string.Empty, Id = p23.Id, CreatedAt = p23.CreatedAt }; @@ -314,15 +311,5 @@ namespace NetinaShop.Domain.Mappers return result; } - - private static bool funcMain5(BrandStorageFile f) - { - return f.IsHeader; - } - - private static bool funcMain6(BrandStorageFile f) - { - return f.IsHeader; - } } } \ No newline at end of file diff --git a/NetinaShop.Domain/Mappers/ProductMapper.g.cs b/NetinaShop.Domain/Mappers/ProductMapper.g.cs index 9bd3daf..2b19dac 100644 --- a/NetinaShop.Domain/Mappers/ProductMapper.g.cs +++ b/NetinaShop.Domain/Mappers/ProductMapper.g.cs @@ -274,7 +274,8 @@ namespace NetinaShop.Domain.Mappers Id = p37.CategoryId }, Id = p37.Id, - CreatedAt = p37.CreatedAt + CreatedAt = p37.CreatedAt, + ModifiedAt = p37.ModifiedAt }; } public static Product AdaptTo(this ProductSDto p38, Product p39) @@ -306,6 +307,7 @@ namespace NetinaShop.Domain.Mappers result.Category = funcMain16(new Never(), result.Category, p38); result.Id = p38.Id; result.CreatedAt = p38.CreatedAt; + result.ModifiedAt = p38.ModifiedAt; return result; } @@ -333,6 +335,7 @@ namespace NetinaShop.Domain.Mappers BrandId = p44.BrandId, BrandName = p44.Brand == null ? null : p44.Brand.PersianName, CategoryName = p44.Category == null ? null : p44.Category.Name, + ModifiedAt = p44.ModifiedAt, Id = p44.Id, CreatedAt = p44.CreatedAt }; @@ -365,6 +368,7 @@ namespace NetinaShop.Domain.Mappers result.BrandId = p45.BrandId; result.BrandName = p45.Brand == null ? null : p45.Brand.PersianName; result.CategoryName = p45.Category == null ? null : p45.Category.Name; + result.ModifiedAt = p45.ModifiedAt; result.Id = p45.Id; result.CreatedAt = p45.CreatedAt; return result; @@ -392,6 +396,7 @@ namespace NetinaShop.Domain.Mappers BrandId = p47.BrandId, BrandName = p47.Brand == null ? null : p47.Brand.PersianName, CategoryName = p47.Category == null ? null : p47.Category.Name, + ModifiedAt = p47.ModifiedAt, Id = p47.Id, CreatedAt = p47.CreatedAt }; diff --git a/NetinaShop.Domain/MapsterRegister.cs b/NetinaShop.Domain/MapsterRegister.cs index 6305892..4bfbc51 100644 --- a/NetinaShop.Domain/MapsterRegister.cs +++ b/NetinaShop.Domain/MapsterRegister.cs @@ -7,11 +7,11 @@ public class MapsterRegister : IRegister public void Register(TypeAdapterConfig config) { config.NewConfig() - .Map("HeaderFileName", o => o.Files.Count > 0 && o.Files.Any(f=>f.IsHeader) ? o.Files.FirstOrDefault(f=>f.IsHeader)!.FileName : string.Empty) + .Map("MainImage", o => o.Files.Count > 0 && o.Files.Any(f=>f.IsPrimary) ? o.Files.FirstOrDefault(f=>f.IsPrimary)!.FileName : string.Empty) .TwoWays(); config.NewConfig() - .Map("HeaderFileName", o => o.Files.Count > 0 && o.Files.Any(f => f.IsHeader) ? o.Files.FirstOrDefault(f => f.IsHeader)!.FileName : string.Empty) + .Map("MainImage", o => o.Files.Count > 0 && o.Files.Any(f => f.IsHeader) ? o.Files.FirstOrDefault(f => f.IsHeader)!.FileName : string.Empty) .TwoWays(); config.NewConfig() diff --git a/NetinaShop.Domain/Models/Settings/SiteSettings.cs b/NetinaShop.Domain/Models/Settings/SiteSettings.cs index ab54b77..7ba8172 100644 --- a/NetinaShop.Domain/Models/Settings/SiteSettings.cs +++ b/NetinaShop.Domain/Models/Settings/SiteSettings.cs @@ -4,11 +4,13 @@ public class SiteSettings { public JwtSettings JwtSettings { get; set; } = new JwtSettings(); public string BaseUrl { get; set; } = string.Empty; + public string WebSiteUrl { get; set; } = string.Empty; public string AdminPanelBaseUrl { get; set; } = string.Empty; public string StorageBaseUrl { get; set; } = string.Empty; public RedisSettings MasterRedisConfiguration { get; set; } = new RedisSettings(); public UserSetting UserSetting { get; set; } = new UserSetting(); public string KaveNegarApiKey { get; set; } = string.Empty; + public StorageSettings StorageSetting { get; set; } = new StorageSettings(); } public class RedisSettings { @@ -18,6 +20,12 @@ public class RedisSettings public int Port { get; set; } } +public class StorageSettings +{ + public string AccessKey { get; set; } = string.Empty; + public string SecretKey { get; set; } = string.Empty; + public string BucketKey { get; set; } = string.Empty; +} public class JwtSettings { diff --git a/NetinaShop.Infrastructure/Services/StorageService.cs b/NetinaShop.Infrastructure/Services/StorageService.cs index 4f56947..2cbe141 100644 --- a/NetinaShop.Infrastructure/Services/StorageService.cs +++ b/NetinaShop.Infrastructure/Services/StorageService.cs @@ -6,10 +6,20 @@ namespace NetinaShop.Infrastructure.Services; public class StorageService : IStorageService { private IAmazonS3? _s3Client; - private string _bucketName = "vesmeh-content"; + private readonly string _bucketName; + private readonly string _accessKey; + private readonly string _secretKey; + + public StorageService(IOptionsSnapshot snapshot) + { + _accessKey = snapshot.Value.StorageSetting.AccessKey; + _bucketName = snapshot.Value.StorageSetting.BucketKey; + _secretKey = snapshot.Value.StorageSetting.SecretKey; + } + private IAmazonS3 GetClientAsync() { - var awsCredentials = new Amazon.Runtime.BasicAWSCredentials("979313b7-30fb-40ff-94d8-d0390d3fa876", "d37a1cc6acfea3a6f92c538ef0f6601f1edcdc9143942b6470e5d1032aa6bfe2"); + var awsCredentials = new Amazon.Runtime.BasicAWSCredentials(secretKey: _secretKey, accessKey: _accessKey); var config = new AmazonS3Config { ServiceURL = "https://s3.ir-thr-at1.arvanstorage.ir" }; _s3Client = new AmazonS3Client(awsCredentials, config); return _s3Client;