", "");
- }
-
- // Category
- match = categoryRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.Category = Converters.ToDiscCategory(match.Groups[1].Value);
- else
- info.CommonDiscInfo.Category = RedumpDiscCategory.Games;
-
- // Comments
- match = commentsRegex.Match(discData);
- if (match.Success)
- {
- info.CommonDiscInfo.Comments = WebUtility.HtmlDecode(match.Groups[1].Value)
- .Replace("
", "\n")
- .Replace("ISBN", "[T:ISBN]") + "\n";
- }
-
- // Contents
- match = contentsRegex.Match(discData);
- if (match.Success)
- {
- info.CommonDiscInfo.Contents = WebUtility.HtmlDecode(match.Groups[1].Value)
- .Replace("
", "\n")
- .Replace("
", "");
- info.CommonDiscInfo.Contents = Regex.Replace(info.CommonDiscInfo.Contents, @"", "");
- }
-
- // Dumpers
- var matches = dumpersRegex.Matches(discData);
- if (matches.Count > 0)
- {
- List tempDumpers = new List();
- foreach (Match submatch in matches)
- {
- tempDumpers.Add(WebUtility.HtmlDecode(submatch.Groups[1].Value));
- }
-
- info.DumpersAndStatus.Dumpers = tempDumpers.ToArray();
- }
-
- // Edition
- match = editionRegex.Match(discData);
- if (match.Success)
- info.VersionAndEditions.OtherEditions = WebUtility.HtmlDecode(match.Groups[1].Value);
-
- // Error Count
- match = errorCountRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.ErrorsCount = match.Groups[1].Value;
-
- // Foreign Title
- match = foreignTitleRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.ForeignTitleNonLatin = WebUtility.HtmlDecode(match.Groups[1].Value);
- else
- info.CommonDiscInfo.ForeignTitleNonLatin = null;
-
- // Languages
- matches = languagesRegex.Matches(discData);
- if (matches.Count > 0)
- {
- List tempLanguages = new List();
- foreach (Match submatch in matches)
- {
- tempLanguages.Add(Converters.ToRedumpLanguage(submatch.Groups[1].Value));
- }
-
- info.CommonDiscInfo.Languages = tempLanguages.Where(l => l != null).ToArray();
- }
-
- // Last Modified
- match = lastModifiedRegex.Match(discData);
- if (match.Success)
- {
- if (DateTime.TryParse(match.Groups[1].Value, out DateTime lastModified))
- info.LastModified = lastModified;
- else
- info.LastModified = null;
- }
-
- // Media
- match = mediaRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.Media = Converters.ToMediaType(match.Groups[1].Value);
-
- // PVD
- match = pvdRegex.Match(discData);
- if (match.Success)
- {
- info.Extras.PVD = WebUtility.HtmlDecode(match.Groups[1].Value)
- .Replace("
", "\n")
- .Replace("
", "");
- info.Extras.PVD = Regex.Replace(info.Extras.PVD, @"", "");
- }
-
- // Region
- match = regionRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.Region = Converters.ToRedumpRegion(match.Groups[1].Value);
-
- // Serial
- match = serialRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.Serial = WebUtility.HtmlDecode(match.Groups[1].Value);
-
- // System
- match = systemRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.System = Converters.ToKnownSystem(match.Groups[1].Value);
-
- // Title, Disc Number/Letter, Disc Title
- match = titleRegex.Match(discData);
- if (match.Success)
- {
- string title = WebUtility.HtmlDecode(match.Groups[1].Value);
-
- // If we have parenthesis, title is everything before the first one
- int firstParenLocation = title.IndexOf(" (");
- if (firstParenLocation >= 0)
- {
- info.CommonDiscInfo.Title = title.Substring(0, firstParenLocation);
- var subMatches = discNumberLetterRegex.Match(title);
- for (int i = 1; i < subMatches.Groups.Count; i++)
- {
- string subMatch = subMatches.Groups[i].Value;
-
- // Disc number or letter
- if (subMatch.StartsWith("Disc"))
- info.CommonDiscInfo.DiscNumberLetter = subMatch.Remove(0, "Disc ".Length);
-
- // Disc title
- else
- info.CommonDiscInfo.DiscTitle = subMatch;
- }
- }
- // Otherwise, leave the title as-is
- else
- {
- info.CommonDiscInfo.Title = title;
- }
- }
-
- // Tracks
- matches = trackRegex.Matches(discData);
- if (matches.Count > 0)
- {
- List
tempTracks = new List();
- foreach (Match submatch in matches)
- {
- tempTracks.Add(submatch.Groups[1].Value);
- }
-
- info.TracksAndWriteOffsets.ClrMameProData = string.Join("\n", tempTracks);
- }
-
- // Track Count
- match = trackCountRegex.Match(discData);
- if (match.Success)
- info.TracksAndWriteOffsets.Cuesheet = match.Groups[1].Value;
-
- // Version
- match = versionRegex.Match(discData);
- if (match.Success)
- info.VersionAndEditions.Version = WebUtility.HtmlDecode(match.Groups[1].Value);
-
- // Write Offset
- match = writeOffsetRegex.Match(discData);
- if (match.Success)
- info.TracksAndWriteOffsets.OtherWriteOffsets = WebUtility.HtmlDecode(match.Groups[1].Value);
-
- return info;
- }
-
- ///
- /// Download the last modified disc pages, until first failure
- ///
- /// Output directory to save data to
- public void DownloadLastModified(string outDir)
- {
- // Keep getting last modified pages until there are none left
- int pageNumber = 1;
- while (true)
- {
- if (!CheckSingleSitePage(string.Format(lastModifiedUrl, pageNumber++), outDir, true))
- break;
- }
- }
-
- ///
- /// Download the last submitted WIP disc pages
- ///
- /// Output directory to save data to
- public void DownloadLastSubmitted(string outDir)
- {
- CheckSingleWIPPage(wipDumpsUrl, outDir, false);
- }
-
- ///
- /// Download premade packs
- ///
- /// Output directory to save data to
- /// True to use named subfolders to store downloads, false to store directly in the output directory
- public void DownloadPacks(string outDir, bool useSubfolders)
- {
- this.DownloadPacks(packCuesUrl, Extras.HasCues, "CUEs", outDir, useSubfolders ? "cue" : null);
- this.DownloadPacks(packDatfileUrl, Extras.HasDat, "DATs", outDir, useSubfolders ? "dat" : null);
- this.DownloadPacks(packDkeysUrl, Extras.HasDkeys, "Decrypted KEYS", outDir, useSubfolders ? "dkey" : null);
- this.DownloadPacks(packGdiUrl, Extras.HasGdi, "GDIs", outDir, useSubfolders ? "gdi" : null);
- this.DownloadPacks(packKeysUrl, Extras.HasKeys, "KEYS", outDir, useSubfolders ? "keys" : null);
- this.DownloadPacks(packLsdUrl, Extras.HasKeys, "LSD", outDir, useSubfolders ? "lsd" : null);
- this.DownloadPacks(packSbiUrl, Extras.HasSbi, "SBIs", outDir, useSubfolders ? "sbi" : null);
- }
-
- ///
- /// Download premade packs for an individual system
- ///
- /// RedumpSystem to get all possible packs for
- /// Output directory to save data to
- /// True to use named subfolders to store downloads, false to store directly in the output directory
- public void DownloadPacksForSystem(RedumpSystem system, string outDir, bool useSubfolders)
- {
- RedumpSystem?[] systemAsArray = new RedumpSystem?[] { system };
-
- if (Extras.HasCues.Contains(system))
- this.DownloadPacks(packCuesUrl, systemAsArray, "CUEs", outDir, useSubfolders ? "cue" : null);
-
- if (Extras.HasDat.Contains(system))
- this.DownloadPacks(packCuesUrl, Extras.HasDat, "DATs", outDir, useSubfolders ? "dat" : null);
-
- if (Extras.HasDkeys.Contains(system))
- this.DownloadPacks(packCuesUrl, Extras.HasDkeys, "Decrypted KEYS", outDir, useSubfolders ? "dkey" : null);
-
- if (Extras.HasGdi.Contains(system))
- this.DownloadPacks(packCuesUrl, Extras.HasGdi, "GDIs", outDir, useSubfolders ? "gdi" : null);
-
- if (Extras.HasKeys.Contains(system))
- this.DownloadPacks(packCuesUrl, Extras.HasKeys, "KEYS", outDir, useSubfolders ? "keys" : null);
-
- if (Extras.HasLsd.Contains(system))
- this.DownloadPacks(packCuesUrl, Extras.HasKeys, "LSD", outDir, useSubfolders ? "lsd" : null);
-
- if (Extras.HasSbi.Contains(system))
- this.DownloadPacks(packCuesUrl, Extras.HasSbi, "SBIs", outDir, useSubfolders ? "sbi" : null);
- }
-
- ///
- /// Download the disc pages associated with a given quicksearch query
- ///
- /// Query string to attempt to search for
- public Dictionary DownloadSearchResults(string query)
- {
- Dictionary resultPages = new Dictionary();
-
- // Strip quotes
- query = query.Trim('"', '\'');
-
- // Special characters become dashes
- query = query.Replace(' ', '-');
- query = query.Replace('/', '-');
- query = query.Replace('\\', '/');
-
- // Lowercase is defined per language
- query = query.ToLowerInvariant();
-
- // Keep getting quicksearch pages until there are none left
- int pageNumber = 1;
- while (true)
- {
- List pageIds = CheckSingleSitePage(string.Format(quickSearchUrl, query, pageNumber++));
- foreach (int pageId in pageIds)
- {
- resultPages[pageId] = DownloadSingleSiteID(pageId);
- }
-
- if (pageIds.Count <= 1)
- break;
- }
-
- return resultPages;
- }
-
- ///
- /// Download the disc pages associated with a given quicksearch query
- ///
- /// Query string to attempt to search for
- /// Output directory to save data to
- public void DownloadSearchResults(string query, string outDir)
- {
- // Strip quotes
- query = query.Trim('"', '\'');
-
- // Special characters become dashes
- query = query.Replace(' ', '-');
- query = query.Replace('/', '-');
- query = query.Replace('\\', '/');
-
- // Lowercase is defined per language
- query = query.ToLowerInvariant();
-
- // Keep getting quicksearch pages until there are none left
- int pageNumber = 1;
- while (true)
- {
- if (!CheckSingleSitePage(string.Format(quickSearchUrl, query, pageNumber++), outDir, false))
- break;
- }
- }
-
- ///
- /// Download the specified range of site disc pages
- ///
- /// Output directory to save data to
- /// Starting ID for the range
- /// Ending ID for the range (inclusive)
- public void DownloadSiteRange(string outDir, int minId = 0, int maxId = 0)
- {
- if (!LoggedIn)
- {
- Console.WriteLine("Site download functionality is only available to Redump members");
- return;
- }
-
- for (int id = minId; id <= maxId; id++)
- {
- if (DownloadSingleSiteID(id, outDir, true))
- Thread.Sleep(5 * 1000); // Intentional sleep here so we don't flood the server
- }
- }
-
- ///
- /// Download the disc pages associated with the given user
- ///
- /// Username to check discs for
- /// Output directory to save data to
- public void DownloadUser(string username, string outDir)
- {
- if (!LoggedIn)
- {
- Console.WriteLine("User download functionality is only available to Redump members");
- return;
- }
-
- // Keep getting user pages until there are none left
- int pageNumber = 1;
- while (true)
- {
- if (!CheckSingleSitePage(string.Format(userDumpsUrl, username, pageNumber++), outDir, false))
- break;
- }
- }
-
- ///
- /// Download the specified range of WIP disc pages
- ///
- /// RedumpWebClient for all access
- /// Output directory to save data to
- /// Starting ID for the range
- /// Ending ID for the range (inclusive)
- public void DownloadWIPRange(string outDir, int minId = 0, int maxId = 0)
- {
- if (!LoggedIn || !IsStaff)
- {
- Console.WriteLine("WIP download functionality is only available to Redump moderators");
- return;
- }
-
- for (int id = minId; id <= maxId; id++)
- {
- if (DownloadSingleWIPID(id, outDir, true))
- Thread.Sleep(5 * 1000); // Intentional sleep here so we don't flood the server
- }
- }
-
- ///
- /// Fill out an existing SubmissionInfo object based on a disc page
- ///
- /// Existing SubmissionInfo object to fill
- /// Redump disc ID to retrieve
- public void FillFromId(SubmissionInfo info, int id)
- {
- string discData = DownloadSingleSiteID(id);
- if (string.IsNullOrEmpty(discData))
- return;
-
- // Title, Disc Number/Letter, Disc Title
- var match = titleRegex.Match(discData);
- if (match.Success)
- {
- string title = WebUtility.HtmlDecode(match.Groups[1].Value);
-
- // If we have parenthesis, title is everything before the first one
- int firstParenLocation = title.IndexOf(" (");
- if (firstParenLocation >= 0)
- {
- info.CommonDiscInfo.Title = title.Substring(0, firstParenLocation);
- var subMatches = discNumberLetterRegex.Match(title);
- for (int i = 1; i < subMatches.Groups.Count; i++)
- {
- string subMatch = subMatches.Groups[i].Value;
-
- // Disc number or letter
- if (subMatch.StartsWith("Disc"))
- info.CommonDiscInfo.DiscNumberLetter = subMatch.Remove(0, "Disc ".Length);
-
- // Disc title
- else
- info.CommonDiscInfo.DiscTitle = subMatch;
- }
- }
- // Otherwise, leave the title as-is
- else
- {
- info.CommonDiscInfo.Title = title;
- }
- }
-
- // Foreign Title
- match = foreignTitleRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.ForeignTitleNonLatin = WebUtility.HtmlDecode(match.Groups[1].Value);
- else
- info.CommonDiscInfo.ForeignTitleNonLatin = null;
-
- // Category
- match = categoryRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.Category = Converters.ToDiscCategory(match.Groups[1].Value);
- else
- info.CommonDiscInfo.Category = RedumpDiscCategory.Games;
-
- // Region
- match = regionRegex.Match(discData);
- if (match.Success)
- info.CommonDiscInfo.Region = Converters.ToRedumpRegion(match.Groups[1].Value);
-
- // Languages
- var matches = languagesRegex.Matches(discData);
- if (matches.Count > 0)
- {
- List tempLanguages = new List();
- foreach (Match submatch in matches)
- tempLanguages.Add(Converters.ToRedumpLanguage(submatch.Groups[1].Value));
-
- info.CommonDiscInfo.Languages = tempLanguages.Where(l => l != null).ToArray();
- }
-
- // Error count
- match = errorCountRegex.Match(discData);
- if (match.Success)
- {
- // If the error count is empty, fill from the page
- if (string.IsNullOrEmpty(info.CommonDiscInfo.ErrorsCount))
- info.CommonDiscInfo.ErrorsCount = match.Groups[1].Value;
- }
-
- // Version
- match = versionRegex.Match(discData);
- if (match.Success)
- info.VersionAndEditions.Version = WebUtility.HtmlDecode(match.Groups[1].Value);
-
- // Dumpers
- matches = dumpersRegex.Matches(discData);
- if (matches.Count > 0)
- {
- // Start with any currently listed dumpers
- List tempDumpers = new List();
- if (info.DumpersAndStatus.Dumpers.Length > 0)
- {
- foreach (string dumper in info.DumpersAndStatus.Dumpers)
- tempDumpers.Add(dumper);
- }
-
- foreach (Match submatch in matches)
- tempDumpers.Add(WebUtility.HtmlDecode(submatch.Groups[1].Value));
-
- info.DumpersAndStatus.Dumpers = tempDumpers.ToArray();
- }
-
- // Comments
- match = commentsRegex.Match(discData);
- if (match.Success)
- {
- info.CommonDiscInfo.Comments += (string.IsNullOrEmpty(info.CommonDiscInfo.Comments) ? string.Empty : "\n")
- + WebUtility.HtmlDecode(match.Groups[1].Value)
- .Replace("
", "\n")
- .Replace("ISBN", "[T:ISBN]") + "\n";
- }
-
- // Contents
- match = contentsRegex.Match(discData);
- if (match.Success)
- {
- info.CommonDiscInfo.Contents = WebUtility.HtmlDecode(match.Groups[1].Value)
- .Replace("
", "\n")
- .Replace(" ", "");
- info.CommonDiscInfo.Contents = Regex.Replace(info.CommonDiscInfo.Contents, @"