public void AddDataFromXmlTest() { XElement xml; EshopTitle title; // check samurai data xml = XElement.Parse("<title id=\"1234\">" + "<product_code>CTR-P-WXYZ</product_code>" + "<name>TestTitle <br>Newline <br>Newline2</name>" + "<icon_url>https://icon.url/test.jpg</icon_url>" + "<platform id=\"124\" device=\"CTR\"><name>Nintendo 3DS (Card/Download)</name></platform>" + "</title>"); title = new EshopTitle(); title.AddDataFromXml(xml); Assert.AreEqual("1234", title.EshopId); Assert.AreEqual("WXYZ", title.ProductCode); Assert.AreEqual("TestTitle Newline Newline2", title.Name); Assert.AreEqual("https://icon.url/test.jpg", title.IconUrl); Assert.AreEqual((int)124, title.Platform); // check ninja data xml = XElement.Parse("<title_ec_info>" + "<title_id>00050000101C9500</title_id>" + "<content_size>10551265752</content_size>" + "<title_version>0</title_version>" + "<disable_download>false</disable_download>" + "</title_ec_info>"); title = new EshopTitle(); title.AddDataFromXml(xml); Assert.AreEqual("00050000101C9500", title.TitleIdString); Assert.AreEqual((ulong)10551265752, title.Size); Assert.AreEqual("", title.VersionString); }
/// <summary> /// Retrieves a list of all titles from all available regions. /// </summary> /// <param name="shopID">Use 1 for the 3DS eShop, 2 for the WiiU eShop.</param> /// <returns>A list of titles</returns> public async Task <List <EshopTitle> > GetAllTitles(int shopID) { // get title counts for all regions Console.WriteLine("Getting title count for {0} regions ...", Enum.GetValues(typeof(Region)).Length - 2); Dictionary <Region, int> titleCounts = new Dictionary <Region, int>(); foreach (Region region in Enum.GetValues(typeof(Region))) { if (region == Region.None || region == Region.ALL) { continue; } await Retry(async() => { titleCounts.Add(region, await Samurai.GetTitleCountForRegion(webClient, region, shopID)); }); } int totalTitleCount = titleCounts.Values.Sum(); Console.WriteLine("Downloading metadata for {0} titles ...", totalTitleCount); progressManager.SetTitle(string.Format("Downloading metadata for {0} titles ...", totalTitleCount)); progressManager.Reset(totalTitleCount); DateTime currentDate = DateTime.Today; List <EshopTitle> titleList = new List <EshopTitle>(); // loop through regions foreach (KeyValuePair <Region, int> pair in titleCounts) { Region region = pair.Key; int titleCount = pair.Value; // get titles from samurai for (int offset = 0; offset < titleCount; offset += TitleRequestLimit) { XDocument titlesXml = null; await Retry(async() => { titlesXml = await Samurai.GetTitlesXmlForRegion(webClient, region, shopID, TitleRequestLimit, offset); }); /* structure: * <eshop><contents ...> * <content index=1><title ...>[title info]</title></content> * <content index=2><title ...>[title info]</title></content> * </contents></eshop> */ XElement contentsElement = titlesXml.Root.Element("contents"); // iterate over titles in xml foreach (XElement titleElement in contentsElement.Elements().Select(e => e.Element("title"))) { // check release date string releaseDateString = titleElement.Element("release_date_on_eshop")?.Value; if (!String.IsNullOrEmpty(releaseDateString)) { DateTime releaseDate; if (!DateTime.TryParseExact(releaseDateString, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out releaseDate)) { continue; } if (releaseDate > currentDate) { continue; } } // create title and add data EshopTitle title = new EshopTitle(); title.Region = region; // set title fields from xml (incomplete, some fields must be retrieved from ninja) title.AddDataFromXml(titleElement); progressManager.Step(string.Format("{0}-{1}", region.ToCountryCode(), title.EshopId)); // some exceptions: if (title.Platform == 63 || title.Platform == 1003) // ignore 3DS software updates { continue; } if (title.Platform == 143) // ignore some unknown platform with just 1 title { continue; } // get remaining data from ninja XElement titleECInfoElement; await Retry(async() => { titleECInfoElement = await Ninja.GetECInfoForRegionAndTitleID(certWebClient, region, title.EshopId); title.AddDataFromXml(titleECInfoElement); if (title.JsonType != DatabaseJsonType.None) { titleList.Add(title); } }); } } } // merge titles that occur in all regions into one title with the 'ALL' region IEnumerable <EshopTitle> titleListEnumerable = titleList; var allRegions = Enum.GetValues(typeof(Region)).OfType <Region>().Where(r => r != Region.None && r != Region.ALL); var groups = titleListEnumerable.GroupBy(t => t.TitleId).Select(g => g.ToList()).ToList(); foreach (var group in groups) { var groupRegions = group.Select(t => t.Region); if (allRegions.All(groupRegions.Contains)) { titleListEnumerable = titleListEnumerable.Except(group.Skip(1)); group[0].Region = Region.ALL; } } titleList = titleListEnumerable.ToList(); return(titleList); }