|
|
|
|
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<string, string> 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("<code>", answerStart) + "<code>".Length;
|
|
|
|
|
var endIndex = html.IndexOf("</code>", 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("<code>", answerStart) + "<code>".Length;
|
|
|
|
|
endIndex = html.IndexOf("</code>", 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|