module Needles.Bot (runBot) where
import Control.Monad
import Control.Monad.Trans.State.Strict
import Control.Monad.IO.Class
import Control.Exception
import Data.ByteString (ByteString)
import Data.Map.Strict (empty)
import Needles.Bot.Message.Handle
import Needles.Bot.Configuration
import Needles.Bot.Message
import Needles.Bot.State
import qualified Network.WebSockets as WS
import Data.IORef
runBot :: Configuration -> IO ()
runBot config = do
WS.runClient (cServer config) (cPort config) (cPath config) (bot config)
bot :: Configuration -> WS.ClientApp ()
bot c conn = do
putStrLn "Connected"
(chan, _) <- mkPSQueue conn (const $ return () :: SomeException -> IO ())
let newBot = BotState { bName = cUsername c
, bPass = cPassword c
, bConn = conn
, bTriggers = cTriggers c
, bConfig = c
, bMessChan = chan
, bTimestamps = empty
}
backup <- newIORef newBot
catch (loop backup newBot) (\e -> const id (e :: SomeException) reinitialize backup)
loop :: IORef BotState -> BotState -> IO ()
loop backup thebot = flip evalStateT thebot . forever $ do
mess <- getData
handleBS mess
get >>= liftIO . writeIORef backup
getData :: StateT BotState IO ByteString
getData = get >>= liftIO . WS.receiveData . bConn
reinitialize :: IORef BotState -> IO ()
reinitialize backup = do
reclaim <- readIORef backup
let config = bConfig reclaim
WS.runClient (cServer config) (cPort config) (cPath config) (fixBot reclaim)
where fixBot oldBot conn = do
(queue, _) <- mkPSQueue conn (const $ return () :: SomeException -> IO ())
let newBot = oldBot { bConn = conn
, bMessChan = queue
}
writeIORef backup newBot
loop backup newBot