private static async Task <bool> RunAsync(CommandLineArgs args) { using (var scraper = new EndomondoScraper(args.UserToken)) { // Scrape user id from endoConfig. var userId = await scraper.GetUserIdAsync(); if (!userId.HasValue) { Console.Error.WriteLine("Cannot get Endomondo user id. Is your USER_TOKEN still valid? Try again with a new one."); return(false); } Console.WriteLine($"Found account id: {userId}"); int offset = 0; while (true) { // Scrape history from API. Console.Error.WriteLine($"Processing workouts from offset={offset}"); var history = await scraper.GetHistoryAsync(userId.Value, offset, 100); offset += 100; if (history?.Data == null || !history.Data.Any()) { Console.Error.WriteLine("No more workouts found."); return(true); } Console.WriteLine($"Found {history.Data.Count} workouts."); // Slowly, synchronously scrape workouts. Not doing any parallel work as seems to trigger 429 responses. foreach (var item in history.Data) { foreach (var format in args.GetFormats()) { var fileName = $"{item.Id}.{format}"; Console.Write($" -> saving {fileName} ({item.LocalStartTime}) -> "); if (File.Exists(fileName)) { Console.WriteLine("already exists."); continue; } using (var data = await scraper.GetWorkout(userId.Value, item.Id, format)) using (var file = File.OpenWrite(fileName)) { await data.Stream.CopyToAsync(file); Console.WriteLine(data.Length.Bytes()); } } } } } }