aboutsummaryrefslogtreecommitdiff
path: root/app/Main.hs
blob: 1b403139d83a5bc13c9dd9a14a7f9dc892c60b8b (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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
module Main
  ( main
  ) where

import RIO

import Data.Conduit (runConduit, (.|))
import Data.Conduit.Attoparsec (sinkParser)
import Network.HTTP.Req
    ( jsonResponse
    , req
    , (=:)
    , NoReqBody (..)
    , (/:)
    , GET (..)
    , https
    , responseBody
    , Req
    , defaultHttpConfig
    , runReq
    )
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 Data.Message (InMessage (..))
import Data.Tomato (Tomato)
import Tomato.Post (postTomato)
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'


data App = App
    { appLogFunc :: !LogFunc
    , appToken   :: !Text
    , appBotId   :: !Text
    }

instance HasLogFunc App where
    logFuncL = lens appLogFunc (\x y -> x { appLogFunc = y })

runApp :: RIO App a -> IO a
runApp inner = do
  logOptions' <- logOptionsHandle stderr False
  -- let logOptions = setLogUseTime True $ setLogUseLoc True logOptions'
  let logOptions = logOptions'
  withLogFunc logOptions $ \logFunc -> do
    let app = App
          { appLogFunc = logFunc
          , appToken = "placeholder"
          , appBotId = "placeholder"
          }
    runRIO app inner

_randomTomato :: Req Tomato
_randomTomato = do
    let url = https "api.unsplash.com" /: "photos" /: "random"
    js <- req GET url NoReqBody jsonResponse $
        "query" =: ("tomato" :: Text) <>
        "client_id" =: ("FbzqI-oR7277JwL1ZGsyUw7yG1F5U0U3WhQ3kOW71Do" :: Text)
    tomato <- case Ae.fromJSON (responseBody js) of
        Ae.Success r -> pure r
        Ae.Error _s  -> error "deal with this later"
    return tomato

tomatoBot :: RIO App ()
tomatoBot = do
  logInfo $ "Fetching tomato"
  -- tomato <- runReq defaultHttpConfig randomTomato
  -- logInfo $ displayShow tomato
  -- url <- runReq defaultHttpConfig postTomato
  runReq defaultHttpConfig postTomato
  -- logInfo $ displayShow url
  logInfo $ "All done"

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
    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  -> error "handle this later"
        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