using System; using System.IO; using System.Net.Http; using System.Linq; namespace AdventOfCode.InputFetcher { class Program { private static readonly string AdventOfCodeEndpoint = "https://adventofcode.com/{YEAR}/day"; private static HttpClient _client; static void Main(string[] args) { Console.WriteLine("Please select your year! Default: 2023"); var year = SanitizeInput(Console.ReadLine(), "2023"); Console.WriteLine("Please enter your session key for advent of code:"); var sessionKey = Console.ReadLine(); Console.WriteLine("Please input the target directory for the input files! Default: Current working directory"); var targetDir = SanitizeInput(Console.ReadLine(), Directory.GetCurrentDirectory()); Console.WriteLine("File Name Format? Default: \"{YEAR}_{TYPE}_Day_{DAY}{PART}.txt\" => 2022_Input_Day_1.txt or 2022_Answer_Day_1-PartB"); var format = SanitizeInput(Console.ReadLine(), "{YEAR}_{TYPE}_Day_{DAY}{PART}.txt"); Console.WriteLine("Pull Answers? (Y/N) Default: Y"); var answer = SanitizeInput(Console.ReadLine(), "Y"); Console.WriteLine("Overwrite? (Y/N) Default: N"); var overwrite = SanitizeInput(Console.ReadLine(), "N"); _client = new HttpClient(); _client.DefaultRequestHeaders.Add("Cookie", $"session={sessionKey}"); var filesOnDisk = new DirectoryInfo(targetDir); for (int day = 1; day <= 25; day++) { var dataFileName = format.Replace("{DAY}", day.ToString()).Replace("{TYPE}", "Input").Replace("{PART}", "").Replace("{YEAR}", year); var answerFileNameA = format.Replace("{DAY}", day.ToString()).Replace("{TYPE}", "Answer").Replace("{PART}", "A").Replace("{YEAR}", year); var answerFileNameB = format.Replace("{DAY}", day.ToString()).Replace("{TYPE}", "Answer").Replace("{PART}", "B").Replace("{YEAR}", year); bool dataFileExistsOnDisk = filesOnDisk.EnumerateFiles().Any(x => x.Name == dataFileName); if (!dataFileExistsOnDisk || (overwrite.ToUpper() == "Y")) { try { File.WriteAllText(targetDir + Path.DirectorySeparatorChar + dataFileName, PullDataForDay(year, day)); }catch(FileNotFoundException e) { //Input data not available yet continue; } } if (answer.ToUpper() == "Y") { bool answerFileAExistsOnDisk = filesOnDisk.EnumerateFiles().Any(x => x.Name == answerFileNameA); bool answerFileBExistsOnDisk = filesOnDisk.EnumerateFiles().Any(x => x.Name == answerFileNameB); if ((!answerFileBExistsOnDisk && !answerFileBExistsOnDisk) || (overwrite.ToUpper() == "Y")) { var answers = PullAnswerForDay(year, day); if (!string.IsNullOrWhiteSpace(answers.Item1)) File.WriteAllText(targetDir + Path.DirectorySeparatorChar + answerFileNameA, answers.Item1); if (!string.IsNullOrWhiteSpace(answers.Item2)) File.WriteAllText(targetDir + Path.DirectorySeparatorChar + answerFileNameB, answers.Item2); } } } } private static string PullDataForDay(string year, int day) { return ExecuteWebRequest(string.Format("{0}/{1}/input", AdventOfCodeEndpoint.Replace("{YEAR}", year), day)); } private static readonly string SearchString = "Your puzzle answer was"; private static Tuple PullAnswerForDay(string year, int day) { var html = ExecuteWebRequest(string.Format("{0}/{1}", AdventOfCodeEndpoint.Replace("{YEAR}", year), day)); var answerStart = html.IndexOf(SearchString); if (answerStart < 0) return Tuple.Create("", ""); var startingIndex = html.IndexOf("", answerStart) + "".Length; var endIndex = html.IndexOf("", answerStart); var partA = startingIndex < 0 || endIndex < 0 ? "No Answer Found yet." : html.Substring(startingIndex, (endIndex-startingIndex)); html = html.Substring(endIndex + 1); answerStart = html.IndexOf(SearchString); startingIndex = html.IndexOf("", answerStart) + "".Length; endIndex = html.IndexOf("", answerStart); var partB = startingIndex < 0 || endIndex < 0 ? "No Answer Found yet." : html.Substring(startingIndex, (endIndex - startingIndex)); return Tuple.Create(partA, partB); } private static string ExecuteWebRequest(string url) { var resp = _client.GetAsync(url).Result; if (resp.StatusCode == System.Net.HttpStatusCode.NotFound) throw new FileNotFoundException("No day input was found!"); return resp.Content.ReadAsStringAsync().Result; } private static string SanitizeInput(string input, string defaultText) { if (string.IsNullOrWhiteSpace(input)) return defaultText; return input; } } }