const std = @import("std");
const INPUTS_DIR = "inputs";
const SESSION_FILE = "session.txt";
pub const Options = struct {
year: usize,
days: usize,
};
pub fn fetchInputs(allocator: std.mem.Allocator, opts: Options) !void {
const cwd = std.fs.cwd();
cwd.makeDir(INPUTS_DIR) catch |err| {
switch (err) {
error.PathAlreadyExists => {},
else => return err,
}
};
const session = std.fs.cwd().readFileAlloc(allocator, SESSION_FILE, 256) catch |err| {
std.log.err("Unable to open '{s}'.\nMake sure to copy the session cookie value to this file to download the user specific input files.", .{SESSION_FILE});
return err;
};
for (1..opts.days + 1) |day| {
try fetchDay(allocator, opts, session, day);
}
}
fn fetchDay(allocator: std.mem.Allocator, opts: Options, session: []const u8, day: usize) !void {
var client = std.http.Client{ .allocator = allocator };
defer client.deinit();
std.debug.print("Downloading day{d:0>2}\r", .{day});
const url = try std.fmt.allocPrint(
allocator,
"https://adventofcode.com/{d}/day/{d}/input",
.{ opts.year, day },
);
const uri = try std.Uri.parse(url);
var headers = std.ArrayList(std.http.Header).init(allocator);
defer headers.deinit();
try headers.append(.{
.name = "Cookie",
.value = try std.fmt.allocPrint(allocator, "session={s}", .{session}),
});
var sh: [512]u8 = undefined;
var req = try client.open(.GET, uri, .{
.server_header_buffer = &sh,
.extra_headers = headers.items,
});
defer req.deinit();
try req.send(.{});
// try req.finish();
try req.wait();
if (req.response.status != std.http.Status.ok) return error.NotFound;
const reader = req.reader();
const input = try reader.readAllAlloc(allocator, 512 * 512);
defer allocator.free(input);
const file_name = try std.fmt.allocPrint(allocator, "{s}/day{d:0>2}.txt", .{ INPUTS_DIR, day });
try std.fs.cwd().writeFile2(std.fs.Dir.WriteFileOptions{
.sub_path = file_name,
.data = input,
.flags = .{ .mode = 0o644 },
});
}
pub fn checkInputs(days: usize) bool {
const cwd = std.fs.cwd();
const inputs = cwd.openDir(INPUTS_DIR, std.fs.Dir.OpenDirOptions{
.iterate = true,
}) catch {
return false;
};
var counter: usize = 0;
var it = inputs.iterate();
while (it.next() catch unreachable) |_| : (counter += 1) {}
if (counter == days) return true else return false;
}