{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} {- | Description : Haskell server for Facebook's react-tutorial. Copyright : (c) Alexander Berntsen 2016 License : AGPL-3 Maintainer : alexander@plaimi.net -} import Control.Monad.IO.Class (liftIO) import Data.ByteString (readFile) import Data.ByteString.Lazy (fromStrict, writeFile) import Data.Aeson (FromJSON, ToJSON, decode) import Data.Aeson.Encode.Pretty (Config (Config), encodePretty', keyOrder) import Data.Time.Clock.POSIX (getPOSIXTime) import GHC.Generics (Generic) import Web.Scotty (ActionM, ScottyM, file, get, json, param, post, setHeader ,scotty) import Prelude hiding (id, readFile, writeFile) data Comment = C { id :: Int, author :: String, text :: String } deriving (Generic, Show) instance FromJSON Comment instance ToJSON Comment postComments :: ActionM () postComments = do cs <- readComments i <- liftIO $ round . (* 1000) <$> getPOSIXTime a <- param "author" t <- param "text" let cs' = (++ [C { id = i, author = a, text = t }]) <$> cs liftIO $ writeFile "comments.json" $ encodePretty' (Config 4 (keyOrder ["id", "author", "text"])) cs' presentComments cs' getComments :: ActionM () getComments = presentComments =<< readComments presentComments :: Maybe [Comment] -> ActionM () presentComments cs = do setHeader "Cache-Control" "no-cache" setHeader "Access-Control-Allow-Origin" "*" json cs readComments :: ActionM (Maybe [Comment]) readComments = do f <- liftIO $ readFile "comments.json" let cs = decode (fromStrict f) :: Maybe [Comment] pure cs app :: ScottyM () app = do get "/" $ setHeader "Content-Type" "text/html" >> file "public/index.html" get "/css/base.css" $ file "public/css/base.css" get "/scripts/example.js" $ file "public/scripts/example.js" get "/api/comments" getComments post "/api/comments" postComments main :: IO () main = scotty 3000 app