about summary refs log tree commit diff stats
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rw-r--r--bin/dune4
-rw-r--r--bin/main.ml41
-rw-r--r--bin/utils.ml51
3 files changed, 96 insertions, 0 deletions
diff --git a/bin/dune b/bin/dune
new file mode 100644
index 0000000..7f1bcd1
--- /dev/null
+++ b/bin/dune
@@ -0,0 +1,4 @@
+(executable
+ (public_name aoc)
+ (name main)
+ (libraries cohttp-lwt-unix lwt_ssl aoc))
diff --git a/bin/main.ml b/bin/main.ml
new file mode 100644
index 0000000..8e36c28
--- /dev/null
+++ b/bin/main.ml
@@ -0,0 +1,41 @@
+open Aoc
+open Utils
+
+let () =
+  let args = Sys.argv in
+  let day = args.(1) in
+  let input_file = Printf.sprintf "inputs/%s.in" day in
+  if not @@ Caml.Sys.file_exists input_file then
+    download_input day input_file ;
+  let file = In_channel.open_text input_file in
+  let inputs = In_channel.input_all file in
+  let (module Day : Day.S) =
+    match day with
+    | "1" -> (module Day1)
+    | "2" -> (module Day2)
+    | "3" -> (module Day3)
+    | "4" -> (module Day4)
+    | "5" -> (module Day5)
+    | "6" -> (module Day6)
+    | "7" -> (module Day7)
+    | "8" -> (module Day8)
+    | "9" -> (module Day9)
+    | "10" -> (module Day10)
+    | "11" -> (module Day11)
+    | "12" -> (module Day12)
+    | "13" -> (module Day13)
+    | "14" -> (module Day14)
+    | "15" -> (module Day15)
+    | "16" -> (module Day16)
+    | "17" -> (module Day17)
+    | "18" -> (module Day18)
+    | "19" -> (module Day19)
+    | "20" -> (module Day20)
+    | "21" -> (module Day21)
+    | "22" -> (module Day22)
+    | "23" -> (module Day23)
+    | "24" -> (module Day24)
+    | "25" -> (module Day25)
+    | _ -> failwith "invalid day"
+  in
+  Day.run inputs ; In_channel.close file
diff --git a/bin/utils.ml b/bin/utils.ml
new file mode 100644
index 0000000..4f488f4
--- /dev/null
+++ b/bin/utils.ml
@@ -0,0 +1,51 @@
+open Unix
+open Lwt
+open Cohttp
+open Cohttp_lwt_unix
+
+let session_file = ".session"
+
+let year_file = ".year"
+
+let get_token () =
+  let file = In_channel.open_text session_file in
+  let token = In_channel.input_all file in
+  In_channel.close file ; String.trim token
+
+let get_year () =
+  if Caml.Sys.file_exists year_file then (
+    let file = In_channel.open_text year_file in
+    let year = In_channel.input_all file in
+    In_channel.close file ;
+    int_of_string (String.trim year) )
+  else
+    let time = time () in
+    let time = gmtime time in
+    time.tm_year + 1900
+
+let download_input day fn =
+  let year = get_year () in
+  let url =
+    Printf.sprintf "https://adventofcode.com/%d/day/%s/input" year day
+  in
+  let token = get_token () in
+  let headers = Header.init () in
+  let headers = Header.add headers "Cookie" ("session=" ^ token) in
+  let headers =
+    Header.add headers "User-Agent"
+      "github.com/fangyi-zhou/advent-of-code-ocaml-starter by \
+       me+aoc@fangyi.io"
+  in
+  let uri = Uri.of_string url in
+  let body =
+    Client.get ~headers uri
+    >>= fun (resp, body) ->
+    let code = resp |> Response.status |> Code.code_of_status in
+    if code = 200 then body |> Cohttp_lwt.Body.to_string
+    else failwith ("Unable to get data, status " ^ Int.to_string code)
+  in
+  let body = Lwt_main.run body in
+  let body = String.trim body in
+  let file = Out_channel.open_text fn in
+  Out_channel.output_string file body ;
+  Out_channel.close file