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; 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, }); } } }