advent-of-code-api 0.2.8.5 → 0.2.9.0
raw patch · 4 files changed
+53/−19 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Advent: [_aUserAgent] :: AoCOpts -> AoCUserAgent
+ Advent.API: AoCUserAgent :: Text -> Text -> AoCUserAgent
+ Advent.API: [_auaEmail] :: AoCUserAgent -> Text
+ Advent.API: [_auaRepo] :: AoCUserAgent -> Text
+ Advent.API: data AoCUserAgent
+ Advent.API: instance GHC.Show.Show Advent.API.AoCUserAgent
+ Advent.API: instance Web.Internal.HttpApiData.ToHttpApiData Advent.API.AoCUserAgent
- Advent: AoCOpts :: String -> Integer -> Maybe FilePath -> Bool -> Int -> AoCOpts
+ Advent: AoCOpts :: String -> Integer -> AoCUserAgent -> Maybe FilePath -> Bool -> Int -> AoCOpts
- Advent: aocReq :: Integer -> AoC a -> ClientM a
+ Advent: aocReq :: Maybe AoCUserAgent -> Integer -> AoC a -> ClientM a
- Advent: defaultAoCOpts :: Integer -> String -> AoCOpts
+ Advent: defaultAoCOpts :: AoCUserAgent -> Integer -> String -> AoCOpts
- Advent.API: adventAPIClient :: Integer -> ClientM NextDayTime :<|> ((Day -> ClientM (Map Part Text) :<|> (ClientM Text :<|> (SubmitInfo -> ClientM (Text :<|> SubmitRes)))) :<|> (ClientM GlobalLeaderboard :<|> ((Day -> ClientM DailyLeaderboard) :<|> (PublicCode -> ClientM Leaderboard))))
+ Advent.API: adventAPIClient :: Maybe AoCUserAgent -> Integer -> ClientM NextDayTime :<|> ((Day -> ClientM (Map Part Text) :<|> (ClientM Text :<|> (SubmitInfo -> ClientM (Text :<|> SubmitRes)))) :<|> (ClientM GlobalLeaderboard :<|> ((Day -> ClientM DailyLeaderboard) :<|> (PublicCode -> ClientM Leaderboard))))
- Advent.API: adventAPIPuzzleClient :: Integer -> Day -> ClientM (Map Part Text) :<|> (ClientM Text :<|> (SubmitInfo -> ClientM (Text :<|> SubmitRes)))
+ Advent.API: adventAPIPuzzleClient :: Maybe AoCUserAgent -> Integer -> Day -> ClientM (Map Part Text) :<|> (ClientM Text :<|> (SubmitInfo -> ClientM (Text :<|> SubmitRes)))
- Advent.API: type AdventAPI = Capture "year" Integer :> (Get '[Scripts] NextDayTime :<|> "day" :> Capture "day" Day :> (Get '[Articles] (Map Part Text) :<|> "input" :> Get '[RawText] Text :<|> "answer" :> ReqBody '[FormUrlEncoded] SubmitInfo :> Post '[Articles] (Text :<|> SubmitRes)) :<|> ("leaderboard" :> (Get '[Divs] GlobalLeaderboard :<|> "day" :> Capture "day" Day :> Get '[Divs] DailyLeaderboard :<|> "private" :> "view" :> Capture "code" PublicCode :> Get '[JSON] Leaderboard)))
+ Advent.API: type AdventAPI = Header "User-Agent" AoCUserAgent :> Capture "year" Integer :> (Get '[Scripts] NextDayTime :<|> "day" :> Capture "day" Day :> (Get '[Articles] (Map Part Text) :<|> "input" :> Get '[RawText] Text :<|> "answer" :> ReqBody '[FormUrlEncoded] SubmitInfo :> Post '[Articles] (Text :<|> SubmitRes)) :<|> ("leaderboard" :> (Get '[Divs] GlobalLeaderboard :<|> "day" :> Capture "day" Day :> Get '[Divs] DailyLeaderboard :<|> "private" :> "view" :> Capture "code" PublicCode :> Get '[JSON] Leaderboard)))
Files
- CHANGELOG.md +13/−0
- advent-of-code-api.cabal +1/−1
- src/Advent.hs +19/−13
- src/Advent/API.hs +20/−5
CHANGELOG.md view
@@ -1,6 +1,19 @@ Changelog ========= +Version 0.2.9.0+---------------++*December 11, 2023*++<https://github.com/mstksg/advent-of-code-api/releases/tag/v0.2.9.0>++* All API requests now require providing a structured user agent data type,+ to follow+ <https://www.reddit.com/r/adventofcode/comments/z9dhtd/please_include_your_contact_info_in_the_useragent/>.+ This is not enforced in the raw servant API, but is enforced in the+ "regulated" `Advent` module.+ Version 0.2.8.5 ---------------
advent-of-code-api.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: advent-of-code-api-version: 0.2.8.5+version: 0.2.9.0 synopsis: Advent of Code REST API bindings and servant API description: Haskell bindings for Advent of Code REST API and a servant API. Please use responsibly! See README.md or "Advent" module for an introduction and
src/Advent.hs view
@@ -293,6 +293,9 @@ _aSessionKey :: String -- | Year of challenge , _aYear :: Integer+ -- | Structured user agent to use. See+ -- <https://www.reddit.com/r/adventofcode/comments/z9dhtd/please_include_your_contact_info_in_the_useragent/>+ , _aUserAgent :: AoCUserAgent -- | Cache directory. If 'Nothing' is given, one will be allocated -- using 'getTemporaryDirectory'. , _aCache :: Maybe FilePath@@ -305,17 +308,20 @@ } deriving (Show, Typeable, Generic) --- | Sensible defaults for 'AoCOpts' for a given year and session key.+-- | Sensible defaults for 'AoCOpts' for a given user agent, year and session+-- key. -- -- Use system temporary directory as cache, and throttle requests to one -- request per three seconds. defaultAoCOpts- :: Integer+ :: AoCUserAgent+ -> Integer -> String -> AoCOpts-defaultAoCOpts y s = AoCOpts+defaultAoCOpts aua y s = AoCOpts { _aSessionKey = s , _aYear = y+ , _aUserAgent = aua , _aCache = Nothing , _aForce = False , _aThrottle = 3000000@@ -326,19 +332,19 @@ aocBase = BaseUrl Https "adventofcode.com" 443 "" -- | 'ClientM' request for a given 'AoC' API call.-aocReq :: Integer -> AoC a -> ClientM a-aocReq yr = \case- AoCPrompt i -> let r :<|> _ = adventAPIPuzzleClient yr i in r- AoCInput i -> let _ :<|> r :<|> _ = adventAPIPuzzleClient yr i in r- AoCSubmit i p ans -> let _ :<|> _ :<|> r = adventAPIPuzzleClient yr i+aocReq :: Maybe AoCUserAgent -> Integer -> AoC a -> ClientM a+aocReq aua yr = \case+ AoCPrompt i -> let r :<|> _ = adventAPIPuzzleClient aua yr i in r+ AoCInput i -> let _ :<|> r :<|> _ = adventAPIPuzzleClient aua yr i in r+ AoCSubmit i p ans -> let _ :<|> _ :<|> r = adventAPIPuzzleClient aua yr i in r (SubmitInfo p ans) <&> \(x :<|> y) -> (x, y)- AoCLeaderboard c -> let _ :<|> _ :<|> _ :<|> _ :<|> r = adventAPIClient yr+ AoCLeaderboard c -> let _ :<|> _ :<|> _ :<|> _ :<|> r = adventAPIClient aua yr in r (PublicCode c)- AoCDailyLeaderboard d -> let _ :<|> _ :<|> _ :<|> r :<|> _ = adventAPIClient yr+ AoCDailyLeaderboard d -> let _ :<|> _ :<|> _ :<|> r :<|> _ = adventAPIClient aua yr in r d- AoCGlobalLeaderboard -> let _ :<|> _ :<|> r :<|> _ = adventAPIClient yr+ AoCGlobalLeaderboard -> let _ :<|> _ :<|> r :<|> _ = adventAPIClient aua yr in r- AoCNextDayTime -> let r :<|> _ = adventAPIClient yr+ AoCNextDayTime -> let r :<|> _ = adventAPIClient aua yr in r @@ -397,7 +403,7 @@ mtr <- liftIO . throttling aocThrottler (max 1000000 _aThrottle)- $ runClientM (aocReq _aYear a) =<< aocClientEnv _aSessionKey+ $ runClientM (aocReq (Just _aUserAgent) _aYear a) =<< aocClientEnv _aSessionKey mcr <- maybe (throwError AoCThrottleError) pure mtr either (throwError . AoCClientError) pure mcr
src/Advent/API.hs view
@@ -35,6 +35,7 @@ module Advent.API ( -- * Servant API AdventAPI+ , AoCUserAgent(..) , adventAPI , adventAPIClient , adventAPIPuzzleClient@@ -228,11 +229,23 @@ where t' = "var " <> t <> " = " +-- | A structured user agent, based on+-- <https://www.reddit.com/r/adventofcode/comments/z9dhtd/please_include_your_contact_info_in_the_useragent/>+data AoCUserAgent = AoCUserAgent+ { _auaRepo :: Text -- ^ repository where your code is hosted+ , _auaEmail :: Text -- ^ email address or contact+ }+ deriving (Show)++instance ToHttpApiData AoCUserAgent where+ toQueryParam AoCUserAgent{..} = _auaRepo <> " " <> _auaEmail+ -- | REST API of Advent of Code. -- -- Note that most of these requests assume a "session=" cookie. type AdventAPI =- Capture "year" Integer+ Header "User-Agent" AoCUserAgent+ :> Capture "year" Integer :> (Get '[Scripts] NextDayTime :<|> "day" :> Capture "day" Day :> (Get '[Articles] (Map Part Text)@@ -257,7 +270,8 @@ -- | 'ClientM' requests based on 'AdventAPI', generated by servant. adventAPIClient- :: Integer+ :: Maybe AoCUserAgent+ -> Integer -> ClientM NextDayTime :<|> (Day -> ClientM (Map Part Text) :<|> ClientM Text :<|> (SubmitInfo -> ClientM (Text :<|> SubmitRes)) ) :<|> ClientM GlobalLeaderboard@@ -268,12 +282,13 @@ -- | A subset of 'adventAPIClient' for only puzzle-related API routes, not -- leaderboard ones. adventAPIPuzzleClient- :: Integer+ :: Maybe AoCUserAgent+ -> Integer -> Day -> ClientM (Map Part Text) :<|> ClientM Text :<|> (SubmitInfo -> ClientM (Text :<|> SubmitRes))-adventAPIPuzzleClient y = pis+adventAPIPuzzleClient aua y = pis where- _ :<|> pis :<|> _ = adventAPIClient y+ _ :<|> pis :<|> _ = adventAPIClient aua y userNameNaked :: [TagTree Text] -> Maybe Text userNameNaked = (listToMaybe .) . mapMaybe $ \x -> do