Skip to content

Commit 2260524

Browse files
committed
Refactor and update disclaimers (including user-agent header info)
1 parent 20ab685 commit 2260524

File tree

5 files changed

+109
-59
lines changed

5 files changed

+109
-59
lines changed

README.md

+16-4
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,28 @@ If you're like me and you don't want to copy and paste puzzle input from the web
99
There are other CLI tools that accomplish the same task, none I could see for Neovim. Inspirations include:
1010

1111
- [CLI written in Rust](https://github.com/scarvalhojr/aoc-cli)
12-
- [CLI written in Python](https://github.com/emilkloeden/aoc-cli-python)
12+
- [CLI written in Python](https://github.com/wimglenn/advent-of-code-data)
1313

1414
I'd like to stay within Neovim for as long as I could possibly get away with doing so. Hence, this plugin.
1515

1616
In the true developer fashion, I started with one task to solve Advent of Code puzzles, I ended up talking myself into "Let's spend a day or two to write a tool that saves me ... 5s of copy and paste task". Here we are.
1717

18+
19+
## Disclaimer
20+
21+
This plugin follows the automation guidelines on the `r/adventofcode` [community wiki](https://www.reddit.com/r/adventofcode/wiki/faqs/automation).
22+
23+
Specifically:
24+
25+
- Outbound calls are throttled to every 5 minutes.
26+
- Once inputs are downloaded, they are cached locally.
27+
- If you suspect your input is corrupted, you can manually clear cache and request new input with `:AocClearCache`
28+
- The User-Agent header used in HTTP requests is set to me since I maintain this tool.
29+
1830
### Other features in the work
1931

2032
There are a number of features I'd like to add in the coming days/weeks to get to v1.0.0
2133

22-
- `:AocSubmitAnswer` to submit your answer.
2334
- `:AocGetSampleInput` to write puzzle's sample input to file.
2435
- `:AocYankSampleInput` to yank a puzzle's sample input to a register.
2536

@@ -50,7 +61,7 @@ return {
5061
},
5162
```
5263

53-
Should you want to lazy load this plugin, you could add a condition check in its config:
64+
Should you want to lazy load this plugin, you could add a condition check in its config like so:
5465

5566
``` lua
5667
cond = vim.fn.getcwd() == vim.fn.expand("your AOC directory path"),
@@ -65,7 +76,8 @@ local default_opts = {
6576
session_filepath = "/var/tmp/aoc.txt", -- Default filepath to your AOC session token
6677
puzzle_input = {
6778
filename = "puzzle.txt", -- Default puzzle input filename
68-
save_to_current_dir = true, -- Save puzzle input file to your current buffer's cwd() using {filename} attribute above
79+
save_to_current_dir = true, -- Save puzzle input file to your current buffer's cwd()
80+
-- using {filename} attribute listed above.
6981
alternative_filepath = nil, -- This option is ONLY used when save_to_current_dir is set to false
7082
-- This option allows you to set a generic filepath for your puzzle input
7183
-- For example: ~/aoc/input.txt or ~/aoc/puzzle ...

lua/aoc/api.lua

+28-37
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
local inspect = require "vim.inspect"
12
local cache = require "aoc.cache"
23
local curl = require "plenary.curl"
34
local cfg = require "aoc.config"
45

56
---@class APIWrapper
67
local M = {}
8+
M.session_id = nil
9+
M.user_agent = "github.com/csessh/aoc.nvim by csessh@hey.com"
710

811
---@param day string|osdate
912
---@param year string|osdate
@@ -34,6 +37,25 @@ local validate_args = function(day, year)
3437
return true
3538
end
3639

40+
---Load session token from file
41+
---@return string?
42+
local get_session_id = function()
43+
if M.session_id then
44+
return M.session_id
45+
end
46+
47+
local f = io.open(cfg.options.session_filepath, "r")
48+
if not f then
49+
return nil
50+
end
51+
52+
local sid = f:read "*a"
53+
M.session_id = sid
54+
f:close()
55+
56+
return sid
57+
end
58+
3759
-- Effectively send a curl request like so:
3860
-- curl -X GET https://adventofcode.com/{year}/day/{day}/input -H "Cookie: session={session_token_path}"
3961
-- Always check and validate cache before sending out requests. It's best to polite.
@@ -50,59 +72,28 @@ M.save_puzzle_input = function(day, year)
5072
local content = cf:read "*a"
5173
cf:close()
5274

53-
local f = io.open(vim.uv.cwd() .. "/" .. cfg.options.puzzle_input.filename, "w")
54-
if not f then
55-
vim.api.nvim_err_writeln("Unable to write puzzle input to file at " .. cfg.options.puzzle_input.filename)
56-
return
57-
end
58-
59-
f:write(content)
60-
f:close()
61-
62-
vim.notify("Successfully retrieved puzzle input for Day " .. day .. " (" .. year .. ")")
75+
cache.write_to_file(day, year, content)
6376
return
6477
end
6578

6679
-- Proceed to send GET request to AOC server for the puzzle input
67-
local f = io.open(cfg.options.session_filepath, "r")
68-
if not f then
80+
local sid = get_session_id()
81+
if not sid then
6982
vim.api.nvim_err_writeln "Advent Of Code session token is missing. See :help aoc.nvim-requirements"
7083
return
7184
end
7285

73-
local sid = f:read "*a"
74-
f:close()
75-
7686
local response = curl.get {
7787
url = "https://adventofcode.com/" .. year .. "/day/" .. day .. "/input",
7888
headers = {
7989
cookie = "session=" .. sid,
90+
user_agent = M.user_agent,
8091
},
8192
}
8293

8394
if response.status == 200 then
84-
-- Cache the puzzle input for future use
85-
cache.write(day, year, response.body)
86-
87-
-- Write puzzle input to user's cwd() or where they specify it otherwise
88-
local filename = ""
89-
if cfg.options.puzzle_input.save_to_current_dir then
90-
filename = vim.uv.cwd() .. "/" .. cfg.options.puzzle_input.filename
91-
else
92-
filename = cfg.options.puzzle_input.alternative_filepath
93-
end
94-
95-
---@diagnostic disable-next-line: param-type-mismatch
96-
f = io.open(filename, "w")
97-
if not f then
98-
vim.api.nvim_err_writeln("Unable to write puzzle input to file at " .. filename)
99-
return
100-
end
101-
102-
f:write(response.body)
103-
f:close()
104-
105-
vim.notify("Successfully downloaded puzzle input for Day " .. day .. " (" .. year .. ")")
95+
cache.write_to_cache(day, year, response.body)
96+
cache.write_to_file(day, year, response.body)
10697
else
10798
vim.api.nvim_err_writeln(response.body)
10899
end

lua/aoc/cache.lua

+28-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
local cfg = require "aoc.config"
2+
13
---@class PuzzleCache
24
local M = {}
35

@@ -35,8 +37,7 @@ end
3537
---Write cached content to file
3638
---@param day string|osdate
3739
---@param year string|osdate
38-
---@return boolean
39-
M.write = function(day, year, content)
40+
M.write_to_cache = function(day, year, content)
4041
-- Create a cache directory if one doesn't exist
4142
-- Quite a clevery hacky way to check if a directory exists without relying on external packages
4243
local ok, err = os.rename(cache_path, cache_path)
@@ -49,13 +50,35 @@ M.write = function(day, year, content)
4950
local f = io.open(filename, "w")
5051
if not f then
5152
vim.api.nvim_err_writeln("Unable to write puzzle input to cache at " .. filename)
52-
return false
53+
else
54+
f:write(content)
5355
end
5456

55-
f:write(content)
5657
f:close()
58+
end
5759

58-
return true
60+
---Write puzzle input to user's cwd() or where they specify it otherwise
61+
---@param day string|osdate
62+
---@param year string|osdate
63+
---@param content string
64+
M.write_to_file = function(day, year, content)
65+
local filename = ""
66+
if cfg.options.puzzle_input.save_to_current_dir then
67+
filename = vim.uv.cwd() .. "/" .. cfg.options.puzzle_input.filename
68+
else
69+
filename = cfg.options.puzzle_input.alternative_filepath
70+
end
71+
72+
---@diagnostic disable-next-line: param-type-mismatch
73+
local f = io.open(filename, "w")
74+
if not f then
75+
vim.api.nvim_err_writeln("Unable to write puzzle input to file at " .. filename)
76+
else
77+
f:write(content)
78+
f:close()
79+
end
80+
81+
vim.notify("Successfully downloaded puzzle input for Day " .. day .. " (" .. year .. ")")
5982
end
6083

6184
return M

lua/aoc/init.lua

+26-10
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
local api = require "aoc.api"
22
local cfg = require "aoc.config"
33
local cache = require "aoc.cache"
4+
local utils = require "aoc.utils"
45

56
---@class AOC
67
local M = {}
78

8-
---Strip input of any leading/trailing spaces
9-
---@param s string
10-
---@return string
11-
local trim = function(s)
12-
s, _ = string.gsub(s, "%s+", "")
13-
return s
14-
end
15-
169
---@param args any
1710
M.setup = function(args)
1811
cfg.init(args)
@@ -22,8 +15,8 @@ M.setup = function(args)
2215
local year = vim.fn.input "Year: "
2316
vim.api.nvim_out_write "\n"
2417

25-
day = trim(day)
26-
year = trim(year)
18+
day = utils.trim(day)
19+
year = utils.trim(year)
2720
api.save_puzzle_input(day, year)
2821
end, {})
2922

@@ -34,6 +27,29 @@ M.setup = function(args)
3427
api.save_puzzle_input(day, year)
3528
end, {})
3629

30+
vim.api.nvim_create_user_command("AocSubmitAnswer", function()
31+
local day = vim.fn.input "Day: "
32+
local year = vim.fn.input "Year: "
33+
local answer = vim.fn.input "Answer: "
34+
vim.api.nvim_out_write "\n"
35+
36+
day = utils.trim(day)
37+
year = utils.trim(year)
38+
answer = utils.trim(answer)
39+
40+
api.submit_answer(day, year, answer)
41+
end, {})
42+
43+
vim.api.nvim_create_user_command("AocSubmitTodayAnswer", function()
44+
local day = os.date "%d"
45+
local year = os.date "%Y"
46+
47+
local answer = vim.fn.input "Answer: "
48+
vim.api.nvim_out_write "\n"
49+
50+
api.submit_answer(day, year, answer)
51+
end, {})
52+
3753
vim.api.nvim_create_user_command("AocClearCache", cache.clear_cache, {})
3854
vim.api.nvim_create_user_command("AocInspectConfig", cfg.debug, {})
3955
end

lua/aoc/notification.lua lua/aoc/utils.lua

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
---@class Notification
1+
---@class Utility
22
local M = {}
33

4+
---Strip a string of any leading/trailing spaces
5+
---@param s string
6+
---@return string
7+
M.trim = function(s)
8+
s, _ = string.gsub(s, "%s+", "")
9+
return s
10+
end
11+
412
--- Create a simple popup message, positioned in the bottom right corner of the buffer
513
--- Automatically close this popup after timeout_ms milliseconds
614
---@param message string
7-
---@param timeout_ms number
8-
M.show = function(message, timeout_ms)
15+
---@param timeout_ms integer
16+
M.popup = function(message, timeout_ms)
917
local width = #message
1018
local height = 1
1119
local buf = vim.api.nvim_create_buf(false, true)

0 commit comments

Comments
 (0)