aboutsummaryrefslogtreecommitdiff
path: root/app/Main.hs
blob: b62e614dd9a2c4565126df3575b9f1ecf4e89449 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
module Main
  ( main
  ) where

import RIO

import Data.Conduit (runConduit, (.|))
import Data.Conduit.Attoparsec (sinkParser)
import Network.HTTP.Types (status200, status500)
import Network.Wai (responseBuilder, responseLBS, Response)
import Network.Wai.Conduit (sourceRequestBody)
import Network.Wai.Handler.Warp (run)
import System.Environment (getArgs)

import Tomato.App (runApp)
import Tomato.Bot (tomatoBot)
import Tomato.Data.Except (DecodeException (..))
import Tomato.Data.Message (InMessage (..))
import Tomato.Validate (isTomato)

import qualified Data.Aeson as Ae
import qualified Data.ByteString.Lazy.Char8 as BL8
import qualified RIO.List.Partial as L'
import qualified RIO.Text as T

-- | Listen for tomato message and respond with tomato
runServer :: Int -> IO ()
runServer port = run port $ \request send -> do
    eres <- tryAnyDeep $ do
      val <- runConduit
           $ sourceRequestBody request
          .| sinkParser Ae.json
      case Ae.fromJSON val of
          Ae.Success r -> return r
          Ae.Error s -> throwM $ DecodeException $ T.pack s
    case eres of
      Left e -> send $ errorResponse e
      Right inMes -> do
          when (isTomato inMes) $ runApp tomatoBot
          send $ validResponse inMes
  where
    errorResponse :: SomeException -> Response
    errorResponse e = responseLBS
        status500
        [("Content-Type", "text/plain")]
        $ BL8.pack $ "Exception occurred: " ++ show e
    validResponse :: InMessage -> Response
    validResponse inMes = responseBuilder
        status200
        [("Content-Type", "application/json")]
        $ Ae.fromEncoding $ Ae.toEncoding $ text inMes

main :: IO ()
main = do
    args <- getArgs
    when (null args) (error "no port")
    let portS = readMaybe $ L'.head args
    let port = maybe (error "invalid port") id portS
    runServer port