packages feed

kevin-0.9.0: Kevin/Base.hs

module Kevin.Base (
    module Kevin.Types,
    KevinException(..),
    _KevinException,
    KevinServer(..),
    User(..),

    module K,

    io,
    runPrinter,

    printf
) where

import Control.Applicative ((<$>))
import Control.Concurrent as K (forkIO)
import Control.Concurrent.Chan as K
import Control.Concurrent.STM.TVar as K
import Control.Exception
import Control.Exception as K (IOException)
import Control.Exception.Lens
import Control.Lens as K
import Control.Monad.CatchIO as K
import Control.Monad.Reader as K
import qualified Data.ByteString.Char8 as T (hGetLine, hPutStr)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Typeable
import Kevin.Chatrooms as K
import Kevin.Settings as K
import Kevin.Types
import Kevin.Util.Logger
import Network as K
import System.IO as K
import System.IO.Error

runPrinter :: Chan T.Text -> Handle -> IO ()
runPrinter ch h = void . forkIO . forever $ readChan ch >>= T.hPutStr h . T.encodeUtf8

io :: MonadIO m => IO a -> m a
io = liftIO

class KevinServer a where
    readClient, readServer   :: a -> IO T.Text
    writeServer              :: a -> T.Text -> IO ()
    writeClient              :: a -> T.Text -> IO ()
    closeClient, closeServer :: a -> IO ()

data KevinException = ParseFailure
    deriving (Show, Typeable)

instance Exception KevinException

_KevinException :: Prism' SomeException KevinException
_KevinException = exception

-- actions

hGetCharTimeout :: Handle -> Int -> IO Char
hGetCharTimeout h t = do hSetBuffering h NoBuffering
                         ready <- hWaitForInput h t
                         if ready
                            then hGetChar h
                            else throwIO $ mkIOError eofErrorType "read timeout" (Just h) Nothing

hGetSep :: Char -> Handle -> IO String
hGetSep sep h = fix (\f -> do ch <- hGetCharTimeout h 180000
                              if ch == sep
                                 then return ""
                                 else (ch:) <$> f)

instance KevinServer Kevin where
    readClient k = do line <- T.decodeUtf8 <$> T.hGetLine (irc k)
                      return $ T.init line
    readServer k = T.pack <$> hGetSep '\NUL' (damn k)

    writeClient k = writeChan (iChan k)
    writeServer k = writeChan (dChan k)

    closeClient = hClose . irc
    closeServer = hClose . damn