module HelpEsbClient (
EsbSend
, EsbRecieve
, EsbSendExternal
, EsbRecieveExternal
, getSocket
, sendSocketData
, readSocketDataRaw
, readSocketData
, esbSend
, esbRecieve
, esbSendExternal
, esbRecieveExternal
, esbInit
, esbListen
, encode
, decode
, eitherDecode
, logger
, forM_
, Socket
, module Data.UUID
, module Data.UUID.V4
, module System.Environment
, module Control.Monad
) where
import System.IO
import System.Environment
import Network.Socket
import Network.URI
import Control.Exception
import Control.Monad
import GHC.Generics
import Data.Maybe
import Data.Map
import Data.Text hiding (replace, tail, drop, reverse)
import Data.List.Utils
import Data.UUID
import Data.UUID.V4
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as C
import qualified JSON.Basic.Response as Basic.Response
import qualified JSON.Login.Request as Login.Request
import qualified JSON.Login.Response as Login.Response
import qualified JSON.API.EventGroup.Post.Request as EventGroup.Post.Request
import qualified JSON.API.Event.Post.Request as Event.Post.Request
class EsbSend a where
esbSend :: Socket
-> a
-> IO ()
class EsbSendExternal a b where
esbSendExternal :: Socket
-> a
-> b
-> IO ()
class EsbRecieve a where
esbRecieve :: Socket
-> a
-> IO ()
class EsbRecieveExternal a b where
esbRecieveExternal :: Socket
-> a
-> b
-> IO ()
logger :: String
-> IO ()
logger out = do
let logPrefix = "# "
putStrLn $ logPrefix ++ out
getSocket :: String
-> Int
-> IO Socket
getSocket host port = withSocketsDo $ do
(serveraddr:_) <- getAddrInfo Nothing (Just host) (Just (show port))
sock <- socket (addrFamily serveraddr) Stream defaultProtocol
connect sock (addrAddress serveraddr) >> return sock
sendSocketData :: Socket
-> C.ByteString
-> IO ()
sendSocketData sock bytes = do
let json = replace "h_" "" (C.unpack bytes)
send sock (json ++ "\n")
logger ("+ Raw Send: " ++ json)
readSocketDataRaw :: Socket
-> IO [Char]
readSocketDataRaw sock = do
message <- recv sock 4096
logger ("+ Raw Read: " ++ message)
return message
readSocketData :: Socket
-> IO (C.ByteString)
readSocketData sock = do
raw <- readSocketDataRaw sock
let fixed = replace ",\"" ",\"h_" (replace "{\"" "{\"h_" raw)
return $ C.pack fixed
instance EsbSend Login.Request.Data where
esbSend sock payload = do
uuid <- nextRandom
let meta = Login.Request.Meta {
Login.Request.h_type = "login"
, Login.Request.h_id = toString uuid
}
let message = Login.Request.Message {
Login.Request.h_meta = meta
, Login.Request.h_data = payload
}
sendSocketData sock (encode message)
logger ("Login Request: " ++ show message)
instance EsbSend EventGroup.Post.Request.Data where
esbSend sock payload = do
uuid <- nextRandom
let meta = EventGroup.Post.Request.Meta {
EventGroup.Post.Request.h_type = "sendMessage"
, EventGroup.Post.Request.h_id = toString uuid
, EventGroup.Post.Request.h_group = "api-messages"
}
let message = EventGroup.Post.Request.Message {
EventGroup.Post.Request.h_meta = meta
, EventGroup.Post.Request.h_data = payload
}
sendSocketData sock (encode message)
logger ("EventGroup API Request: " ++ show message)
instance EsbSend Event.Post.Request.Data where
esbSend sock payload = do
uuid <- nextRandom
let meta = Event.Post.Request.Meta {
Event.Post.Request.h_type = "sendMessage"
, Event.Post.Request.h_id = toString uuid
, Event.Post.Request.h_group = "api-messages"
}
let message = Event.Post.Request.Message {
Event.Post.Request.h_meta = meta
, Event.Post.Request.h_data = payload
}
sendSocketData sock (encode message)
logger ("Event API Request: " ++ show message)
instance EsbRecieve Login.Response.Message where
esbRecieve sock message = do
let payload = Login.Response.h_meta message
case Login.Response.h_result payload of
"SUCCESS" -> logger ("Successfully logged in.")
_ -> error "! Failed to login!"
esbInit :: Text
-> [Text]
-> Maybe String
-> Maybe Int
-> IO Socket
esbInit name subscriptions maybeHost maybePort = do
let argHost = fromMaybe "Nothing" maybeHost
let argPort = fromMaybe 0 maybePort
envVars <- getEnvironment
let envMap = Data.Map.fromList envVars
let envUriString = fromMaybe "tcp://127.0.0.1:8900" (Data.Map.lookup "ESB" envMap)
let envUri = fromMaybe nullURI (parseURI envUriString)
let defaultUriAuth = URIAuth {
uriUserInfo = ""
, uriRegName = "127.0.0.1"
, uriPort = ":8900"
}
let envUriAuth = fromMaybe defaultUriAuth (uriAuthority envUri)
let host = if argHost /= "Nothing" then argHost else uriRegName envUriAuth
let port = if argPort /= 0 then argPort else read (tail (uriPort envUriAuth))
sock <- getSocket host port
let loginData = Login.Request.Data { Login.Request.h_name = name, Login.Request.h_subscriptions = subscriptions }
esbSend sock loginData
return sock
esbListen :: Socket
-> IO ([C.ByteString])
esbListen sock = do
bytes <- readSocketData sock
let messages = C.split '\n' bytes
forM_ messages $ \message -> do
case eitherDecode bytes :: (Either String Login.Response.Message) of
Left error -> return ()
Right response -> do
logger ("Response: " ++ show response)
esbRecieve sock response
return messages