2014-05-07 14:35:25 +05:30
|
|
|
{-# LANGUAGE RecordWildCards, RankNTypes, GeneralizedNewtypeDeriving #-}
|
2014-05-11 14:01:09 +05:30
|
|
|
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings, FlexibleContexts #-}
|
2014-05-04 16:50:19 +05:30
|
|
|
|
2014-05-11 14:01:09 +05:30
|
|
|
module Network.IRC.Types
|
|
|
|
(Channel, Nick, MsgHandlerName,
|
|
|
|
User (..), Message (..), Command (..),
|
|
|
|
BotConfig (..), BotStatus (..), Bot (..),
|
|
|
|
IRC, runIRC,
|
|
|
|
MonadMsgHandler, runMsgHandler, initMsgHandler, exitMsgHandler,
|
|
|
|
MsgHandlerState, MsgHandlerStates, MsgHandler (..), newMsgHandler)
|
|
|
|
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
|
2014-05-06 02:50:40 +05:30
|
|
|
import Control.Monad.State
|
2014-05-04 16:50:19 +05:30
|
|
|
import Data.Configurator.Types
|
2014-05-11 14:01:09 +05:30
|
|
|
import Data.Dynamic
|
2014-05-04 02:57:43 +05:30
|
|
|
|
2014-05-11 14:01:09 +05:30
|
|
|
type Channel = Text
|
|
|
|
type Nick = Text
|
|
|
|
type MsgHandlerName = Text
|
2014-05-06 02:50:40 +05:30
|
|
|
|
2014-05-11 14:01:09 +05:30
|
|
|
data User = Self | User { userNick :: !Nick, userServer :: !Text }
|
2014-05-04 02:57:43 +05:30
|
|
|
deriving (Show, Eq)
|
|
|
|
|
|
|
|
data Message =
|
2014-05-11 14:34:05 +05:30
|
|
|
ChannelMsg { msgTime :: !UTCTime, user :: !User, msg :: !Text, msgLine :: !Text }
|
|
|
|
| PrivMsg { msgTime :: !UTCTime, user :: !User, msg :: !Text, msgLine :: !Text }
|
|
|
|
| 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
|
2014-05-11 14:01:09 +05:30
|
|
|
, 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
|
2014-05-11 14:01:09 +05:30
|
|
|
, msgLine :: !Text }
|
2014-05-11 14:34:05 +05:30
|
|
|
| OtherMsg { msgTime :: !UTCTime, source :: !Text, command :: !Text, target :: !Text
|
2014-05-11 14:01:09 +05:30
|
|
|
, msg :: !Text, msgLine :: !Text }
|
2014-05-04 02:57:43 +05:30
|
|
|
deriving (Show, Eq)
|
|
|
|
|
|
|
|
data Command =
|
2014-05-11 14:01:09 +05:30
|
|
|
Pong { rmsg :: !Text }
|
|
|
|
| ChannelMsgReply { rmsg :: !Text }
|
|
|
|
| PrivMsgReply { ruser :: !User, rmsg :: !Text }
|
2014-05-04 02:57:43 +05:30
|
|
|
| NickCmd
|
|
|
|
| UserCmd
|
|
|
|
| JoinCmd
|
|
|
|
deriving (Show, Eq)
|
|
|
|
|
2014-05-11 14:01:09 +05:30
|
|
|
data BotConfig = BotConfig { server :: !Text
|
|
|
|
, port :: !Int
|
|
|
|
, channel :: !Text
|
|
|
|
, botNick :: !Text
|
|
|
|
, botTimeout :: !Int
|
|
|
|
, msgHandlers :: ![MsgHandlerName]
|
|
|
|
, config :: !Config }
|
2014-05-04 16:50:19 +05:30
|
|
|
|
|
|
|
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" ++
|
2014-05-11 14:01:09 +05:30
|
|
|
"handlers = " ++ show msgHandlers
|
|
|
|
|
|
|
|
type MsgHandlerStates = Map MsgHandlerName MsgHandlerState
|
2014-05-04 16:50:19 +05:30
|
|
|
|
2014-05-11 14:01:09 +05:30
|
|
|
data Bot = Bot { botConfig :: !BotConfig
|
|
|
|
, socket :: !Handle
|
|
|
|
, msgHandlerStates :: !MsgHandlerStates}
|
2014-05-04 02:57:43 +05:30
|
|
|
|
2014-05-06 02:50:40 +05:30
|
|
|
data BotStatus = Connected | Disconnected | Joined | Kicked | Errored
|
|
|
|
deriving (Show, Eq)
|
|
|
|
|
|
|
|
newtype IRC a = IRC { _runIRC :: StateT BotStatus (ReaderT Bot IO) a }
|
2014-05-11 14:01:09 +05:30
|
|
|
deriving ( Functor
|
|
|
|
, Applicative
|
|
|
|
, Monad
|
|
|
|
, MonadIO
|
|
|
|
, MonadReader Bot
|
|
|
|
, MonadState BotStatus)
|
2014-05-06 02:50:40 +05:30
|
|
|
|
|
|
|
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
|
2014-05-11 14:01:09 +05:30
|
|
|
|
|
|
|
type MsgHandlerState = Dynamic
|
|
|
|
|
|
|
|
newtype MsgHandlerT a = MsgHandlerT { _runMsgHandler :: StateT MsgHandlerState (ReaderT BotConfig IO) a }
|
|
|
|
deriving ( Functor
|
|
|
|
, Applicative
|
|
|
|
, Monad
|
|
|
|
, MonadIO
|
|
|
|
, MonadState MsgHandlerState
|
|
|
|
, MonadReader BotConfig)
|
|
|
|
|
|
|
|
class ( MonadIO m, Applicative m
|
|
|
|
, MonadState MsgHandlerState m, MonadReader BotConfig m) => MonadMsgHandler m where
|
|
|
|
msgHandler :: MsgHandlerT a -> m a
|
|
|
|
|
|
|
|
instance MonadMsgHandler MsgHandlerT where
|
|
|
|
msgHandler = id
|
|
|
|
|
|
|
|
runMsgHandler :: MsgHandler -> BotConfig -> MsgHandlerState -> Message -> IO (Maybe Command)
|
|
|
|
runMsgHandler MsgHandler { .. } botConfig msgHandlerState =
|
|
|
|
flip runReaderT botConfig . flip evalStateT msgHandlerState . _runMsgHandler . msgHandlerRun
|
|
|
|
|
|
|
|
initMsgHandler :: MsgHandler -> BotConfig -> IO MsgHandlerState
|
|
|
|
initMsgHandler MsgHandler { .. } botConfig =
|
|
|
|
flip runReaderT botConfig . flip execStateT (toDyn ()) . _runMsgHandler $ msgHandlerInit
|
|
|
|
|
|
|
|
exitMsgHandler :: MsgHandler -> BotConfig -> MsgHandlerState -> IO ()
|
|
|
|
exitMsgHandler MsgHandler { .. } botConfig msgHandlerState =
|
|
|
|
flip runReaderT botConfig . flip evalStateT msgHandlerState . _runMsgHandler $ msgHandlerExit
|
|
|
|
|
|
|
|
data MsgHandler = MsgHandler { msgHandlerInit :: !(forall m . MonadMsgHandler m => m ())
|
|
|
|
, msgHandlerRun :: !(forall m . MonadMsgHandler m => Message -> m (Maybe Command))
|
|
|
|
, msgHandlerExit :: !(forall m . MonadMsgHandler m => m ()) }
|
|
|
|
|
|
|
|
newMsgHandler :: MsgHandler
|
|
|
|
newMsgHandler = MsgHandler { msgHandlerInit = return ()
|
|
|
|
, msgHandlerRun = const $ return Nothing
|
|
|
|
, msgHandlerExit = return () }
|