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

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

Structure of the dabdoob.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: using System.Threading;
   11: using OpenQA.Selenium.Interactions;
   12:  
   13: namespace Ia.Statistics.Cl.Models.Dabdoob
   14: {
   15:     ////////////////////////////////////////////////////////////////////////////
   16:  
   17:     /// <summary publish="true">
   18:     /// Structure of the dabdoob.com website.
   19:     /// </summary>
   20:     /// <remarks> 
   21:     /// Copyright © 2024-2025 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
   22:     ///
   23:     /// 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
   24:     /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
   25:     ///
   26:     /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   27:     /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   28:     /// 
   29:     /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
   30:     /// 
   31:     /// Copyright notice: This notice may not be removed or altered from any source distribution.
   32:     /// </remarks> 
   33:     public class Default
   34:     {
   35:         private static XDocument xd;
   36:  
   37:         private static List<Ia.Statistics.Cl.Models.Category> categoryList;
   38:  
   39:         private static List<Ia.Statistics.Cl.Models.Product> productList;
   40:  
   41:         private static List<Ia.Statistics.Cl.Models.Site> dabdoobSiteList = new List<Site>{
   42:             Ia.Statistics.Cl.Models.Site.DabdoobKuwait,
   43:             Ia.Statistics.Cl.Models.Site.DabdoobSaudiArabia,
   44:             Ia.Statistics.Cl.Models.Site.DabdoobEmirates,
   45:             Ia.Statistics.Cl.Models.Site.DabdoobQatar,
   46:             Ia.Statistics.Cl.Models.Site.DabdoobBahrain,
   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.Models.Site site0)
   62:         {
   63:             string s;
   64:  
   65:             var category = Ia.Statistics.Cl.Models.Dabdoob.Default.CategoryList.RandomThenNext();
   66:  
   67:             var site = Ia.Statistics.Cl.Models.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.Models.Product.Create(productPriceStockQuantitySold.Product);
   82:                             Ia.Statistics.Cl.Models.ProductPriceSpot.Create(productPriceStockQuantitySold.Product, productPriceStockQuantitySold.Price);
   83:                             Ia.Statistics.Cl.Models.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.Models.ProductPriceStockQuantitySold> ProductPriceStockListOfCategory(Ia.Statistics.Cl.Models.Site site, Ia.Statistics.Cl.Models.Category category, out string exception)
  108:         {
  109:             int areaId;
  110:  
  111:             var productPriceStockQuantitySoldList = new List<Ia.Statistics.Cl.Models.ProductPriceStockQuantitySold>();
  112:  
  113:             var options = new ChromeOptions();
  114:  
  115:             var chromeDriverService = ChromeDriverService.CreateDefaultService();
  116:             chromeDriverService.HideCommandPromptWindow = true;
  117:             chromeDriverService.SuppressInitialDiagnosticInformation = true;
  118:  
  119:             options.AddArgument("--headless");
  120:             options.AddArgument("--log-level=3");
  121:             options.AddArgument("--disable-extensions");
  122:             options.AddArgument("--ignore-certificate-errors");
  123:  
  124:             switch (site.Iso)
  125:             {
  126:                 case "KW": areaId = 10; break;
  127:                 case "SA": areaId = 2648; break;
  128:                 case "AE": areaId = 12; break;
  129:                 case "QA": areaId = 6; break;
  130:                 case "BH": areaId = 11; break;
  131:                 default: areaId = 10; break;
  132:             }
  133:  
  134:             using (var chromeDriver = new OpenQA.Selenium.Chrome.ChromeDriver(chromeDriverService, options))
  135:             {
  136:                 chromeDriver.Manage().Timeouts().ImplicitWait = Ia.Statistics.Cl.Models.Default.TimeoutTimeSpan;
  137:  
  138:                 chromeDriver.Navigate().GoToUrl(category.Url);
  139:  
  140:                 chromeDriver.Manage().Cookies.AddCookie(new OpenQA.Selenium.Cookie("DAB_AREA", areaId.ToString(), "", DateTime.UtcNow.AddHours(3).AddYears(1)));
  141:                 chromeDriver.Manage().Cookies.AddCookie(new OpenQA.Selenium.Cookie("DAB_COUNTRY", site.Iso, "", DateTime.UtcNow.AddHours(3).AddYears(1)));
  142:                 chromeDriver.Manage().Cookies.AddCookie(new OpenQA.Selenium.Cookie("accept_cookies", "accepted", "", DateTime.UtcNow.AddHours(3).AddYears(1)));
  143:                 chromeDriver.Manage().Cookies.AddCookie(new OpenQA.Selenium.Cookie("ajs_anonymous_id", "e7a170bb-807b-4546-8caf-b7cec22f20c5", "", DateTime.UtcNow.AddHours(3).AddYears(1)));
  144:  
  145:                 chromeDriver.Navigate().GoToUrl(category.Url); // I will access site again with location cookies
  146:  
  147:                 // maximize the browser
  148:                 // chromeDriver.Manage().Window.Maximize();
  149:  
  150:                 // scroll down the webpage
  151:                 var javaScriptExecutor = ((IJavaScriptExecutor)chromeDriver);
  152:                 javaScriptExecutor.ExecuteScript("window.scrollTo(0, document.body.scrollHeight)");
  153:  
  154:                 // loop through all "Load more" buttons 
  155:  
  156:                 IWebElement loadMoreButton;
  157:  
  158:                 do
  159:                 {
  160:                     try
  161:                     {
  162:                         // <button type="button" ... >Load More</button>
  163:                         //loadMoreButton = chromeDriver.FindElement(By.ClassName(@""), 10);
  164:                         //loadMoreButton = chromeDriver.FindElement(By.XPath("//button[@value='Load More' and @type='button']"), 10);
  165:                         loadMoreButton = chromeDriver.FindElement(By.XPath("//button[text()='Load More']"), 10);
  166:  
  167:                         if (loadMoreButton != null)
  168:                         {
  169:                             Actions actions = new Actions(chromeDriver);
  170:                             actions.MoveToElement(loadMoreButton).Click().Build().Perform();
  171:                             Thread.Sleep(2000);
  172:  
  173:                             // loadMoreButton.Click();
  174:  
  175:                             javaScriptExecutor.ExecuteScript("window.scrollTo(0, document.body.scrollHeight)");
  176:                         }
  177:                         else break;
  178:                     }
  179:                     catch (OpenQA.Selenium.NoSuchElementException e)
  180:                     {
  181:                         break;
  182:                     }
  183:                 }
  184:                 while (loadMoreButton != null);
  185:  
  186:                 var content = chromeDriver.PageSource;
  187:  
  188:                 ProductPriceStockListFromCategoryContent(site, category, content, out productPriceStockQuantitySoldList, out exception);
  189:             }
  190:  
  191:             return productPriceStockQuantitySoldList;
  192:         }
  193:  
  194:         ////////////////////////////////////////////////////////////////////////////
  195:  
  196:         /// <summary>
  197:         ///
  198:         /// </summary>
  199:         public static void ProductPriceStockListFromCategoryContent(Ia.Statistics.Cl.Models.Site site, Ia.Statistics.Cl.Models.Category category, string content, out List<Ia.Statistics.Cl.Models.ProductPriceStockQuantitySold> productPriceStockQuantitySoldList, out string exception)
  200:         {
  201:             productPriceStockQuantitySoldList = new List<Ia.Statistics.Cl.Models.ProductPriceStockQuantitySold>();
  202:  
  203:             //  {"id":85023,"name":"Spartan Mattel Hot Wheels Bicycle - 14 Inch","slug":"spartan-mattel-hot-wheels-bicycle-14-inch-85023","default_sku_id":87837,"skus":[{"id":87837,"name":"Spartan Mattel Hot Wheels Bicycle - 14 Inch","slug":"spartan-mattel-hot-wheels-bicycle-14-inch-87837","price":{"price":34.95,"old_price":null,"vat":false,"raw_price":34.95},"buy_limit":1,"medias":[{"url":"https://dabdoob-cdn-primary.fra1.cdn.digitaloceanspaces.com/media/master/sku/OpsgTd/c536d0ac-982c-4033-9e9e-76a14298b232_IircelT7Z.jpeg","type":"image","blurhash":null}]}],"brand":{"id":156,"name":"Spartan","slug":"spartan-156"},"category":{"id":20,"slug":"ride-on-and-scooters-20","name":"Ride-On And Scooters","color":"#334455","text_color":"#000000"},"subcategory":{"id":120,"name":"Bikes","slug":"bikes-120"}},
  204:             var matchCollection = Regex.Matches(content, @"{""id"":(.+?),""name"":""(.+?)"",""slug"":""(.+?)"",""default_sku_id"":(.+?),""skus"":.+?,""price"":{""price"":(.+?),.+?,""buy_limit"":(.+?),.+?}}", RegexOptions.None, Ia.Statistics.Cl.Models.Default.TimeoutTimeSpan);
  205:  
  206:             foreach (Match match in matchCollection)
  207:             {
  208:                 var product = new Ia.Statistics.Cl.Models.Product();
  209:                 var productPriceStockQuantitySold = new Ia.Statistics.Cl.Models.ProductPriceStockQuantitySold();
  210:  
  211:                 var sku = match.Groups[4].Value; // default_sku_id;
  212:  
  213:                 var name = match.Groups[2].Value; // name
  214:                 name = Ia.Statistics.Cl.Models.Default.NormalizeName(name);
  215:  
  216:                 var url = match.Groups[3].Value; // slug;
  217:  
  218:                 product.Id = Ia.Statistics.Cl.Models.Product.ProductId(site, sku);
  219:                 product.SiteId = site.Id;
  220:                 //product.Category = category;
  221:                 product.Sku = sku;
  222:                 product.Name = name;
  223:                 product.Url = site.BaseUrl + "/product/" + url;
  224:  
  225:                 var price = decimal.TryParse(match.Groups[5].Value, out decimal d) ? d : 0;
  226:  
  227:                 var stock = int.Parse(match.Groups[6].Value); // buy_limit;
  228:                 stock = stock <= Ia.Statistics.Cl.Models.Default.MaximumReasonableStockValue ? stock : Ia.Statistics.Cl.Models.Default.MaximumReasonableStockValue;
  229:  
  230:                 productPriceStockQuantitySold.Product = product;
  231:                 productPriceStockQuantitySold.Price = price;
  232:                 productPriceStockQuantitySold.Stock = stock;
  233:  
  234:                 productPriceStockQuantitySoldList.Add(productPriceStockQuantitySold);
  235:             }
  236:  
  237:             exception = string.Empty;
  238:         }
  239:  
  240:         ////////////////////////////////////////////////////////////////////////////
  241:  
  242:         /// <summary>
  243:         ///
  244:         /// </summary>
  245:         public static List<Ia.Statistics.Cl.Models.Category> CategoryList
  246:         {
  247:             get
  248:             {
  249:                 if (categoryList == null || categoryList.Count == 0)
  250:                 {
  251:                     categoryList = new List<Models.Category>();
  252:  
  253:                     foreach (var site in dabdoobSiteList)
  254:                     {
  255:                         categoryList.AddRange((from c in XDocument.Element("dabdoob").Descendants("category")
  256:                                                where !c.HasElements
  257:                                                select new Ia.Statistics.Cl.Models.Category
  258:                                                {
  259:                                                    Id = 0, //Ia.Statistics.Cl.Model.Category.CategoryId(site, int.Parse(c.Attribute("id").Value)),
  260:                                                    SiteId = site.Id,
  261:                                                    Url = site.BaseUrl + c.Attribute("url").Value,
  262:                                                    Name = c.Attribute("name").Value
  263:                                                }
  264:                         ).ToList<Ia.Statistics.Cl.Models.Category>());
  265:  
  266:                         categoryList = categoryList.Shuffle().ToList();
  267:                     }
  268:                 }
  269:  
  270:                 return categoryList;
  271:             }
  272:         }
  273:  
  274:         ////////////////////////////////////////////////////////////////////////////
  275:  
  276:         /// <summary>
  277:         /// 
  278:         /// How to embed and access resources by using Visual C# http://support.microsoft.com/kb/319292/en-us
  279:         /// 
  280:         /// 1. Change the "Build Action" property of your XML file from "Content" to "Embedded Resource".
  281:         /// 2. Add "using System.Reflection".
  282:         /// 3. Manifest resource stream will start with the project namespace, the location of XML file.
  283:         /// 
  284:         /// </summary>
  285:  
  286:         private static XDocument XDocument
  287:         {
  288:             get
  289:             {
  290:                 Assembly assembly;
  291:                 StreamReader streamReader;
  292:  
  293:                 xd = null;
  294:                 assembly = Assembly.GetExecutingAssembly();
  295:                 streamReader = new StreamReader(assembly.GetManifestResourceStream("Ia.Statistics.Cl.Models.dabdoob.com.default.xml"));
  296:  
  297:                 try
  298:                 {
  299:                     if (streamReader.Peek() != -1)
  300:                     {
  301:                         xd = System.Xml.Linq.XDocument.Load(streamReader);
  302:                     }
  303:                 }
  304:                 catch (Exception)
  305:                 {
  306:                 }
  307:                 finally
  308:                 {
  309:                 }
  310:  
  311:                 return xd;
  312:             }
  313:         }
  314:  
  315:         ////////////////////////////////////////////////////////////////////////////
  316:         ////////////////////////////////////////////////////////////////////////////
  317:     }
  318: }