advent-of-code-api 0.2.5.0 → 0.2.6.0
raw patch · 3 files changed
+59/−14 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Advent: aocServerTime :: IO LocalTime
Files
- CHANGELOG.md +12/−0
- advent-of-code-api.cabal +2/−2
- src/Advent.hs +45/−12
CHANGELOG.md view
@@ -1,6 +1,18 @@ Changelog ========= +Version 0.2.6.0+---------------++*December 3, 2019*++<https://github.com/mstksg/advent-of-code-api/releases/tag/v0.2.6.0>++* Add `aocServerTime` to get the current time for AoC servers.+* Fix cacheing rules for global leaderboard (was previously not saving or+ invalidating cache properly) also for prompt (will not invalidate+ part1-only caches if there is no session key)+ Version 0.2.5.0 ---------------
advent-of-code-api.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 47b5a0fa5ec3911f9afa108c1f723d2716f225a23091507886305ff551fdca08+-- hash: 11039e11778c64e34a0031b4251a99a15470033e3dafd1962b1db1a02bcab593 name: advent-of-code-api-version: 0.2.5.0+version: 0.2.6.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
@@ -9,6 +9,7 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeInType #-} {-# LANGUAGE ViewPatterns #-} @@ -63,6 +64,7 @@ -- ** Day , mkDay, mkDay_, dayInt, pattern DayInt, _DayInt , aocDay+ , aocServerTime -- ** Part , partChar, partInt -- ** Leaderboard@@ -138,12 +140,20 @@ data AoC :: Type -> Type where -- | Fetch prompts for a given day. Returns a 'Map' of 'Part's and -- their associated promps, as HTML.+ --+ -- _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. AoCPrompt :: Day -> AoC (Map Part 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. AoCInput :: Day -> AoC Text -- | Submit a plaintext answer (the 'String') to a given day and part.@@ -152,6 +162,8 @@ -- __WARNING__: Answers are not length-limited. Answers are stripped -- of leading and trailing whitespace and run through 'URI.encode' -- before submitting.+ --+ -- /Cacheing rules/: Is never cached. AoCSubmit :: Day -> Part@@ -174,6 +186,9 @@ -- 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 AoCLeaderboard :: Integer@@ -186,7 +201,7 @@ -- when using this. If you automate this, please do not fetch any more -- often than necessary. --- -- Calls to this will be cached if a full leaderboard is observed.+ -- /Cacheing rules/: Will be cached if a full leaderboard is observed. -- -- @since 0.2.3.0 AoCDailyLeaderboard@@ -200,7 +215,8 @@ -- when using this. If you automate this, please do not fetch any more -- often than necessary. --- -- Calls to this will be cached if fetched after each event ends.+ -- /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 AoCGlobalLeaderboard@@ -344,7 +360,10 @@ Just fp -> cacheing (cacheDir </> fp) $ if _aForce then noCache- else saverLoader (not eventOver) a+ else saverLoader+ (not (null _aSessionKey))+ (not eventOver)+ a cacher . runExceptT $ do forM_ (aocDay a) $ \d -> do@@ -389,10 +408,11 @@ saverLoader- :: Bool -- ^ is the event ongoing (True) or over (False)?+ :: Bool -- ^ is there a non-empty session token?+ -> Bool -- ^ is the event ongoing (True) or over (False)? -> AoC a -> SaverLoader (Either AoCError a)-saverLoader evt = \case+saverLoader validToken evt = \case AoCPrompt{} -> SL { _slSave = either (const Nothing) (Just . encodeMap) , _slLoad = \str -> let mp = decodeMap str@@ -411,15 +431,20 @@ guard $ fullDailyBoard r pure $ Right r }- AoCGlobalLeaderboard{}- | evt -> noCache- | otherwise -> SL- { _slSave = either (const Nothing) (Just . TL.toStrict . TL.decodeUtf8 . A.encode)- , _slLoad = fmap Right . A.decode . TL.encodeUtf8 . TL.fromStrict- }+ AoCGlobalLeaderboard{} -> SL+ { _slSave = either+ (const Nothing)+ (Just . TL.toStrict . TL.decodeUtf8 . A.encode @(Bool, GlobalLeaderboard) . (evt,))+ , _slLoad = \str -> do+ (evt', lb) <- A.decode @(Bool, GlobalLeaderboard) . TL.encodeUtf8 . TL.fromStrict $ str+ guard $ not evt' -- only load cache if evt' is false: it was saved in a non-evt time+ pure $ Right lb+ } where expectedParts :: Set Part- expectedParts = S.fromDistinctAscList [Part1 ..]+ expectedParts+ | validToken = S.singleton Part1+ | otherwise = S.fromDistinctAscList [Part1 ..] sep = ">>>>>>>>>" encodeMap mp = T.intercalate "\n" . concat $ [ maybeToList $ M.lookup Part1 mp@@ -454,6 +479,14 @@ -> UTCTime challengeReleaseTime y d = UTCTime (fromGregorian y 12 (fromIntegral (dayInt d))) (5 * 60 * 60)++-- | 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+aocServerTime :: IO LocalTime+aocServerTime = utcToLocalTime (read "EST") <$> getCurrentTime strip :: String -> String strip = T.unpack . T.strip . T.pack