{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveGeneric #-} module Quenya.Web where import GHC.Generics import Web.Scotty import Quenya.Conjugator (conjugate) import qualified Quenya.Conjugator as C import Quenya.Conversion import Quenya.Arguments (getArgs) import Data.Monoid (mconcat) import Data.Aeson hiding (json, object) import qualified Data.Aeson as A (object) import Data.Maybe (fromMaybe) import Control.Monad import Control.Applicative ((<$>), (<*>), pure) import qualified Data.ByteString.Lazy as BS import Network.Wai.Handler.Warp import Network.Wai (Application(..)) import Safe (atMay) import qualified Data.Map as M (fromList, Map(..)) import qualified Data.Text as T import qualified Data.Text.Lazy.IO as T import Data.Word (Word16(..)) import Network.Socket import Control.Monad.IO.Class (liftIO) import Network import Data.IP import Network.Wai.Middleware.RequestLogger import Network.Wai.Middleware.Static -- | Runs 'application' as a Warp app main :: IO () main = do (port, addr, logging) <- getArgs let sett = {-setHost (addr :: HostPreference) $-} setPort port defaultSettings app <- application logging runSettings sett app -- | Converts the Scotty app to a Warp app, for ease of deployment application :: Bool -> IO Application application logging = scottyApp $ do i <- liftIO (T.readFile "index.html") if logging then middleware logStdoutDev else return () middleware $ staticPolicy (hasPrefix "static") post "/api/verb" $ do b <- body json $ respond b get "/" $ html i -- | Takes the raw body of a request and returns a JSONable response respond :: BS.ByteString -> M.Map String String respond b = M.fromList [("conjugated_verb", conjugate $ toVerb $ fromMaybe defaultStringVerb $ (decode b :: Maybe StringVerb))] -- | The "raw" (i.e. without ADTs) verb data type. Only use for interacting with the user. data StringVerb = StringVerb { stem :: String , tense :: String , subject :: String , object :: String } deriving (Show, Generic) instance FromJSON StringVerb -- | Arbitrary default verb, meaning "I love you" defaultStringVerb :: StringVerb defaultStringVerb = StringVerb "mel" "aorist" "you" "me" -- | Converts a 'StringVerb' to a 'C.Verb' using the functions in 'Quenya.Conversion' toVerb :: StringVerb -> C.Verb toVerb sv = C.Verb st te su ob where st = makeStem $ stem sv te = fromMaybe C.Present $ makeTense $ tense sv su = fromMaybe C.FstSg $ makePerson $ subject sv ob = fromMaybe C.SndFamiliarSg $ makePerson $ object sv