packages feed

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 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