packages feed

scrapbook-0.3.2: src/ScrapBook/Data/Site.hs

{-# LANGUAGE ConstraintKinds       #-}
{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedLabels      #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE TypeOperators         #-}

module ScrapBook.Data.Site
  ( Site
  , SiteFields
  , IsSiteFields
  , SiteId
  , AtomConfig
  , toAtomConfig
  , Post
  , Date
  , Url
  , toAbsoluteUrl
  , Summary (..)
  , summaryToText
  ) where

import           RIO
import qualified RIO.Text                     as T

import           Data.Aeson                   (ToJSON (..))
import qualified Data.Aeson                   as JSON
import           Data.Extensible
import           GHC.TypeLits                 (KnownSymbol)
import           ScrapBook.Internal.Instances (kvToJSON)
import           ScrapBook.Internal.Utils     (toHost)
import           Text.Atom.Feed               (Date)

type Site = Record SiteFields

type SiteFields =
  '[ "title"  >: Text
   , "author" >: Text
   , "url"    >: Url
   , "id"     >: SiteId
   ]

type IsSiteFields xs =
  ( Forall (KeyValue KnownSymbol (Instance1 ToJSON Identity)) xs
  , Associate "title" Text xs
  , Associate "author" Text xs
  , Associate "url" Url xs
  , Associate "id" SiteId xs
  )

type SiteId = Variant
  '[ "feed" >: Text
   , "atom" >: AtomConfig
   , "rss"  >: Text -- ^ RSS 2.0
   , "url"  >: Url
   ]

type AtomConfig = Record
  '[ "url"       >: Text
   , "linkAttrs" >: Maybe (Map Text Text)
   ]

toAtomConfig :: Url -> AtomConfig
toAtomConfig url = mempty & #url `set` url

type Post s = Record
  '[ "title"   >: Text
   , "url"     >: Url
   , "date"    >: Date
   , "summary" >: Maybe Summary
   , "site"    >: s
   ]

type Url = Text

data Summary
  = TextSummary Text
  | HtmlSummary Text
  deriving (Show, Eq)

instance ToJSON Summary where
  toJSON (TextSummary txt) = JSON.Object $ kvToJSON "text" txt
  toJSON (HtmlSummary txt) = JSON.Object $ kvToJSON "html" txt

summaryToText :: Summary -> Text
summaryToText (TextSummary txt) = txt
summaryToText (HtmlSummary txt) = txt

-- |
-- if url have prefix `/`, append base url
toAbsoluteUrl :: IsSiteFields xs => Record xs -> Url -> Url
toAbsoluteUrl site url =
  case T.uncons url of
    Just ('/', _) -> toHost (site ^. #url) `mappend` url
    _             -> url