Copyright | (c) Justin Le 2019 |
---|---|
License | BSD3 |
Maintainer | justin@jle.im |
Stability | experimental |
Portability | non-portable |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
Haskell bindings for Advent of Code 2018 API. Caches and throttles requests automatically.
Specify your requests with AoC
and AoCOpts
, and run them with
runAoC
.
Examples:
-- Fetch prompts for day 5runAoC
myOpts $AoCPrompt
(mkDay_
5) -- Fetch input for day 8runAoC
myOpts $AoCInput
(mkDay_
8) -- Submit answer "hello" for Day 10, Part 1runAoC
myOpts $AoCSubmit
(mkDay_
10)Part1
"hello"
Please use responsibly. All actions are by default rate limited to one per three seconds, but this can be adjusted to a hard-limited cap of one per second.
Synopsis
- data AoC :: Type -> Type where
- AoCPrompt :: Day -> AoC (Map Part Text)
- AoCInput :: Day -> AoC Text
- AoCSubmit :: Day -> Part -> String -> AoC (Text, SubmitRes)
- AoCLeaderboard :: Integer -> AoC Leaderboard
- AoCDailyLeaderboard :: Day -> AoC DailyLeaderboard
- AoCGlobalLeaderboard :: AoC GlobalLeaderboard
- AoCNextDayTime :: AoC NextDayTime
- data Part
- newtype Day = Day {}
- data NextDayTime
- data AoCOpts = AoCOpts {}
- data SubmitRes
- = SubCorrect (Maybe Integer)
- | SubIncorrect Int (Maybe String)
- | SubWait Int
- | SubInvalid
- | SubUnknown String
- showSubmitRes :: SubmitRes -> String
- runAoC :: AoCOpts -> AoC a -> IO (Either AoCError a)
- runAoC_ :: AoCOpts -> AoC a -> IO a
- defaultAoCOpts :: Integer -> String -> AoCOpts
- data AoCError
- challengeReleaseTime :: Integer -> Day -> ZonedTime
- timeToRelease :: Integer -> Day -> IO NominalDiffTime
- challengeReleased :: Integer -> Day -> IO Bool
- mkDay :: Integer -> Maybe Day
- mkDay_ :: Integer -> Day
- dayInt :: Day -> Integer
- pattern DayInt :: Day -> Integer
- _DayInt :: (Choice p, Applicative f) => p Day (f Day) -> p Integer (f Integer)
- aocDay :: AoC a -> Maybe Day
- aocServerTime :: IO LocalTime
- partChar :: Part -> Char
- partInt :: Part -> Int
- fullDailyBoard :: DailyLeaderboard -> Bool
- setAoCThrottleLimit :: Int -> IO ()
- getAoCThrottleLimit :: IO Int
- aocReq :: Integer -> AoC a -> ClientM a
- aocBase :: BaseUrl
API
data AoC :: Type -> Type where Source #
An API command. An
an AoC API request that returns
results of type AoC
aa
.
A lot of these commands take Day
, which represents a day of December
up to and including Christmas Day (December 25th). You can convert an
integer day (1 - 25) into a Day
using mkDay
or mkDay_
.
AoCPrompt :: Day -> AoC (Map Part Text) | Fetch prompts for a given day. Returns a _Cacheing rules_: Is cached on a per-day basis. An empty session key is given, it will be happy with only having Part 1 cached. If a non-empty session key is given, it will trigger a cache invalidation on every request until both Part 1 and Part 2 are received. |
AoCInput :: Day -> AoC Text | Fetch input, as plaintext. Returned verbatim. Be aware that input might contain trailing newlines. Cacheing rules: Is cached forever, per day per session key. |
AoCSubmit :: Day -> Part -> String -> AoC (Text, SubmitRes) | Submit a plaintext answer (the WARNING: Answers are not length-limited. Answers are stripped
of leading and trailing whitespace and run through Cacheing rules: Is never cached. |
AoCLeaderboard :: Integer -> AoC Leaderboard | Fetch the leaderboard for a given leaderboard public code (owner member ID). Requires session key. The public code can be found in the URL of the leaderboard: https://adventofcode.com/2019/leaderboard/private/view/12345 (the NOTE: This is the most expensive and taxing possible API call, and makes up the majority of bandwidth to the Advent of Code servers. As a courtesy to all who are participating in Advent of Code, please use this super respectfully, especially in December: if you set up automation for this, please do not use it more than once per day. Cacheing rules: Is never cached, so please use responsibly (see note above). Since: 0.2.0.0 |
AoCDailyLeaderboard :: Day -> AoC DailyLeaderboard | Fetch the daily leaderboard for a given day. Does not require a session key. Leaderboard API calls tend to be expensive, so please be respectful when using this. If you automate this, please do not fetch any more often than necessary. Cacheing rules: Will be cached if a full leaderboard is observed. Since: 0.2.3.0 |
AoCGlobalLeaderboard :: AoC GlobalLeaderboard | Fetch the global leaderboard. Does not require a session key. Leaderboard API calls tend to be expensive, so please be respectful when using this. If you automate this, please do not fetch any more often than necessary. Cacheing rules: Will not cache if an event is ongoing, but will be cached if received after the event is over. Since: 0.2.3.0 |
AoCNextDayTime :: AoC NextDayTime | From the calendar, fetch the next release's day and the number of seconds util its release, if there is any at all. This does an actual request to the AoC servers, and is only accurate
to the second; to infer this information (to the millisecond level)
from the system clock, you should probably use Since: 0.2.8.0 |
A given part of a problem. All Advent of Code challenges are two-parts.
You can usually get Part1
(if it is already released) with a nonsense
session key, but Part2
always requires a valid session key.
Instances
FromJSON Part Source # | |
FromJSONKey Part Source # | |
Defined in Advent.Types | |
ToJSON Part Source # | Since: 0.2.4.2 |
Defined in Advent.Types | |
ToJSONKey Part Source # | Since: 0.2.4.2 |
Defined in Advent.Types | |
Bounded Part Source # | |
Enum Part Source # | |
Generic Part Source # | |
Read Part Source # | |
Show Part Source # | |
Eq Part Source # | |
Ord Part Source # | |
ToHttpApiData Part Source # | |
Defined in Advent.Types toUrlPiece :: Part -> Text # toEncodedUrlPiece :: Part -> Builder # toHeader :: Part -> ByteString # toQueryParam :: Part -> Text # toEncodedQueryParam :: Part -> Builder # | |
type Rep Part Source # | |
Describes the day: a number between 1 and 25 inclusive.
Represented by a Finite
ranging from 0 to 24 inclusive; you should
probably make one using the smart constructor mkDay
.
Instances
FromJSON Day Source # | |
FromJSONKey Day Source # | |
Defined in Advent.Types | |
ToJSON Day Source # | Since: 0.2.4.2 |
Defined in Advent.Types | |
ToJSONKey Day Source # | Since: 0.2.4.2 |
Defined in Advent.Types | |
Bounded Day Source # | |
Enum Day Source # | |
Generic Day Source # | |
Show Day Source # | |
Eq Day Source # | |
Ord Day Source # | |
ToHttpApiData Day Source # | |
Defined in Advent.Types toUrlPiece :: Day -> Text # toEncodedUrlPiece :: Day -> Builder # toHeader :: Day -> ByteString # toQueryParam :: Day -> Text # toEncodedQueryParam :: Day -> Builder # | |
type Rep Day Source # | |
Defined in Advent.Types |
data NextDayTime Source #
The next day for a challenge in a given year, and also the number of seconds until the challenge is released.
Since: 0.2.8.0
Instances
Setings for running an API request.
Session keys are required for all commands, but if you enter a bogus key
you should be able to get at least Part 1 from AoCPrompt
.
The session key can be found by logging in on a web client and checking the cookies. You can usually check these with in-browser developer tools.
Throttling is hard-limited to a minimum of 1 second between calls. Please be respectful and do not try to bypass this.
AoCOpts | |
|
Instances
Generic AoCOpts Source # | |
Show AoCOpts Source # | |
type Rep AoCOpts Source # | |
Defined in Advent type Rep AoCOpts = D1 ('MetaData "AoCOpts" "Advent" "advent-of-code-api-0.2.8.5-FaFBzvb1hJk3a2yu8byIsn" 'False) (C1 ('MetaCons "AoCOpts" 'PrefixI 'True) ((S1 ('MetaSel ('Just "_aSessionKey") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 String) :*: S1 ('MetaSel ('Just "_aYear") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Integer)) :*: (S1 ('MetaSel ('Just "_aCache") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe FilePath)) :*: (S1 ('MetaSel ('Just "_aForce") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Bool) :*: S1 ('MetaSel ('Just "_aThrottle") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int))))) |
The result of a submission.
SubCorrect (Maybe Integer) | Correct submission, including global rank (if reported, which usually happens if rank is under 1000) |
SubIncorrect Int (Maybe String) | Incorrect submission. Contains the number of seconds you must
wait before trying again. The |
SubWait Int | Submission was rejected because an incorrect submission was recently submitted. Contains the number of seconds you must wait before trying again. |
SubInvalid | Submission was rejected because it was sent to an invalid question or part. Usually happens if you submit to a part you have already answered or have not yet unlocked. |
SubUnknown String | Could not parse server response. Contains parse error. |
Instances
defaultAoCOpts :: Integer -> String -> AoCOpts Source #
Sensible defaults for AoCOpts
for a given year and session key.
Use system temporary directory as cache, and throttle requests to one request per three seconds.
A possible (syncronous, logical, pure) error returnable from runAoC
.
Does not cover any asynchronous or IO errors.
AoCClientError ClientError | An error in the http request itself Note that if you are building this with servant-client-core <= 0.16,
this will contain |
AoCReleaseError NominalDiffTime | Tried to interact with a challenge that has not yet been released. Contains the amount of time until release. |
AoCThrottleError | The throttler limit is full. Either make less requests, or adjust
it with |
Instances
Exception AoCError Source # | |
Defined in Advent toException :: AoCError -> SomeException # fromException :: SomeException -> Maybe AoCError # displayException :: AoCError -> String # | |
Generic AoCError Source # | |
Show AoCError Source # | |
type Rep AoCError Source # | |
Defined in Advent type Rep AoCError = D1 ('MetaData "AoCError" "Advent" "advent-of-code-api-0.2.8.5-FaFBzvb1hJk3a2yu8byIsn" 'False) (C1 ('MetaCons "AoCClientError" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ClientError)) :+: (C1 ('MetaCons "AoCReleaseError" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 NominalDiffTime)) :+: C1 ('MetaCons "AoCThrottleError" 'PrefixI 'False) (U1 :: Type -> Type))) |
Calendar
Prompt release time.
Changed from UTCTime
to ZonedTime
in v0.2.7.0. To use as
a UTCTime
, use zonedTimeToUTC
.
:: Integer | year |
-> Day | day |
-> IO NominalDiffTime |
Get time until release of a given challenge.
Check if a challenge has been released yet.
Utility
Day
aocDay :: AoC a -> Maybe Day Source #
Get the day associated with a given API command, if there is one.
aocServerTime :: IO LocalTime Source #
Utility to get the current time on AoC servers. Basically just gets the current time in Eastern Standard Time. This is only as accurate as your machine's actual time --- it doesn't actually do anything networked.
Since: 0.2.6.0
Part
Leaderboard
fullDailyBoard :: DailyLeaderboard -> Bool Source #
Check if a DailyLeaderboard
is filled up or not.
Since: 0.2.4.0
Throttler
setAoCThrottleLimit :: Int -> IO () Source #
Set the internal throttler maximum queue capacity. Default is 100.
getAoCThrottleLimit :: IO Int Source #
Get the internal throttler maximum queue capacity.