|
|
|
@ -6,7 +6,9 @@ import qualified Data.Text as T |
|
|
|
|
|
|
|
|
|
import Control.Exception |
|
|
|
|
import Control.Concurrent |
|
|
|
|
import Control.Monad |
|
|
|
|
import Control.Monad.Reader |
|
|
|
|
import Control.Monad.State |
|
|
|
|
import Network |
|
|
|
|
import Prelude hiding (log, catch) |
|
|
|
|
import System.IO |
|
|
|
@ -18,13 +20,8 @@ import Network.IRC.Handlers |
|
|
|
|
import Network.IRC.Protocol |
|
|
|
|
import Network.IRC.Types |
|
|
|
|
|
|
|
|
|
data Status = Connected | Disconnected | Joined | Kicked | Errored |
|
|
|
|
deriving (Show, Eq) |
|
|
|
|
|
|
|
|
|
oneSec = 1000000 |
|
|
|
|
|
|
|
|
|
io = liftIO |
|
|
|
|
|
|
|
|
|
log msg = getClockTime >>= \t -> printf "[%s] ** %s\n" (show t) msg |
|
|
|
|
|
|
|
|
|
sendCommand :: Bot -> Command -> IO () |
|
|
|
@ -32,39 +29,40 @@ sendCommand Bot { .. } reply = do |
|
|
|
|
let line = T.unpack $ lineFromCommand botConfig reply |
|
|
|
|
hPrintf socket "%s\r\n" line >> printf "> %s\n" line |
|
|
|
|
|
|
|
|
|
listen :: Status -> IRC Status |
|
|
|
|
listen status = do |
|
|
|
|
listen :: IRC () |
|
|
|
|
listen = do |
|
|
|
|
status <- get |
|
|
|
|
bot@Bot { .. } <- ask |
|
|
|
|
let nick = botNick botConfig |
|
|
|
|
|
|
|
|
|
when (status == Kicked) $ |
|
|
|
|
io $ threadDelay (5 * oneSec) >> sendCommand bot JoinCmd |
|
|
|
|
|
|
|
|
|
mLine <- io . timeout (oneSec * botTimeout botConfig) . hGetLine $ socket |
|
|
|
|
case mLine of |
|
|
|
|
Nothing -> return Disconnected |
|
|
|
|
Just l -> do |
|
|
|
|
let line = init l |
|
|
|
|
time <- io getClockTime |
|
|
|
|
|
|
|
|
|
io $ printf "[%s] %s\n" (show time) line |
|
|
|
|
|
|
|
|
|
let message = msgFromLine botConfig time (T.pack line) |
|
|
|
|
nStatus <- io $ case message of |
|
|
|
|
JoinMsg { .. } | userNick user == nick -> log "Joined" >> return Joined |
|
|
|
|
KickMsg { .. } -> log "Kicked" >> return Kicked |
|
|
|
|
_ -> do |
|
|
|
|
forkIO $ case message of |
|
|
|
|
Ping { .. } -> sendCommand bot $ Pong msg |
|
|
|
|
ModeMsg { user = Self, .. } -> sendCommand bot JoinCmd |
|
|
|
|
msg -> forM_ (handlers botConfig) $ \handler -> do |
|
|
|
|
cmd <- handleMessage handler botConfig msg |
|
|
|
|
case cmd of |
|
|
|
|
Nothing -> return () |
|
|
|
|
Just cmd -> sendCommand bot cmd |
|
|
|
|
return status |
|
|
|
|
|
|
|
|
|
listen nStatus |
|
|
|
|
nStatus <- liftIO $ do |
|
|
|
|
when (status == Kicked) $ |
|
|
|
|
threadDelay (5 * oneSec) >> sendCommand bot JoinCmd |
|
|
|
|
|
|
|
|
|
mLine <- fmap (fmap init) . timeout (oneSec * botTimeout botConfig) . hGetLine $ socket |
|
|
|
|
case mLine of |
|
|
|
|
Nothing -> return Disconnected |
|
|
|
|
Just line -> do |
|
|
|
|
time <- getClockTime |
|
|
|
|
printf "[%s] %s\n" (show time) line |
|
|
|
|
|
|
|
|
|
let message = msgFromLine botConfig time (T.pack line) |
|
|
|
|
case message of |
|
|
|
|
JoinMsg { .. } | userNick user == nick -> log "Joined" >> return Joined |
|
|
|
|
KickMsg { .. } -> log "Kicked" >> return Kicked |
|
|
|
|
_ -> do |
|
|
|
|
forkIO $ case message of |
|
|
|
|
Ping { .. } -> sendCommand bot $ Pong msg |
|
|
|
|
ModeMsg { user = Self, .. } -> sendCommand bot JoinCmd |
|
|
|
|
msg -> forM_ (handlers botConfig) $ \handler -> forkIO $ do |
|
|
|
|
cmd <- runHandler (getHandler handler) botConfig msg |
|
|
|
|
case cmd of |
|
|
|
|
Nothing -> return () |
|
|
|
|
Just cmd -> sendCommand bot cmd |
|
|
|
|
return status |
|
|
|
|
|
|
|
|
|
put nStatus |
|
|
|
|
when (nStatus /= Disconnected) listen |
|
|
|
|
|
|
|
|
|
connect :: BotConfig -> IO Bot |
|
|
|
|
connect botConfig@BotConfig { .. } = do |
|
|
|
@ -104,4 +102,4 @@ run botConfig = withSocketsDo $ do |
|
|
|
|
go bot = do |
|
|
|
|
sendCommand bot NickCmd |
|
|
|
|
sendCommand bot UserCmd |
|
|
|
|
runReaderT (listen Connected) bot |
|
|
|
|
runIRC bot Connected listen |
|
|
|
|