advent-of-code-api 0.2.6.1 → 0.2.6.2
raw patch · 3 files changed
+42/−24 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +2/−0
- advent-of-code-api.cabal +2/−2
- src/Advent/API.hs +38/−22
CHANGELOG.md view
@@ -13,6 +13,8 @@ invalidating cache properly) also for prompt (will not invalidate part1-only caches if there is no session key) * **0.2.6.1 Bugfix**: Fix bug in prompt cache invalidation+* **0.2.6.2 Bugfix**: HTML parser for articles (for prompt API calls) now+ more robust, adjusting for more malformed HTML from site. Version 0.2.5.0 ---------------
advent-of-code-api.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 7c78803c08846a438e524f068966ad9074ebfd7ce45ca61c3e10b611c820e23a+-- hash: 29142f7dd051872d37ae0e834ec0dd60a68dc650d60dfa4d913add426cceb3c3 name: advent-of-code-api-version: 0.2.6.1+version: 0.2.6.2 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/API.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}@@ -53,27 +54,27 @@ import Data.Char import Data.Finite import Data.Foldable-import Data.List.NonEmpty (NonEmpty(..))-import Data.Map (Map)+import Data.List.NonEmpty (NonEmpty(..))+import Data.Map (Map) import Data.Maybe import Data.Ord import Data.Proxy-import Data.Text (Text)+import Data.Text (Text) import Data.Time.Format import Data.Time.LocalTime import GHC.TypeLits import Servant.API import Servant.Client-import Text.HTML.TagSoup.Tree (TagTree(..))-import Text.Read (readMaybe)-import qualified Data.ByteString.Lazy as BSL-import qualified Data.List.NonEmpty as NE-import qualified Data.Map as M-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Network.HTTP.Media as M-import qualified Text.HTML.TagSoup as H-import qualified Text.HTML.TagSoup.Tree as H+import Text.HTML.TagSoup.Tree (TagTree(..))+import Text.Read (readMaybe)+import qualified Data.ByteString.Lazy as BSL+import qualified Data.List.NonEmpty as NE+import qualified Data.Map as M+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Network.HTTP.Media as M+import qualified Text.HTML.TagSoup as H+import qualified Text.HTML.TagSoup.Tree as H #if !MIN_VERSION_base(4,11,0) import Data.Semigroup ((<>))@@ -276,17 +277,32 @@ -> [Text] processHTML tag = mapMaybe getTag . H.universeTree- . H.parseTree- . cleanDoubleTitle+ . H.tagTree+ . cleanTags+ . H.parseTags where getTag :: TagTree Text -> Maybe Text getTag (TagBranch n _ ts) = H.renderTree ts <$ guard (n == T.pack tag) getTag _ = Nothing- -- 2016 Day 2 Part 2 has a malformed `<span>...</title>` tag that- -- causes tagsoup to choke. this converts all </title> except for the- -- first one to be <span>.- cleanDoubleTitle :: Text -> Text- cleanDoubleTitle t = case T.splitOn "</title>" t of- x:xs -> x <> "</title>" <> T.intercalate "</span>" xs- [] -> "" -- this shouldn't ever happen because splitOn is always non-empty +-- | Some days, including:+--+-- * 2015 Day 6 Part 1+-- * 2016 Day 2 Part 2+--+-- Have malformed HTML tags; the first has @<p></code>@ and the second has+-- @<span></title>@. This function cleans up all tags so that any closing+-- tags ignore their actual tag type and instead close the last opened tag+-- (if there is any). If no tag is currently open then it just leaves it+-- unchanged.+cleanTags+ :: [H.Tag str]+ -> [H.Tag str]+cleanTags = flip evalState [] . mapM go+ where+ go t = case t of+ H.TagOpen n _ -> t <$ modify (n:)+ H.TagClose _ -> get >>= \case+ [] -> pure t+ m:ms -> H.TagClose m <$ put ms+ _ -> pure t