)>}]
شركة التطبيقات المتكاملة لتصميم وبرمجة البرمجيات الخاصة ش.ش.و.
Integrated Applications Programming Company
Home » Code Library » Default (Ia.Statistics.Cl.Model.Boutiqaat)

Public general use code classes and xml files that we've compiled and used over the years:

Structure of the boutiqaat.com website.

    1: using System;
    2: using System.Collections.Generic;
    3: using System.IO;
    4: using System.Linq;
    5: using System.Reflection;
    6: using System.Xml.Linq;
    7: using System.Text.RegularExpressions;
    8: using OpenQA.Selenium;
    9: using OpenQA.Selenium.Chrome;
   10:  
   11: namespace Ia.Statistics.Cl.Model.Boutiqaat
   12: {
   13:     ////////////////////////////////////////////////////////////////////////////
   14:  
   15:     /// <summary publish="true">
   16:     /// Structure of the boutiqaat.com website.
   17:     /// </summary>
   18:     /// <remarks> 
   19:     /// Copyright © 2024-2025 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
   20:     ///
   21:     /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
   22:     /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
   23:     ///
   24:     /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   25:     /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   26:     /// 
   27:     /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
   28:     /// 
   29:     /// Copyright notice: This notice may not be removed or altered from any source distribution.
   30:     /// </remarks> 
   31:     public class Default
   32:     {
   33:         private static XDocument xd;
   34:  
   35:         private static List<Ia.Statistics.Cl.Model.Category> categoryList;
   36:  
   37:         private static List<Ia.Statistics.Cl.Model.Product> productList;
   38:  
   39:         private static List<Ia.Statistics.Cl.Model.Site> boutiqaatSiteList = new List<Site>{
   40:             Ia.Statistics.Cl.Model.Site.BoutiqaatKuwait,
   41:             Ia.Statistics.Cl.Model.Site.BoutiqaatSaudiArabia,
   42:             Ia.Statistics.Cl.Model.Site.BoutiqaatEmirates,
   43:             Ia.Statistics.Cl.Model.Site.BoutiqaatQatar,
   44:             Ia.Statistics.Cl.Model.Site.BoutiqaatBahrain,
   45:             Ia.Statistics.Cl.Model.Site.BoutiqaatOman,
   46:             Ia.Statistics.Cl.Model.Site.BoutiqaatIraq,
   47:         };
   48:  
   49:         ////////////////////////////////////////////////////////////////////////////
   50:  
   51:         /// <summary>
   52:         /// 
   53:         /// </summary>
   54:         public Default() { }
   55:  
   56:         ////////////////////////////////////////////////////////////////////////////
   57:  
   58:         /// <summary>
   59:         ///
   60:         /// </summary>
   61:         public static string ReadUpdateProductListOfCategorySequentially(Ia.Statistics.Cl.Model.Site site0)
   62:         {
   63:             string s;
   64:  
   65:             var category = Ia.Statistics.Cl.Model.Boutiqaat.Default.CategoryList.RandomThenNext();
   66:  
   67:             var site = Ia.Statistics.Cl.Model.Site.SiteFromId(category.SiteId);
   68:  
   69:             var productPriceStockQuantitySoldList = ProductPriceStockListOfCategory(site, category, out string exception);
   70:  
   71:             if (string.IsNullOrEmpty(exception))
   72:             {
   73:                 if (productPriceStockQuantitySoldList.Count > 0)
   74:                 {
   75:                     s = string.Empty;
   76:  
   77:                     foreach (var productPriceStockQuantitySold in productPriceStockQuantitySoldList)
   78:                     {
   79:                         if (!string.IsNullOrEmpty(productPriceStockQuantitySold.Product.Sku))
   80:                         {
   81:                             Ia.Statistics.Cl.Model.Product.Create(productPriceStockQuantitySold.Product);
   82:                             Ia.Statistics.Cl.Model.ProductPriceSpot.Create(productPriceStockQuantitySold.Product, productPriceStockQuantitySold.Price);
   83:                             Ia.Statistics.Cl.Model.ProductStockSpot.Create(productPriceStockQuantitySold.Product, productPriceStockQuantitySold.Stock);
   84:  
   85:                             s += "Product: " + productPriceStockQuantitySold.Product.Name + "; price: " + productPriceStockQuantitySold.Price + "; stock: " + productPriceStockQuantitySold.Stock + ". ";
   86:                         }
   87:                         else
   88:                         {
   89:                             s += "Product: " + productPriceStockQuantitySold.Product.Name + ": SKU is null. ";
   90:                         }
   91:                     }
   92:                 }
   93:                 else s = "Product list is 0. ";
   94:  
   95:                 s = site.Name + ": " + category.Url + ": " + s;
   96:             }
   97:             else s = exception;
   98:  
   99:             return s;
  100:         }
  101:  
  102:         ////////////////////////////////////////////////////////////////////////////
  103:  
  104:         /// <summary>
  105:         ///
  106:         /// </summary>
  107:         public static List<Ia.Statistics.Cl.Model.ProductPriceStockQuantitySold> ProductPriceStockListOfCategory(Ia.Statistics.Cl.Model.Site site, Ia.Statistics.Cl.Model.Category category, out string exception)
  108:         {
  109:             var productPriceStockQuantitySoldList = new List<Ia.Statistics.Cl.Model.ProductPriceStockQuantitySold>();
  110:  
  111:             var options = new ChromeOptions();
  112:  
  113:             var chromeDriverService = ChromeDriverService.CreateDefaultService();
  114:             chromeDriverService.HideCommandPromptWindow = true;
  115:             chromeDriverService.SuppressInitialDiagnosticInformation = true;
  116:  
  117:             options.AddArgument("--headless");
  118:             options.AddArgument("--log-level=3");
  119:             options.AddArgument("--disable-extensions");
  120:             options.AddArgument("--ignore-certificate-errors");
  121:  
  122:             using (var chromeDriver = new OpenQA.Selenium.Chrome.ChromeDriver(chromeDriverService, options))
  123:             {
  124:                 chromeDriver.Manage().Timeouts().ImplicitWait = Ia.Statistics.Cl.Model.Default.TimeoutTimeSpan;
  125:  
  126:                 chromeDriver.Navigate().GoToUrl(category.Url);
  127:  
  128:                 // maximize the browser
  129:                 // chromeDriver.Manage().Window.Maximize();
  130:  
  131:                 // scroll down the webpage
  132:                 var javaScriptExecutor = ((IJavaScriptExecutor)chromeDriver);
  133:                 javaScriptExecutor.ExecuteScript("window.scrollTo(0, document.body.scrollHeight)");
  134:  
  135:                 var content = chromeDriver.PageSource;
  136:  
  137:                 ProductPriceStockListFromCategoryContent(site, category, content, out productPriceStockQuantitySoldList, out exception);
  138:             }
  139:  
  140:             return productPriceStockQuantitySoldList;
  141:         }
  142:  
  143:         ////////////////////////////////////////////////////////////////////////////
  144:  
  145:         /// <summary>
  146:         ///
  147:         /// </summary>
  148:         public static void ProductPriceStockListFromCategoryContent(Ia.Statistics.Cl.Model.Site site, Ia.Statistics.Cl.Model.Category category, string content, out List<Ia.Statistics.Cl.Model.ProductPriceStockQuantitySold> productPriceStockQuantitySoldList, out string exception)
  149:         {
  150:             productPriceStockQuantitySoldList = new List<Ia.Statistics.Cl.Model.ProductPriceStockQuantitySold>();
  151:  
  152:             var matchCollection = Regex.Matches(content, @"{""gender"":.+?,""name"":""(.+?)"",.+?,""sku"":""(.+?)"",.+?,""final_price"":""(.+?)"",""product_url"":""(.+?)"",.+?,""qty_available"":""(.+?)"",""qty_allowed"":""(.+?)"",.+?}", RegexOptions.None, Ia.Statistics.Cl.Model.Default.TimeoutTimeSpan);
  153:  
  154:             foreach (Match match in matchCollection)
  155:             {
  156:                 var product = new Ia.Statistics.Cl.Model.Product();
  157:                 var productPriceStockQuantitySold = new Ia.Statistics.Cl.Model.ProductPriceStockQuantitySold();
  158:  
  159:                 var sku = match.Groups[2].Value; // sku
  160:  
  161:                 var name = match.Groups[1].Value; // name
  162:                 name = Ia.Statistics.Cl.Model.Default.NormalizeName(name);
  163:  
  164:                 var url = match.Groups[4].Value; // product_url
  165:  
  166:                 product.Id = Ia.Statistics.Cl.Model.Product.ProductId(site, sku);
  167:                 product.SiteId = site.Id;
  168:                 //product.Category = category;
  169:                 product.Sku = sku;
  170:                 product.Name = name;
  171:                 product.Url = url;
  172:  
  173:                 var price = decimal.TryParse(match.Groups[3].Value, out decimal d) ? d : 0; // final_price
  174:  
  175:                 var stock = int.Parse(match.Groups[5].Value); // qty_available
  176:                 stock = stock <= Ia.Statistics.Cl.Model.Default.MaximumReasonableStockValue ? stock : Ia.Statistics.Cl.Model.Default.MaximumReasonableStockValue;
  177:  
  178:                 productPriceStockQuantitySold.Product = product;
  179:                 productPriceStockQuantitySold.Price = price;
  180:                 productPriceStockQuantitySold.Stock = stock;
  181:  
  182:                 productPriceStockQuantitySoldList.Add(productPriceStockQuantitySold);
  183:             }
  184:  
  185:             exception = string.Empty;
  186:         }
  187:  
  188:         ////////////////////////////////////////////////////////////////////////////
  189:  
  190:         /// <summary>
  191:         ///
  192:         /// </summary>
  193:         public static List<Ia.Statistics.Cl.Model.Category> CategoryList
  194:         {
  195:             get
  196:             {
  197:                 if (categoryList == null || categoryList.Count == 0)
  198:                 {
  199:                     categoryList = new List<Model.Category>();
  200:  
  201:                     foreach (var site in boutiqaatSiteList)
  202:                     {
  203:                         categoryList.AddRange((from c in XDocument.Element("boutiqaat").Descendants("category")
  204:                                                where !c.HasElements
  205:                                                select new Ia.Statistics.Cl.Model.Category
  206:                                                {
  207:                                                    Id = 0, //Ia.Statistics.Cl.Model.Category.CategoryId(site, int.Parse(c.Attribute("id").Value)),
  208:                                                    SiteId = site.Id,
  209:                                                    Url = site.BaseUrl + c.Attribute("url").Value,
  210:                                                    Name = c.Attribute("name").Value
  211:                                                }
  212:                         ).ToList<Ia.Statistics.Cl.Model.Category>());
  213:  
  214:                         categoryList = categoryList.Shuffle().ToList();
  215:                     }
  216:                 }
  217:  
  218:                 return categoryList;
  219:             }
  220:         }
  221:  
  222:         ////////////////////////////////////////////////////////////////////////////
  223:  
  224:         /// <summary>
  225:         /// 
  226:         /// How to embed and access resources by using Visual C# http://support.microsoft.com/kb/319292/en-us
  227:         /// 
  228:         /// 1. Change the "Build Action" property of your XML file from "Content" to "Embedded Resource".
  229:         /// 2. Add "using System.Reflection".
  230:         /// 3. Manifest resource stream will start with the project namespace, the location of XML file.
  231:         /// 
  232:         /// </summary>
  233:  
  234:         private static XDocument XDocument
  235:         {
  236:             get
  237:             {
  238:                 Assembly _assembly;
  239:                 StreamReader streamReader;
  240:  
  241:                 xd = null;
  242:                 _assembly = Assembly.GetExecutingAssembly();
  243:                 streamReader = new StreamReader(_assembly.GetManifestResourceStream("Ia.Statistics.Cl.model.boutiqaat.com.default.xml"));
  244:  
  245:                 try
  246:                 {
  247:                     if (streamReader.Peek() != -1)
  248:                     {
  249:                         xd = System.Xml.Linq.XDocument.Load(streamReader);
  250:                     }
  251:                 }
  252:                 catch (Exception)
  253:                 {
  254:                 }
  255:                 finally
  256:                 {
  257:                 }
  258:  
  259:                 return xd;
  260:             }
  261:         }
  262:  
  263:         ////////////////////////////////////////////////////////////////////////////
  264:         ////////////////////////////////////////////////////////////////////////////
  265:     }
  266: }