hask-irc/Network/IRC/Types.hs

116 lines
4.9 KiB
Haskell
Raw Normal View History

2014-05-13 00:00:33 +05:30
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
module Network.IRC.Types
(Channel, Nick, MsgHandlerName, User (..), Message (..), Command (..),
BotConfig (..), BotStatus (..), Bot (..), IRC, runIRC,
MsgHandler (..), MonadMsgHandler, newMsgHandler, runMsgHandler, stopMsgHandler)
where
2014-05-04 02:57:43 +05:30
2014-05-10 21:45:16 +05:30
import ClassyPrelude
2014-05-04 02:57:43 +05:30
import Control.Monad.Reader
import Control.Monad.State
import Data.Configurator.Types
2014-05-04 02:57:43 +05:30
type Channel = Text
type Nick = Text
type MsgHandlerName = Text
data User = Self | User { userNick :: !Nick, userServer :: !Text }
2014-05-04 02:57:43 +05:30
deriving (Show, Eq)
data Message =
IdleMsg
| ChannelMsg { msgTime :: !UTCTime, user :: !User, msg :: !Text, msgLine :: !Text }
2014-05-11 14:34:05 +05:30
| PrivMsg { msgTime :: !UTCTime, user :: !User, msg :: !Text, msgLine :: !Text }
| ActionMsg { msgTime :: !UTCTime, user :: !User, msg :: !Text, msgLine :: !Text }
2014-05-11 14:34:05 +05:30
| Ping { msgTime :: !UTCTime, msg :: !Text, msgLine :: !Text }
| JoinMsg { msgTime :: !UTCTime, user :: !User, msgLine :: !Text }
| QuitMsg { msgTime :: !UTCTime, user :: !User, msg :: !Text, msgLine :: !Text }
| PartMsg { msgTime :: !UTCTime, user :: !User, msg :: !Text, msgLine :: !Text }
| ModeMsg { msgTime :: !UTCTime, user :: !User, target :: !Text, mode :: !Text
, modeArgs :: ![Text], msgLine :: !Text }
2014-05-11 14:34:05 +05:30
| NickMsg { msgTime :: !UTCTime, user :: !User, nick :: !Text, msgLine :: !Text }
| KickMsg { msgTime :: !UTCTime, user :: !User, kickedNick :: !Text, msg :: !Text
, msgLine :: !Text }
2014-05-11 14:34:05 +05:30
| OtherMsg { msgTime :: !UTCTime, source :: !Text, command :: !Text, target :: !Text
, msg :: !Text, msgLine :: !Text }
2014-05-04 02:57:43 +05:30
deriving (Show, Eq)
data Command =
Pong { rmsg :: !Text }
| ChannelMsgReply { rmsg :: !Text }
| PrivMsgReply { ruser :: !User, rmsg :: !Text }
2014-05-04 02:57:43 +05:30
| NickCmd
| UserCmd
| JoinCmd
| MessageCmd Message
2014-05-04 02:57:43 +05:30
deriving (Show, Eq)
data BotConfig = BotConfig { server :: !Text
, port :: !Int
, channel :: !Text
, botNick :: !Text
, botTimeout :: !Int
, msgHandlerNames :: ![MsgHandlerName]
, config :: !Config }
instance Show BotConfig where
show BotConfig { .. } = "server = " ++ show server ++ "\n" ++
"port = " ++ show port ++ "\n" ++
"channel = " ++ show channel ++ "\n" ++
"nick = " ++ show botNick ++ "\n" ++
"timeout = " ++ show botTimeout ++ "\n" ++
"handlers = " ++ show msgHandlerNames
data Bot = Bot { botConfig :: !BotConfig
, socket :: !Handle
, msgHandlers :: !(Map MsgHandlerName MsgHandler) }
2014-05-04 02:57:43 +05:30
2014-05-15 12:02:31 +05:30
data BotStatus = Connected | Disconnected | Joined | Kicked | Errored | Idle | Interrupted
deriving (Show, Eq)
newtype IRC a = IRC { _runIRC :: StateT BotStatus (ReaderT Bot IO) a }
deriving ( Functor
, Applicative
, Monad
, MonadIO
, MonadReader Bot
, MonadState BotStatus )
runIRC :: Bot -> BotStatus -> IRC a -> IO BotStatus
2014-05-07 14:35:25 +05:30
runIRC bot botStatus = flip runReaderT bot . flip execStateT botStatus . _runIRC
newtype MsgHandlerT a = MsgHandlerT { _runMsgHandler :: ReaderT BotConfig IO a }
deriving ( Functor
, Applicative
, Monad
, MonadIO
, MonadReader BotConfig )
class ( MonadIO m, Applicative m, MonadReader BotConfig m ) => MonadMsgHandler m where
msgHandler :: MsgHandlerT a -> m a
instance MonadMsgHandler MsgHandlerT where
msgHandler = id
runMsgHandler :: MsgHandler -> BotConfig -> Message -> IO (Maybe Command)
runMsgHandler MsgHandler { .. } botConfig = flip runReaderT botConfig . _runMsgHandler . msgHandlerRun
stopMsgHandler :: MsgHandler -> BotConfig -> IO ()
stopMsgHandler MsgHandler { .. } botConfig =
flip runReaderT botConfig . _runMsgHandler $ msgHandlerStop
data MsgHandler = MsgHandler { msgHandlerRun :: !(forall m . MonadMsgHandler m => Message -> m (Maybe Command))
, msgHandlerStop :: !(forall m . MonadMsgHandler m => m ()) }
newMsgHandler :: MsgHandler
newMsgHandler = MsgHandler { msgHandlerRun = const $ return Nothing
, msgHandlerStop = return () }