{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TupleSections #-} module Kurita.Bot.Connection where import Control.Monad (forever) import Control.Monad.Except import Data.Bifunctor import qualified Data.Aeson as Aeson import qualified Data.ByteString.Char8 as Char8 import URI.ByteString import Network.Linklater import Network.Linklater.Types import qualified Network.WebSockets as WS import qualified Wuss as Wuss import Kurita.Bot.Types startBot :: BotConfig -> (BotEvent -> IO ()) -> IO () startBot token onCommand = do sockUri <- runExceptT fetchRTMUri case (\uri -> (getUriPath uri,) <$> uriHost uri) =<< (first show sockUri) of Right (path, host) -> do Wuss.runSecureClient host 443 path $ app onCommand pure () Left err -> error err pure () where fetchRTMUri :: ExceptT RequestError IO URI fetchRTMUri = startRTM $ botConfigToken token uriHost :: URI -> Either String String uriHost = maybe (Left "Unable to find uri authority") (Right . Char8.unpack) . fmap (hostBS . authorityHost) . uriAuthority getUriPath :: URI -> String getUriPath = Char8.unpack . uriPath app :: (BotEvent -> IO ()) -> WS.ClientApp () app onCommand conn = do putStrLn "Slack bot connected!" forever $ do msg <- WS.receiveData conn let botMessage :: Either String BotEvent botMessage = Aeson.eitherDecode' msg either (const $ pure ()) onCommand botMessage