2020-07-07 20:52:01 -04:00
|
|
|
{-# OPTIONS_GHC -Wno-orphans #-}
|
|
|
|
module Info
|
|
|
|
(Info (..), Image (..), Link (..),
|
|
|
|
-- ** Reexports
|
|
|
|
Day (..), Text, Vector)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Data.YAML (FromYAML (..), (.:))
|
|
|
|
import qualified Data.YAML as YAML
|
|
|
|
import Data.Time.Calendar (Day (..))
|
|
|
|
import Data.Text (Text)
|
|
|
|
import qualified Data.Text as Text
|
|
|
|
import Data.Vector (Vector)
|
|
|
|
import qualified Data.Vector as Vector
|
|
|
|
import qualified Data.Map.Strict as Map
|
|
|
|
import Control.Applicative
|
|
|
|
import Text.Read (readMaybe)
|
|
|
|
|
|
|
|
|
|
|
|
data Info =
|
|
|
|
Info {
|
2020-07-07 23:27:38 -04:00
|
|
|
date :: !Day,
|
|
|
|
title :: !Text,
|
|
|
|
tags :: !(Vector Text),
|
|
|
|
description :: !Text,
|
|
|
|
images :: !(Vector Image),
|
|
|
|
thumb :: !Text,
|
|
|
|
links :: !(Vector Link)
|
2020-07-07 20:52:01 -04:00
|
|
|
}
|
|
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
data Image =
|
|
|
|
Image {
|
2020-07-07 23:27:38 -04:00
|
|
|
label :: !Text,
|
|
|
|
path :: !Text,
|
|
|
|
nsfw :: !Bool
|
2020-07-07 20:52:01 -04:00
|
|
|
}
|
|
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
data Link =
|
|
|
|
Link {
|
2020-07-07 23:27:38 -04:00
|
|
|
title :: !Text,
|
2020-07-09 15:45:57 -04:00
|
|
|
url :: !Text,
|
|
|
|
nsfw :: !Bool
|
2020-07-07 20:52:01 -04:00
|
|
|
}
|
|
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
|
|
|
|
instance FromYAML Info where
|
|
|
|
parseYAML = YAML.withMap "info" \m ->
|
|
|
|
Info <$> m .: "date"
|
|
|
|
<*> m .: "title"
|
|
|
|
<*> m .: "tags"
|
|
|
|
<*> m .: "description"
|
|
|
|
<*> m .: "images"
|
|
|
|
<*> m .: "thumb"
|
|
|
|
<*> m .: "links"
|
|
|
|
|
|
|
|
instance FromYAML Image where
|
2020-07-09 15:45:57 -04:00
|
|
|
parseYAML = labelledOptNsfw Image "path" "path"
|
2020-07-07 20:52:01 -04:00
|
|
|
|
|
|
|
instance FromYAML Link where
|
2020-07-09 15:45:57 -04:00
|
|
|
parseYAML = labelledOptNsfw Link "url" "url"
|
2020-07-07 20:52:01 -04:00
|
|
|
|
|
|
|
|
|
|
|
data Pair a b = Pair !a !b
|
|
|
|
|
|
|
|
instance (FromYAML a, FromYAML b) => FromYAML (Pair a b) where
|
|
|
|
parseYAML =
|
|
|
|
YAML.withMap "single-pair map" \m ->
|
|
|
|
case Map.toList m of
|
|
|
|
[(a, b)] -> Pair <$> parseYAML a <*> parseYAML b
|
|
|
|
_ -> fail "expected exactly one pair"
|
|
|
|
|
2020-07-09 15:45:57 -04:00
|
|
|
|
|
|
|
data OptNsfw a = NoNsfw !a | WithNsfw !a !Bool
|
|
|
|
|
|
|
|
appOptNsfw :: (a -> Bool -> b) -> OptNsfw a -> b
|
|
|
|
appOptNsfw f (NoNsfw x) = f x False
|
|
|
|
appOptNsfw f (WithNsfw x n) = f x n
|
|
|
|
|
|
|
|
labelledOptNsfw :: FromYAML a
|
|
|
|
=> (Text -> a -> Bool -> b)
|
|
|
|
-> String -- ^ name in \"expected\" message
|
|
|
|
-> Text -- ^ field name
|
|
|
|
-> YAML.Node YAML.Pos -> YAML.Parser b
|
|
|
|
labelledOptNsfw f name field y = do
|
|
|
|
Pair l n' <- parseYAML y
|
|
|
|
n <- parseOptNsfw name field n'
|
|
|
|
pure $ appOptNsfw (f l) n
|
|
|
|
|
|
|
|
parseOptNsfw :: FromYAML a
|
|
|
|
=> String -- ^ name in \"expected\" message
|
|
|
|
-> Text -- ^ field name
|
|
|
|
-> YAML.Node YAML.Pos -> YAML.Parser (OptNsfw a)
|
|
|
|
parseOptNsfw name field y = yes y <|> no y where
|
|
|
|
yes = YAML.withMap (name <> " & nsfw") \m ->
|
|
|
|
WithNsfw <$> m .: field <*> m .: "nsfw"
|
|
|
|
no = fmap NoNsfw . parseYAML
|
|
|
|
|
|
|
|
|
2020-07-07 20:52:01 -04:00
|
|
|
instance FromYAML Day where
|
|
|
|
parseYAML = YAML.withStr "date" \str ->
|
|
|
|
case readMaybe $ Text.unpack str of
|
|
|
|
Just d -> pure d
|
|
|
|
Nothing -> fail $ "couldn't parse date " ++ show str
|
|
|
|
|
|
|
|
instance FromYAML a => FromYAML (Vector a) where
|
|
|
|
parseYAML = YAML.withSeq "seq" $ fmap Vector.fromList . traverse parseYAML
|