-- | The site configuration read from @website.yaml@ in the content repo
module MathiasSM.Yaml.Website (
    -- * Main logic
    loadWebsite,
    validateSecurityExpiration,

    -- * @website.yaml@ parsing

    -- ** website:
    Website (..),

    -- ** site:
    Site (..),

    -- ** contact:
    Contact (..),

    -- ** manifest:
    Manifest (..),

    -- ** mathjax:
    Mathjax (..),

    -- ** highlight:
    Highlight (..),
    HighlightStyle (..),
    highlightStyleName,
    parseHighlightStyle,
    toPandocStyle,

    -- ** feed:
    FeedConfig (..),

    -- ** security:
    Security (..),

    -- ** robots:
    Robots (..),

    -- ** trust:
    Trust (..),

    -- ** funding:
    Funding (..),
    FundingEntity (..),
    FundingProject (..),
    FundingChannel (..),
    FundingPlan (..),
) where

import Control.Monad (unless, when)
import Data.Aeson (FromJSON (parseJSON), withObject, (.:))
import Data.Time (getCurrentTime, utctDay)
import Data.Time.Calendar (Day, addDays)
import Data.Time.Format (defaultTimeLocale, parseTimeM)
import Data.Yaml (decodeFileEither, prettyPrintParseException)
import MathiasSM.Yaml (enumFromJSON)
import System.Directory (doesFileExist)
import System.Exit (die)
import System.FilePath.Posix ((</>))
import Text.Pandoc.Highlighting (Style, breezeDark, espresso, haddock, kate, monochrome, pygments, tango, zenburn)

-- | The @site:@ section: the site's identity
data Site = Site
    { Site -> [Char]
siteName :: String
    , Site -> [Char]
siteDescription :: String
    , Site -> [Char]
siteAuthor :: String
    , Site -> Int
siteCopyrightYear :: Int
    , Site -> [Char]
siteDomain :: String
    , Site -> [Char]
siteTwitterHandle :: String
    }
    deriving (Site -> Site -> Bool
(Site -> Site -> Bool) -> (Site -> Site -> Bool) -> Eq Site
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Site -> Site -> Bool
== :: Site -> Site -> Bool
$c/= :: Site -> Site -> Bool
/= :: Site -> Site -> Bool
Eq, Int -> Site -> ShowS
[Site] -> ShowS
Site -> [Char]
(Int -> Site -> ShowS)
-> (Site -> [Char]) -> ([Site] -> ShowS) -> Show Site
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Site -> ShowS
showsPrec :: Int -> Site -> ShowS
$cshow :: Site -> [Char]
show :: Site -> [Char]
$cshowList :: [Site] -> ShowS
showList :: [Site] -> ShowS
Show)

-- | The @contact:@ section: how to reach the site owner
data Contact = Contact
    { Contact -> [Char]
contactEmail :: String
    , Contact -> [Char]
contactPage :: String
    }
    deriving (Contact -> Contact -> Bool
(Contact -> Contact -> Bool)
-> (Contact -> Contact -> Bool) -> Eq Contact
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Contact -> Contact -> Bool
== :: Contact -> Contact -> Bool
$c/= :: Contact -> Contact -> Bool
/= :: Contact -> Contact -> Bool
Eq, Int -> Contact -> ShowS
[Contact] -> ShowS
Contact -> [Char]
(Int -> Contact -> ShowS)
-> (Contact -> [Char]) -> ([Contact] -> ShowS) -> Show Contact
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Contact -> ShowS
showsPrec :: Int -> Contact -> ShowS
$cshow :: Contact -> [Char]
show :: Contact -> [Char]
$cshowList :: [Contact] -> ShowS
showList :: [Contact] -> ShowS
Show)

-- | The @manifest:@ section: web app manifest colours
data Manifest = Manifest
    { Manifest -> [Char]
manifestBackgroundColor :: String
    , Manifest -> [Char]
manifestThemeColor :: String
    }
    deriving (Manifest -> Manifest -> Bool
(Manifest -> Manifest -> Bool)
-> (Manifest -> Manifest -> Bool) -> Eq Manifest
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Manifest -> Manifest -> Bool
== :: Manifest -> Manifest -> Bool
$c/= :: Manifest -> Manifest -> Bool
/= :: Manifest -> Manifest -> Bool
Eq, Int -> Manifest -> ShowS
[Manifest] -> ShowS
Manifest -> [Char]
(Int -> Manifest -> ShowS)
-> (Manifest -> [Char]) -> ([Manifest] -> ShowS) -> Show Manifest
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Manifest -> ShowS
showsPrec :: Int -> Manifest -> ShowS
$cshow :: Manifest -> [Char]
show :: Manifest -> [Char]
$cshowList :: [Manifest] -> ShowS
showList :: [Manifest] -> ShowS
Show)

-- | The @mathjax:@ section: which MathJax CDN version renders the site's math
data Mathjax = Mathjax
    { Mathjax -> [Char]
mathjaxVersion :: String
    }
    deriving (Mathjax -> Mathjax -> Bool
(Mathjax -> Mathjax -> Bool)
-> (Mathjax -> Mathjax -> Bool) -> Eq Mathjax
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Mathjax -> Mathjax -> Bool
== :: Mathjax -> Mathjax -> Bool
$c/= :: Mathjax -> Mathjax -> Bool
/= :: Mathjax -> Mathjax -> Bool
Eq, Int -> Mathjax -> ShowS
[Mathjax] -> ShowS
Mathjax -> [Char]
(Int -> Mathjax -> ShowS)
-> (Mathjax -> [Char]) -> ([Mathjax] -> ShowS) -> Show Mathjax
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Mathjax -> ShowS
showsPrec :: Int -> Mathjax -> ShowS
$cshow :: Mathjax -> [Char]
show :: Mathjax -> [Char]
$cshowList :: [Mathjax] -> ShowS
showList :: [Mathjax] -> ShowS
Show)

-- | The @highlight:@ section: which pandoc style renders code blocks
data Highlight = Highlight
    { Highlight -> HighlightStyle
highlightStyle :: HighlightStyle
    }
    deriving (Highlight -> Highlight -> Bool
(Highlight -> Highlight -> Bool)
-> (Highlight -> Highlight -> Bool) -> Eq Highlight
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Highlight -> Highlight -> Bool
== :: Highlight -> Highlight -> Bool
$c/= :: Highlight -> Highlight -> Bool
/= :: Highlight -> Highlight -> Bool
Eq, Int -> Highlight -> ShowS
[Highlight] -> ShowS
Highlight -> [Char]
(Int -> Highlight -> ShowS)
-> (Highlight -> [Char])
-> ([Highlight] -> ShowS)
-> Show Highlight
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Highlight -> ShowS
showsPrec :: Int -> Highlight -> ShowS
$cshow :: Highlight -> [Char]
show :: Highlight -> [Char]
$cshowList :: [Highlight] -> ShowS
showList :: [Highlight] -> ShowS
Show)

-- | A pandoc syntax-highlighting style, as spelled in @highlight.style@
data HighlightStyle = Pygments | Espresso | Zenburn | Tango | Kate | Monochrome | BreezeDark | Haddock
    deriving (HighlightStyle -> HighlightStyle -> Bool
(HighlightStyle -> HighlightStyle -> Bool)
-> (HighlightStyle -> HighlightStyle -> Bool) -> Eq HighlightStyle
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: HighlightStyle -> HighlightStyle -> Bool
== :: HighlightStyle -> HighlightStyle -> Bool
$c/= :: HighlightStyle -> HighlightStyle -> Bool
/= :: HighlightStyle -> HighlightStyle -> Bool
Eq, Int -> HighlightStyle -> ShowS
[HighlightStyle] -> ShowS
HighlightStyle -> [Char]
(Int -> HighlightStyle -> ShowS)
-> (HighlightStyle -> [Char])
-> ([HighlightStyle] -> ShowS)
-> Show HighlightStyle
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HighlightStyle -> ShowS
showsPrec :: Int -> HighlightStyle -> ShowS
$cshow :: HighlightStyle -> [Char]
show :: HighlightStyle -> [Char]
$cshowList :: [HighlightStyle] -> ShowS
showList :: [HighlightStyle] -> ShowS
Show, Int -> HighlightStyle
HighlightStyle -> Int
HighlightStyle -> [HighlightStyle]
HighlightStyle -> HighlightStyle
HighlightStyle -> HighlightStyle -> [HighlightStyle]
HighlightStyle
-> HighlightStyle -> HighlightStyle -> [HighlightStyle]
(HighlightStyle -> HighlightStyle)
-> (HighlightStyle -> HighlightStyle)
-> (Int -> HighlightStyle)
-> (HighlightStyle -> Int)
-> (HighlightStyle -> [HighlightStyle])
-> (HighlightStyle -> HighlightStyle -> [HighlightStyle])
-> (HighlightStyle -> HighlightStyle -> [HighlightStyle])
-> (HighlightStyle
    -> HighlightStyle -> HighlightStyle -> [HighlightStyle])
-> Enum HighlightStyle
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: HighlightStyle -> HighlightStyle
succ :: HighlightStyle -> HighlightStyle
$cpred :: HighlightStyle -> HighlightStyle
pred :: HighlightStyle -> HighlightStyle
$ctoEnum :: Int -> HighlightStyle
toEnum :: Int -> HighlightStyle
$cfromEnum :: HighlightStyle -> Int
fromEnum :: HighlightStyle -> Int
$cenumFrom :: HighlightStyle -> [HighlightStyle]
enumFrom :: HighlightStyle -> [HighlightStyle]
$cenumFromThen :: HighlightStyle -> HighlightStyle -> [HighlightStyle]
enumFromThen :: HighlightStyle -> HighlightStyle -> [HighlightStyle]
$cenumFromTo :: HighlightStyle -> HighlightStyle -> [HighlightStyle]
enumFromTo :: HighlightStyle -> HighlightStyle -> [HighlightStyle]
$cenumFromThenTo :: HighlightStyle
-> HighlightStyle -> HighlightStyle -> [HighlightStyle]
enumFromThenTo :: HighlightStyle
-> HighlightStyle -> HighlightStyle -> [HighlightStyle]
Enum, HighlightStyle
HighlightStyle -> HighlightStyle -> Bounded HighlightStyle
forall a. a -> a -> Bounded a
$cminBound :: HighlightStyle
minBound :: HighlightStyle
$cmaxBound :: HighlightStyle
maxBound :: HighlightStyle
Bounded)

-- | How a highlight style is spelled
highlightStyleName :: HighlightStyle -> String
highlightStyleName :: HighlightStyle -> [Char]
highlightStyleName HighlightStyle
Pygments = [Char]
"pygments"
highlightStyleName HighlightStyle
Espresso = [Char]
"espresso"
highlightStyleName HighlightStyle
Zenburn = [Char]
"zenburn"
highlightStyleName HighlightStyle
Tango = [Char]
"tango"
highlightStyleName HighlightStyle
Kate = [Char]
"kate"
highlightStyleName HighlightStyle
Monochrome = [Char]
"monochrome"
highlightStyleName HighlightStyle
BreezeDark = [Char]
"breezeDark"
highlightStyleName HighlightStyle
Haddock = [Char]
"haddock"

instance FromJSON HighlightStyle where
    parseJSON :: Value -> Parser HighlightStyle
parseJSON = [Char]
-> (HighlightStyle -> [Char]) -> Value -> Parser HighlightStyle
forall a.
(Enum a, Bounded a) =>
[Char] -> (a -> [Char]) -> Value -> Parser a
enumFromJSON [Char]
"highlight style" HighlightStyle -> [Char]
highlightStyleName

-- | Resolves a 'HighlightStyle' from its @highlight.style@ spelling, if known
parseHighlightStyle :: String -> Maybe HighlightStyle
parseHighlightStyle :: [Char] -> Maybe HighlightStyle
parseHighlightStyle [Char]
name = [Char] -> [([Char], HighlightStyle)] -> Maybe HighlightStyle
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup [Char]
name [(HighlightStyle -> [Char]
highlightStyleName HighlightStyle
style, HighlightStyle
style) | HighlightStyle
style <- [HighlightStyle
forall a. Bounded a => a
minBound .. HighlightStyle
forall a. Bounded a => a
maxBound]]

-- | The pandoc 'Style' backing a 'HighlightStyle'
toPandocStyle :: HighlightStyle -> Style
toPandocStyle :: HighlightStyle -> Style
toPandocStyle HighlightStyle
Pygments = Style
pygments
toPandocStyle HighlightStyle
Espresso = Style
espresso
toPandocStyle HighlightStyle
Zenburn = Style
zenburn
toPandocStyle HighlightStyle
Tango = Style
tango
toPandocStyle HighlightStyle
Kate = Style
kate
toPandocStyle HighlightStyle
Monochrome = Style
monochrome
toPandocStyle HighlightStyle
BreezeDark = Style
breezeDark
toPandocStyle HighlightStyle
Haddock = Style
haddock

instance FromJSON Highlight where
    parseJSON :: Value -> Parser Highlight
parseJSON = [Char] -> (Object -> Parser Highlight) -> Value -> Parser Highlight
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"highlight" ((Object -> Parser Highlight) -> Value -> Parser Highlight)
-> (Object -> Parser Highlight) -> Value -> Parser Highlight
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        HighlightStyle -> Highlight
Highlight (HighlightStyle -> Highlight)
-> Parser HighlightStyle -> Parser Highlight
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser HighlightStyle
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"style"

-- | The @funding:@ section: data behind @funding.json@
data Funding = Funding
    { Funding -> FundingEntity
fundingEntity :: FundingEntity
    , Funding -> [FundingProject]
fundingProjects :: [FundingProject]
    , Funding -> [FundingChannel]
fundingChannels :: [FundingChannel]
    , Funding -> [FundingPlan]
fundingPlans :: [FundingPlan]
    }
    deriving (Funding -> Funding -> Bool
(Funding -> Funding -> Bool)
-> (Funding -> Funding -> Bool) -> Eq Funding
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Funding -> Funding -> Bool
== :: Funding -> Funding -> Bool
$c/= :: Funding -> Funding -> Bool
/= :: Funding -> Funding -> Bool
Eq, Int -> Funding -> ShowS
[Funding] -> ShowS
Funding -> [Char]
(Int -> Funding -> ShowS)
-> (Funding -> [Char]) -> ([Funding] -> ShowS) -> Show Funding
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Funding -> ShowS
showsPrec :: Int -> Funding -> ShowS
$cshow :: Funding -> [Char]
show :: Funding -> [Char]
$cshowList :: [Funding] -> ShowS
showList :: [Funding] -> ShowS
Show)

-- | The entity being funded (the @funding.entity@ section)
data FundingEntity = FundingEntity
    { FundingEntity -> [Char]
fundingEntityEmail :: String
    , FundingEntity -> [Char]
fundingEntityDescription :: String
    }
    deriving (FundingEntity -> FundingEntity -> Bool
(FundingEntity -> FundingEntity -> Bool)
-> (FundingEntity -> FundingEntity -> Bool) -> Eq FundingEntity
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FundingEntity -> FundingEntity -> Bool
== :: FundingEntity -> FundingEntity -> Bool
$c/= :: FundingEntity -> FundingEntity -> Bool
/= :: FundingEntity -> FundingEntity -> Bool
Eq, Int -> FundingEntity -> ShowS
[FundingEntity] -> ShowS
FundingEntity -> [Char]
(Int -> FundingEntity -> ShowS)
-> (FundingEntity -> [Char])
-> ([FundingEntity] -> ShowS)
-> Show FundingEntity
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FundingEntity -> ShowS
showsPrec :: Int -> FundingEntity -> ShowS
$cshow :: FundingEntity -> [Char]
show :: FundingEntity -> [Char]
$cshowList :: [FundingEntity] -> ShowS
showList :: [FundingEntity] -> ShowS
Show)

-- | A project listed in @funding.json@
data FundingProject = FundingProject
    { FundingProject -> [Char]
fundingProjectGuid :: String
    , FundingProject -> [Char]
fundingProjectName :: String
    , FundingProject -> [Char]
fundingProjectDescription :: String
    , FundingProject -> [Char]
fundingProjectRepositoryUrl :: String
    , FundingProject -> [Char]
fundingProjectRepositoryWellKnown :: String
    , FundingProject -> [[Char]]
fundingProjectLicenses :: [String]
    , FundingProject -> [[Char]]
fundingProjectTags :: [String]
    }
    deriving (FundingProject -> FundingProject -> Bool
(FundingProject -> FundingProject -> Bool)
-> (FundingProject -> FundingProject -> Bool) -> Eq FundingProject
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FundingProject -> FundingProject -> Bool
== :: FundingProject -> FundingProject -> Bool
$c/= :: FundingProject -> FundingProject -> Bool
/= :: FundingProject -> FundingProject -> Bool
Eq, Int -> FundingProject -> ShowS
[FundingProject] -> ShowS
FundingProject -> [Char]
(Int -> FundingProject -> ShowS)
-> (FundingProject -> [Char])
-> ([FundingProject] -> ShowS)
-> Show FundingProject
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FundingProject -> ShowS
showsPrec :: Int -> FundingProject -> ShowS
$cshow :: FundingProject -> [Char]
show :: FundingProject -> [Char]
$cshowList :: [FundingProject] -> ShowS
showList :: [FundingProject] -> ShowS
Show)

-- | A funding channel in @funding.json@
data FundingChannel = FundingChannel
    { FundingChannel -> [Char]
fundingChannelGuid :: String
    , FundingChannel -> [Char]
fundingChannelType :: String
    , FundingChannel -> [Char]
fundingChannelAddress :: String
    , FundingChannel -> [Char]
fundingChannelDescription :: String
    }
    deriving (FundingChannel -> FundingChannel -> Bool
(FundingChannel -> FundingChannel -> Bool)
-> (FundingChannel -> FundingChannel -> Bool) -> Eq FundingChannel
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FundingChannel -> FundingChannel -> Bool
== :: FundingChannel -> FundingChannel -> Bool
$c/= :: FundingChannel -> FundingChannel -> Bool
/= :: FundingChannel -> FundingChannel -> Bool
Eq, Int -> FundingChannel -> ShowS
[FundingChannel] -> ShowS
FundingChannel -> [Char]
(Int -> FundingChannel -> ShowS)
-> (FundingChannel -> [Char])
-> ([FundingChannel] -> ShowS)
-> Show FundingChannel
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FundingChannel -> ShowS
showsPrec :: Int -> FundingChannel -> ShowS
$cshow :: FundingChannel -> [Char]
show :: FundingChannel -> [Char]
$cshowList :: [FundingChannel] -> ShowS
showList :: [FundingChannel] -> ShowS
Show)

-- | A funding plan in @funding.json@
data FundingPlan = FundingPlan
    { FundingPlan -> [Char]
fundingPlanGuid :: String
    , FundingPlan -> [Char]
fundingPlanStatus :: String
    , FundingPlan -> [Char]
fundingPlanName :: String
    , FundingPlan -> [Char]
fundingPlanDescription :: String
    , FundingPlan -> Int
fundingPlanAmount :: Int
    , FundingPlan -> [Char]
fundingPlanCurrency :: String
    , FundingPlan -> [Char]
fundingPlanFrequency :: String
    , FundingPlan -> [[Char]]
fundingPlanChannels :: [String]
    }
    deriving (FundingPlan -> FundingPlan -> Bool
(FundingPlan -> FundingPlan -> Bool)
-> (FundingPlan -> FundingPlan -> Bool) -> Eq FundingPlan
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FundingPlan -> FundingPlan -> Bool
== :: FundingPlan -> FundingPlan -> Bool
$c/= :: FundingPlan -> FundingPlan -> Bool
/= :: FundingPlan -> FundingPlan -> Bool
Eq, Int -> FundingPlan -> ShowS
[FundingPlan] -> ShowS
FundingPlan -> [Char]
(Int -> FundingPlan -> ShowS)
-> (FundingPlan -> [Char])
-> ([FundingPlan] -> ShowS)
-> Show FundingPlan
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FundingPlan -> ShowS
showsPrec :: Int -> FundingPlan -> ShowS
$cshow :: FundingPlan -> [Char]
show :: FundingPlan -> [Char]
$cshowList :: [FundingPlan] -> ShowS
showList :: [FundingPlan] -> ShowS
Show)

-- | The @security:@ section: data behind @.well-known/security.txt@
data Security = Security
    { Security -> [Char]
securityPreferredLanguages :: String
    , Security -> [Char]
securityExpires :: String
    , Security -> Int
securityExpirationMarginDays :: Int
    }
    deriving (Security -> Security -> Bool
(Security -> Security -> Bool)
-> (Security -> Security -> Bool) -> Eq Security
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Security -> Security -> Bool
== :: Security -> Security -> Bool
$c/= :: Security -> Security -> Bool
/= :: Security -> Security -> Bool
Eq, Int -> Security -> ShowS
[Security] -> ShowS
Security -> [Char]
(Int -> Security -> ShowS)
-> (Security -> [Char]) -> ([Security] -> ShowS) -> Show Security
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Security -> ShowS
showsPrec :: Int -> Security -> ShowS
$cshow :: Security -> [Char]
show :: Security -> [Char]
$cshowList :: [Security] -> ShowS
showList :: [Security] -> ShowS
Show)

-- | The @robots:@ section: data behind @robots.txt@
data Robots = Robots {Robots -> [[Char]]
robotsDisallow :: [String]}
    deriving (Robots -> Robots -> Bool
(Robots -> Robots -> Bool)
-> (Robots -> Robots -> Bool) -> Eq Robots
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Robots -> Robots -> Bool
== :: Robots -> Robots -> Bool
$c/= :: Robots -> Robots -> Bool
/= :: Robots -> Robots -> Bool
Eq, Int -> Robots -> ShowS
[Robots] -> ShowS
Robots -> [Char]
(Int -> Robots -> ShowS)
-> (Robots -> [Char]) -> ([Robots] -> ShowS) -> Show Robots
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Robots -> ShowS
showsPrec :: Int -> Robots -> ShowS
$cshow :: Robots -> [Char]
show :: Robots -> [Char]
$cshowList :: [Robots] -> ShowS
showList :: [Robots] -> ShowS
Show)

-- | The @trust:@ section: data behind @.well-known/trust.txt@
data Trust = Trust {Trust -> [Char]
trustTrainingAllowed :: String}
    deriving (Trust -> Trust -> Bool
(Trust -> Trust -> Bool) -> (Trust -> Trust -> Bool) -> Eq Trust
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Trust -> Trust -> Bool
== :: Trust -> Trust -> Bool
$c/= :: Trust -> Trust -> Bool
/= :: Trust -> Trust -> Bool
Eq, Int -> Trust -> ShowS
[Trust] -> ShowS
Trust -> [Char]
(Int -> Trust -> ShowS)
-> (Trust -> [Char]) -> ([Trust] -> ShowS) -> Show Trust
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Trust -> ShowS
showsPrec :: Int -> Trust -> ShowS
$cshow :: Trust -> [Char]
show :: Trust -> [Char]
$cshowList :: [Trust] -> ShowS
showList :: [Trust] -> ShowS
Show)

-- | The @feed:@ section: data behind @atom.xml@ files
data FeedConfig = FeedConfig {FeedConfig -> Int
feedSize :: Int}
    deriving (FeedConfig -> FeedConfig -> Bool
(FeedConfig -> FeedConfig -> Bool)
-> (FeedConfig -> FeedConfig -> Bool) -> Eq FeedConfig
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FeedConfig -> FeedConfig -> Bool
== :: FeedConfig -> FeedConfig -> Bool
$c/= :: FeedConfig -> FeedConfig -> Bool
/= :: FeedConfig -> FeedConfig -> Bool
Eq, Int -> FeedConfig -> ShowS
[FeedConfig] -> ShowS
FeedConfig -> [Char]
(Int -> FeedConfig -> ShowS)
-> (FeedConfig -> [Char])
-> ([FeedConfig] -> ShowS)
-> Show FeedConfig
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FeedConfig -> ShowS
showsPrec :: Int -> FeedConfig -> ShowS
$cshow :: FeedConfig -> [Char]
show :: FeedConfig -> [Char]
$cshowList :: [FeedConfig] -> ShowS
showList :: [FeedConfig] -> ShowS
Show)

-- | Everything @website.yaml@ describes
data Website = Website
    { Website -> Site
websiteSite :: Site
    , Website -> Contact
websiteContact :: Contact
    , Website -> Manifest
websiteManifest :: Manifest
    , Website -> Mathjax
websiteMathjax :: Mathjax
    , Website -> Highlight
websiteHighlight :: Highlight
    , Website -> Funding
websiteFunding :: Funding
    , Website -> Security
websiteSecurity :: Security
    , Website -> Robots
websiteRobots :: Robots
    , Website -> Trust
websiteTrust :: Trust
    , Website -> FeedConfig
websiteFeed :: FeedConfig
    }
    deriving (Website -> Website -> Bool
(Website -> Website -> Bool)
-> (Website -> Website -> Bool) -> Eq Website
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Website -> Website -> Bool
== :: Website -> Website -> Bool
$c/= :: Website -> Website -> Bool
/= :: Website -> Website -> Bool
Eq, Int -> Website -> ShowS
[Website] -> ShowS
Website -> [Char]
(Int -> Website -> ShowS)
-> (Website -> [Char]) -> ([Website] -> ShowS) -> Show Website
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Website -> ShowS
showsPrec :: Int -> Website -> ShowS
$cshow :: Website -> [Char]
show :: Website -> [Char]
$cshowList :: [Website] -> ShowS
showList :: [Website] -> ShowS
Show)

instance FromJSON Site where
    parseJSON :: Value -> Parser Site
parseJSON = [Char] -> (Object -> Parser Site) -> Value -> Parser Site
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"site" ((Object -> Parser Site) -> Value -> Parser Site)
-> (Object -> Parser Site) -> Value -> Parser Site
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char] -> [Char] -> [Char] -> Int -> [Char] -> [Char] -> Site
Site
            ([Char] -> [Char] -> [Char] -> Int -> [Char] -> [Char] -> Site)
-> Parser [Char]
-> Parser ([Char] -> [Char] -> Int -> [Char] -> [Char] -> Site)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
            Parser ([Char] -> [Char] -> Int -> [Char] -> [Char] -> Site)
-> Parser [Char]
-> Parser ([Char] -> Int -> [Char] -> [Char] -> Site)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"description"
            Parser ([Char] -> Int -> [Char] -> [Char] -> Site)
-> Parser [Char] -> Parser (Int -> [Char] -> [Char] -> Site)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"author"
            Parser (Int -> [Char] -> [Char] -> Site)
-> Parser Int -> Parser ([Char] -> [Char] -> Site)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Int
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"copyrightYear"
            Parser ([Char] -> [Char] -> Site)
-> Parser [Char] -> Parser ([Char] -> Site)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"domain"
            Parser ([Char] -> Site) -> Parser [Char] -> Parser Site
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"twitterHandle"

instance FromJSON Contact where
    parseJSON :: Value -> Parser Contact
parseJSON = [Char] -> (Object -> Parser Contact) -> Value -> Parser Contact
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"contact" ((Object -> Parser Contact) -> Value -> Parser Contact)
-> (Object -> Parser Contact) -> Value -> Parser Contact
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char] -> [Char] -> Contact
Contact ([Char] -> [Char] -> Contact)
-> Parser [Char] -> Parser ([Char] -> Contact)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"email" Parser ([Char] -> Contact) -> Parser [Char] -> Parser Contact
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"page"

instance FromJSON Manifest where
    parseJSON :: Value -> Parser Manifest
parseJSON = [Char] -> (Object -> Parser Manifest) -> Value -> Parser Manifest
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"manifest" ((Object -> Parser Manifest) -> Value -> Parser Manifest)
-> (Object -> Parser Manifest) -> Value -> Parser Manifest
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char] -> [Char] -> Manifest
Manifest ([Char] -> [Char] -> Manifest)
-> Parser [Char] -> Parser ([Char] -> Manifest)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"backgroundColor" Parser ([Char] -> Manifest) -> Parser [Char] -> Parser Manifest
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"themeColor"

instance FromJSON Mathjax where
    parseJSON :: Value -> Parser Mathjax
parseJSON = [Char] -> (Object -> Parser Mathjax) -> Value -> Parser Mathjax
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"mathjax" ((Object -> Parser Mathjax) -> Value -> Parser Mathjax)
-> (Object -> Parser Mathjax) -> Value -> Parser Mathjax
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char] -> Mathjax
Mathjax ([Char] -> Mathjax) -> Parser [Char] -> Parser Mathjax
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"version"

instance FromJSON Funding where
    parseJSON :: Value -> Parser Funding
parseJSON = [Char] -> (Object -> Parser Funding) -> Value -> Parser Funding
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"funding" ((Object -> Parser Funding) -> Value -> Parser Funding)
-> (Object -> Parser Funding) -> Value -> Parser Funding
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        FundingEntity
-> [FundingProject] -> [FundingChannel] -> [FundingPlan] -> Funding
Funding
            (FundingEntity
 -> [FundingProject]
 -> [FundingChannel]
 -> [FundingPlan]
 -> Funding)
-> Parser FundingEntity
-> Parser
     ([FundingProject] -> [FundingChannel] -> [FundingPlan] -> Funding)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser FundingEntity
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"entity"
            Parser
  ([FundingProject] -> [FundingChannel] -> [FundingPlan] -> Funding)
-> Parser [FundingProject]
-> Parser ([FundingChannel] -> [FundingPlan] -> Funding)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [FundingProject]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"projects"
            Parser ([FundingChannel] -> [FundingPlan] -> Funding)
-> Parser [FundingChannel] -> Parser ([FundingPlan] -> Funding)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [FundingChannel]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"channels"
            Parser ([FundingPlan] -> Funding)
-> Parser [FundingPlan] -> Parser Funding
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [FundingPlan]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"plans"

instance FromJSON FeedConfig where
    parseJSON :: Value -> Parser FeedConfig
parseJSON = [Char]
-> (Object -> Parser FeedConfig) -> Value -> Parser FeedConfig
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"feed" ((Object -> Parser FeedConfig) -> Value -> Parser FeedConfig)
-> (Object -> Parser FeedConfig) -> Value -> Parser FeedConfig
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        Int -> FeedConfig
FeedConfig (Int -> FeedConfig) -> Parser Int -> Parser FeedConfig
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser Int
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"size"

instance FromJSON FundingEntity where
    parseJSON :: Value -> Parser FundingEntity
parseJSON = [Char]
-> (Object -> Parser FundingEntity)
-> Value
-> Parser FundingEntity
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"funding.entity" ((Object -> Parser FundingEntity) -> Value -> Parser FundingEntity)
-> (Object -> Parser FundingEntity)
-> Value
-> Parser FundingEntity
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char] -> [Char] -> FundingEntity
FundingEntity ([Char] -> [Char] -> FundingEntity)
-> Parser [Char] -> Parser ([Char] -> FundingEntity)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"email" Parser ([Char] -> FundingEntity)
-> Parser [Char] -> Parser FundingEntity
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"description"

instance FromJSON FundingProject where
    parseJSON :: Value -> Parser FundingProject
parseJSON = [Char]
-> (Object -> Parser FundingProject)
-> Value
-> Parser FundingProject
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"funding.project" ((Object -> Parser FundingProject)
 -> Value -> Parser FundingProject)
-> (Object -> Parser FundingProject)
-> Value
-> Parser FundingProject
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char]
-> [Char]
-> [Char]
-> [Char]
-> [Char]
-> [[Char]]
-> [[Char]]
-> FundingProject
FundingProject
            ([Char]
 -> [Char]
 -> [Char]
 -> [Char]
 -> [Char]
 -> [[Char]]
 -> [[Char]]
 -> FundingProject)
-> Parser [Char]
-> Parser
     ([Char]
      -> [Char]
      -> [Char]
      -> [Char]
      -> [[Char]]
      -> [[Char]]
      -> FundingProject)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"guid"
            Parser
  ([Char]
   -> [Char]
   -> [Char]
   -> [Char]
   -> [[Char]]
   -> [[Char]]
   -> FundingProject)
-> Parser [Char]
-> Parser
     ([Char]
      -> [Char] -> [Char] -> [[Char]] -> [[Char]] -> FundingProject)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
            Parser
  ([Char]
   -> [Char] -> [Char] -> [[Char]] -> [[Char]] -> FundingProject)
-> Parser [Char]
-> Parser
     ([Char] -> [Char] -> [[Char]] -> [[Char]] -> FundingProject)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"description"
            Parser ([Char] -> [Char] -> [[Char]] -> [[Char]] -> FundingProject)
-> Parser [Char]
-> Parser ([Char] -> [[Char]] -> [[Char]] -> FundingProject)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"repositoryUrl"
            Parser ([Char] -> [[Char]] -> [[Char]] -> FundingProject)
-> Parser [Char] -> Parser ([[Char]] -> [[Char]] -> FundingProject)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"repositoryWellKnown"
            Parser ([[Char]] -> [[Char]] -> FundingProject)
-> Parser [[Char]] -> Parser ([[Char]] -> FundingProject)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [[Char]]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"licenses"
            Parser ([[Char]] -> FundingProject)
-> Parser [[Char]] -> Parser FundingProject
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [[Char]]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"tags"

instance FromJSON FundingChannel where
    parseJSON :: Value -> Parser FundingChannel
parseJSON = [Char]
-> (Object -> Parser FundingChannel)
-> Value
-> Parser FundingChannel
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"funding.channel" ((Object -> Parser FundingChannel)
 -> Value -> Parser FundingChannel)
-> (Object -> Parser FundingChannel)
-> Value
-> Parser FundingChannel
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char] -> [Char] -> [Char] -> [Char] -> FundingChannel
FundingChannel
            ([Char] -> [Char] -> [Char] -> [Char] -> FundingChannel)
-> Parser [Char]
-> Parser ([Char] -> [Char] -> [Char] -> FundingChannel)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"guid"
            Parser ([Char] -> [Char] -> [Char] -> FundingChannel)
-> Parser [Char] -> Parser ([Char] -> [Char] -> FundingChannel)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
            Parser ([Char] -> [Char] -> FundingChannel)
-> Parser [Char] -> Parser ([Char] -> FundingChannel)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"address"
            Parser ([Char] -> FundingChannel)
-> Parser [Char] -> Parser FundingChannel
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"description"

instance FromJSON FundingPlan where
    parseJSON :: Value -> Parser FundingPlan
parseJSON = [Char]
-> (Object -> Parser FundingPlan) -> Value -> Parser FundingPlan
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"funding.plan" ((Object -> Parser FundingPlan) -> Value -> Parser FundingPlan)
-> (Object -> Parser FundingPlan) -> Value -> Parser FundingPlan
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char]
-> [Char]
-> [Char]
-> [Char]
-> Int
-> [Char]
-> [Char]
-> [[Char]]
-> FundingPlan
FundingPlan
            ([Char]
 -> [Char]
 -> [Char]
 -> [Char]
 -> Int
 -> [Char]
 -> [Char]
 -> [[Char]]
 -> FundingPlan)
-> Parser [Char]
-> Parser
     ([Char]
      -> [Char]
      -> [Char]
      -> Int
      -> [Char]
      -> [Char]
      -> [[Char]]
      -> FundingPlan)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"guid"
            Parser
  ([Char]
   -> [Char]
   -> [Char]
   -> Int
   -> [Char]
   -> [Char]
   -> [[Char]]
   -> FundingPlan)
-> Parser [Char]
-> Parser
     ([Char]
      -> [Char] -> Int -> [Char] -> [Char] -> [[Char]] -> FundingPlan)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"status"
            Parser
  ([Char]
   -> [Char] -> Int -> [Char] -> [Char] -> [[Char]] -> FundingPlan)
-> Parser [Char]
-> Parser
     ([Char] -> Int -> [Char] -> [Char] -> [[Char]] -> FundingPlan)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
            Parser
  ([Char] -> Int -> [Char] -> [Char] -> [[Char]] -> FundingPlan)
-> Parser [Char]
-> Parser (Int -> [Char] -> [Char] -> [[Char]] -> FundingPlan)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"description"
            Parser (Int -> [Char] -> [Char] -> [[Char]] -> FundingPlan)
-> Parser Int
-> Parser ([Char] -> [Char] -> [[Char]] -> FundingPlan)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Int
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"amount"
            Parser ([Char] -> [Char] -> [[Char]] -> FundingPlan)
-> Parser [Char] -> Parser ([Char] -> [[Char]] -> FundingPlan)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"currency"
            Parser ([Char] -> [[Char]] -> FundingPlan)
-> Parser [Char] -> Parser ([[Char]] -> FundingPlan)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"frequency"
            Parser ([[Char]] -> FundingPlan)
-> Parser [[Char]] -> Parser FundingPlan
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [[Char]]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"channels"

instance FromJSON Security where
    parseJSON :: Value -> Parser Security
parseJSON = [Char] -> (Object -> Parser Security) -> Value -> Parser Security
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"security" ((Object -> Parser Security) -> Value -> Parser Security)
-> (Object -> Parser Security) -> Value -> Parser Security
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        [Char] -> [Char] -> Int -> Security
Security
            ([Char] -> [Char] -> Int -> Security)
-> Parser [Char] -> Parser ([Char] -> Int -> Security)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"preferredLanguages"
            Parser ([Char] -> Int -> Security)
-> Parser [Char] -> Parser (Int -> Security)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"expires"
            Parser (Int -> Security) -> Parser Int -> Parser Security
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Int
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"expirationMarginDays"

instance FromJSON Robots where
    parseJSON :: Value -> Parser Robots
parseJSON = [Char] -> (Object -> Parser Robots) -> Value -> Parser Robots
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"robots" ((Object -> Parser Robots) -> Value -> Parser Robots)
-> (Object -> Parser Robots) -> Value -> Parser Robots
forall a b. (a -> b) -> a -> b
$ \Object
o -> [[Char]] -> Robots
Robots ([[Char]] -> Robots) -> Parser [[Char]] -> Parser Robots
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [[Char]]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"disallow"

instance FromJSON Trust where
    parseJSON :: Value -> Parser Trust
parseJSON = [Char] -> (Object -> Parser Trust) -> Value -> Parser Trust
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"trust" ((Object -> Parser Trust) -> Value -> Parser Trust)
-> (Object -> Parser Trust) -> Value -> Parser Trust
forall a b. (a -> b) -> a -> b
$ \Object
o -> [Char] -> Trust
Trust ([Char] -> Trust) -> Parser [Char] -> Parser Trust
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"trainingAllowed"

instance FromJSON Website where
    parseJSON :: Value -> Parser Website
parseJSON = [Char] -> (Object -> Parser Website) -> Value -> Parser Website
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"website" ((Object -> Parser Website) -> Value -> Parser Website)
-> (Object -> Parser Website) -> Value -> Parser Website
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        Site
-> Contact
-> Manifest
-> Mathjax
-> Highlight
-> Funding
-> Security
-> Robots
-> Trust
-> FeedConfig
-> Website
Website
            (Site
 -> Contact
 -> Manifest
 -> Mathjax
 -> Highlight
 -> Funding
 -> Security
 -> Robots
 -> Trust
 -> FeedConfig
 -> Website)
-> Parser Site
-> Parser
     (Contact
      -> Manifest
      -> Mathjax
      -> Highlight
      -> Funding
      -> Security
      -> Robots
      -> Trust
      -> FeedConfig
      -> Website)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser Site
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"site"
            Parser
  (Contact
   -> Manifest
   -> Mathjax
   -> Highlight
   -> Funding
   -> Security
   -> Robots
   -> Trust
   -> FeedConfig
   -> Website)
-> Parser Contact
-> Parser
     (Manifest
      -> Mathjax
      -> Highlight
      -> Funding
      -> Security
      -> Robots
      -> Trust
      -> FeedConfig
      -> Website)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Contact
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"contact"
            Parser
  (Manifest
   -> Mathjax
   -> Highlight
   -> Funding
   -> Security
   -> Robots
   -> Trust
   -> FeedConfig
   -> Website)
-> Parser Manifest
-> Parser
     (Mathjax
      -> Highlight
      -> Funding
      -> Security
      -> Robots
      -> Trust
      -> FeedConfig
      -> Website)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Manifest
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"manifest"
            Parser
  (Mathjax
   -> Highlight
   -> Funding
   -> Security
   -> Robots
   -> Trust
   -> FeedConfig
   -> Website)
-> Parser Mathjax
-> Parser
     (Highlight
      -> Funding -> Security -> Robots -> Trust -> FeedConfig -> Website)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Mathjax
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"mathjax"
            Parser
  (Highlight
   -> Funding -> Security -> Robots -> Trust -> FeedConfig -> Website)
-> Parser Highlight
-> Parser
     (Funding -> Security -> Robots -> Trust -> FeedConfig -> Website)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Highlight
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"highlight"
            Parser
  (Funding -> Security -> Robots -> Trust -> FeedConfig -> Website)
-> Parser Funding
-> Parser (Security -> Robots -> Trust -> FeedConfig -> Website)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Funding
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"funding"
            Parser (Security -> Robots -> Trust -> FeedConfig -> Website)
-> Parser Security
-> Parser (Robots -> Trust -> FeedConfig -> Website)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Security
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"security"
            Parser (Robots -> Trust -> FeedConfig -> Website)
-> Parser Robots -> Parser (Trust -> FeedConfig -> Website)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Robots
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"robots"
            Parser (Trust -> FeedConfig -> Website)
-> Parser Trust -> Parser (FeedConfig -> Website)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Trust
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"trust"
            Parser (FeedConfig -> Website)
-> Parser FeedConfig -> Parser Website
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser FeedConfig
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"feed"

-- | Reads and parses @<contentDir>/website.yaml@, failing with a clear message
loadWebsite :: FilePath -> IO Website
loadWebsite :: [Char] -> IO Website
loadWebsite [Char]
contentDir = do
    let path :: [Char]
path = [Char]
contentDir [Char] -> ShowS
</> [Char]
"website.yaml"
    exists <- [Char] -> IO Bool
doesFileExist [Char]
path
    unless exists $ die $ path ++ " not found"
    result <- decodeFileEither path
    either (\ParseException
e -> [Char] -> IO Website
forall a. [Char] -> IO a
die ([Char] -> IO Website) -> [Char] -> IO Website
forall a b. (a -> b) -> a -> b
$ [Char]
"Invalid " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
path [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
":\n" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ ParseException -> [Char]
prettyPrintParseException ParseException
e) pure result

-- | Fails if the @security.txt@ expiration is within the configured margin (or already passed)
validateSecurityExpiration :: Website -> IO ()
validateSecurityExpiration :: Website -> IO ()
validateSecurityExpiration Website
website = do
    today <- UTCTime -> Day
utctDay (UTCTime -> Day) -> IO UTCTime -> IO Day
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO UTCTime
getCurrentTime
    let security = Website -> Security
websiteSecurity Website
website
        margin = Security -> Int
securityExpirationMarginDays Security
security
        deadline = Integer -> Day -> Day
addDays (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
margin) Day
today
    case parseExpiryDate (securityExpires security) of
        Maybe Day
Nothing -> [Char] -> IO ()
forall a. [Char] -> IO a
die ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Invalid security.expires date: " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Security -> [Char]
securityExpires Security
security
        Just Day
expires ->
            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Day
expires Day -> Day -> Bool
forall a. Ord a => a -> a -> Bool
<= Day
deadline)
                (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> IO ()
forall a. [Char] -> IO a
die
                ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"security.txt expires on " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Day -> [Char]
forall a. Show a => a -> [Char]
show Day
expires [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" (within " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
margin [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" days); renew it"

-- | Parses the leading @YYYY-MM-DD@ of an ISO timestamp
parseExpiryDate :: String -> Maybe Day
parseExpiryDate :: [Char] -> Maybe Day
parseExpiryDate = Bool -> TimeLocale -> [Char] -> [Char] -> Maybe Day
forall (m :: * -> *) t.
(MonadFail m, ParseTime t) =>
Bool -> TimeLocale -> [Char] -> [Char] -> m t
parseTimeM Bool
True TimeLocale
defaultTimeLocale [Char]
"%Y-%m-%d" ([Char] -> Maybe Day) -> ShowS -> [Char] -> Maybe Day
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
forall a. Int -> [a] -> [a]
take Int
10