public static List<DownloadsView> CreateCollectionFromProducts(List<ProductInfo> products) { List<DownloadsView> views = new List<DownloadsView> (); foreach (ProductInfo product in products) { if (product.Downloads.Count == 0) continue; DownloadsView view = new DownloadsView (); view.Name = product.Name; view.Downloads = new List<NamePlatformStringTuple> (product.Downloads); view.BranchId = product.BranchId; view.Slug = product.Slug; views.Add (view); } return views; }
public static List <DownloadsView> CreateCollectionFromProducts(List <ProductInfo> products) { List <DownloadsView> views = new List <DownloadsView> (); foreach (ProductInfo product in products) { if (product.Downloads.Count == 0) { continue; } DownloadsView view = new DownloadsView(); view.Name = product.Name; view.Downloads = new List <NamePlatformStringTuple> (product.Downloads); view.BranchId = product.BranchId; view.Slug = product.Slug; views.Add(view); } return(views); }
static List <string> GetCdnLinks(List <DownloadsView> downloads, CookieAwareWebClient wc, bool addComments = true) { List <string> links = new List <string> (); for (int i = 0; i < downloads.Count; ++i) { DownloadsView view = downloads [i]; Console.WriteLine("[{0}/{1}] {2}: Getting CDN links", i + 1, downloads.Count, view.Name); List <string> presentNames = new List <string> (view.Downloads.Select(v => v.Name + "\t" + v.Platform)); List <Tuple <string, string, string> > prodDownloads = GetDownloads(view.Slug, view.BranchId, wc); foreach (Tuple <string, string, string> tuple in prodDownloads.Where(t => presentNames.Contains(t.Item1 + "\t" + t.Item2))) { if (addComments) { links.Add(string.Format("# {0} - {1} ({2})", view.Name, tuple.Item1, tuple.Item2)); } links.Add(GetRedirectUrl(tuple.Item3, wc.CookieContainer)); } } return(links); }
public static void Main(string[] args) { Console.WriteLine("Desura Collection Dumper"); Console.WriteLine("(C) cyanic"); Console.WriteLine(); // Variables string dbPath = null; string downloadsPath = null; string keysPath = null; string linksPath = null; string tokensPath = null; string keysExportFilter = null; bool exportDownloads = false; bool exportKeys = false; bool exportLinks = false; bool omitLinksComments = false; // Argument parser foreach (string arg in args) { // Each switch is in the format of "/option=value" if (arg.StartsWith("/")) // A switch { string[] argSplit = arg.Split(new char[] { '=' }, 2); switch (argSplit [0].ToLower()) // Check option. New: Now works with flag options (no "=value"). { case "/i": // Check if specified already. Such a check should be present for every option. if (!string.IsNullOrEmpty(dbPath)) { argError("Database path is specified more than once."); } if (argSplit.Length != 2) { argError("Value for /i not specified."); } dbPath = argSplit [1]; break; case "/d": // Check if specified already. Such a check should be present for every option. if (!string.IsNullOrEmpty(downloadsPath)) { argError("Downloads database path is specified more than once."); } if (argSplit.Length != 2) { argError("Value for /d not specified."); } downloadsPath = argSplit [1]; break; case "/k": // Check if specified already. Such a check should be present for every option. if (!string.IsNullOrEmpty(dbPath)) { argError("Keys database path is specified more than once."); } if (argSplit.Length != 2) { argError("Value for /k not specified."); } keysPath = argSplit [1]; break; case "/l": // Check if specified already. Such a check should be present for every option. if (!string.IsNullOrEmpty(dbPath)) { argError("Links file path is specified more than once."); } if (argSplit.Length != 2) { argError("Value for /l not specified."); } linksPath = argSplit [1]; break; case "/t": // Check if specified already. Such a check should be present for every option. if (!string.IsNullOrEmpty(dbPath)) { argError("Token path is specified more than once."); } if (argSplit.Length != 2) { argError("Value for /t not specified."); } tokensPath = argSplit [1]; break; case "/xd": if (exportDownloads) { argError("Export downloads database option specified more than once."); } exportDownloads = true; break; case "/xk": if (exportKeys) { argError("Export keys database option specified more than once."); } exportKeys = true; if (argSplit.Length == 2) { keysExportFilter = argSplit [1]; } break; case "/xl": if (exportLinks) { argError("Export links option specified more than once."); } exportLinks = true; break; case "/o": if (omitLinksComments) { argError("Omit links file comments option specified more than once."); } omitLinksComments = true; break; case "/?": case "/h": case "/help": usage(); break; default: argError("Unknown argument " + argSplit [0]); break; } } } // Fill in default paths, if not specified if (dbPath == null) { dbPath = "database.yml"; } if (downloadsPath == null) { downloadsPath = "downloads.yml"; } if (keysPath == null) { keysPath = "keys.yml"; } if (linksPath == null) { linksPath = "downloadLinks.txt"; } if (tokensPath == null) { tokensPath = "tokens.txt"; } if (keysExportFilter == null) { keysExportFilter = ".*"; } // Argument validation. Oh boy... if ((exportKeys || exportDownloads) && !File.Exists(dbPath)) { argError("Input database must be specified."); } if (exportLinks && !File.Exists(dbPath) && !File.Exists(downloadsPath)) { argError("Either main database or downloads database path must be specified."); } if (!exportKeys && !exportDownloads && !exportLinks) { // Running with no export arguments, which auto-exports keys and downloads exportKeys = exportDownloads = true; } try { CookieAwareWebClient wc = new CookieAwareWebClient() { Encoding = Encoding.UTF8 }; if (exportLinks || !File.Exists(dbPath)) { if (!PromptAndLogIn(wc, tokensPath)) { return; } } List <ProductInfo> products = null; if (!(exportLinks && File.Exists(downloadsPath))) { if (!File.Exists(dbPath)) { products = DownloadInitial(wc); Console.Error.WriteLine("Saving database..."); using (StreamWriter sw = File.CreateText(dbPath)) { ProductInfo.SerializeCollection(products, sw); sw.Flush(); } } else { Console.Error.WriteLine("Loading database..."); using (StreamReader sr = File.OpenText(dbPath)) { products = ProductInfo.DeserializeCollection(sr); } } } List <DownloadsView> downloadsDb = null; if (products != null) { downloadsDb = DownloadsView.CreateCollectionFromProducts(products); } if (exportDownloads) { Console.Error.WriteLine("Exporting downloads database..."); using (StreamWriter sw = File.CreateText(downloadsPath)) { DownloadsView.SerializeCollection(downloadsDb, sw); sw.Flush(); } } if (exportKeys) { Console.Error.WriteLine("Exporting keys database..."); using (StreamWriter sw = File.CreateText(keysPath)) { KeysView.SerializeCollection(KeysView.CreateCollectionFromProducts(products, keysExportFilter), sw); sw.Flush(); } } if (exportLinks) { if (downloadsDb == null) { // Deserialize downloads DB Console.Error.WriteLine("Loading downloads database..."); using (StreamReader sr = File.OpenText(downloadsPath)) { downloadsDb = DownloadsView.DeserializeCollection(sr); } } List <string> links = GetCdnLinks(downloadsDb, wc, !omitLinksComments); Console.Error.WriteLine("Saving links to file..."); using (StreamWriter sw = File.CreateText(linksPath)) { foreach (string link in links) { sw.WriteLine(link); } sw.Flush(); } } Console.Error.WriteLine("Done."); } catch (Exception ex) { Console.Error.WriteLine("Error during processing: {0}", ex.Message); Console.Error.WriteLine(ex); } }