{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Lambdabot.Bot
( ircLoadModule
, ircUnloadModule
, checkPrivs
, checkIgnore
, ircCodepage
, ircGetChannels
, ircQuit
, ircReconnect
, ircPrivmsg
, ircPrivmsg'
) where
import Lambdabot.ChanName
import Lambdabot.Config
import Lambdabot.Config.Core
import Lambdabot.IRC
import Lambdabot.Logging
import Lambdabot.Message
import Lambdabot.Module
import Lambdabot.Monad
import Lambdabot.Nick
import Lambdabot.State
import Control.Concurrent
import Control.Exception.Lifted as E
import Control.Monad.Error
import Control.Monad.Reader
import Control.Monad.State
import qualified Data.Map as M
import Data.Random.Source
import qualified Data.Set as S
ircLoadModule :: String -> Module st -> LB ()
ircLoadModule mName m = do
infoM ("Loading module " ++ show mName)
savedState <- readGlobalState m mName
mState <- maybe (moduleDefState m) return savedState
mInfo <- registerModule mName m mState
flip runModuleT mInfo (do
moduleInit m
registerCommands =<< moduleCmds m)
`E.catch` \e@SomeException{} -> do
errorM ("Module " ++ show mName ++ " failed to load. Exception thrown: " ++ show e)
unregisterModule mName
fail "Refusing to load due to a broken plugin"
ircUnloadModule :: String -> LB ()
ircUnloadModule mName = do
infoM ("Unloading module " ++ show mName)
inModuleNamed mName (fail "module not loaded") $ do
m <- asks theModule
when (moduleSticky m) $ fail "module is sticky"
moduleExit m
`E.catch` \e@SomeException{} ->
errorM ("Module " ++ show mName ++ " threw the following exception in moduleExit: " ++ show e)
writeGlobalState
unregisterModule mName
checkPrivs :: IrcMessage -> LB Bool
checkPrivs msg = gets (S.member (nick msg) . ircPrivilegedUsers)
checkIgnore :: IrcMessage -> LB Bool
checkIgnore msg = liftM2 (&&) (liftM not (checkPrivs msg))
(gets (S.member (nick msg) . ircIgnoredUsers))
ircCodepage :: String -> String -> LB ()
ircCodepage svr cpage = do
send $ codepage svr cpage
ircGetChannels :: LB [Nick]
ircGetChannels = (map getCN . M.keys) `fmap` gets ircChannels
ircQuit :: String -> String -> LB ()
ircQuit svr msg = do
modify $ \state' -> state' { ircPersists = M.delete svr $ ircPersists state' }
send $ quit svr msg
liftIO $ threadDelay 1000
noticeM "Quitting"
ircReconnect :: String -> String -> LB ()
ircReconnect svr msg = do
modify $ \state' -> state' { ircPersists = M.insertWith (flip const) svr False $ ircPersists state' }
send $ quit svr msg
liftIO $ threadDelay 1000
ircPrivmsg :: Nick
-> String
-> LB ()
ircPrivmsg who msg = do
sendlines <- applyOutputFilters who msg
w <- getConfig textWidth
mapM_ (\s -> ircPrivmsg' who (take w s)) (take 10 sendlines)
ircPrivmsg' :: Nick -> String -> LB ()
ircPrivmsg' who "" = ircPrivmsg' who " "
ircPrivmsg' who msg = send $ privmsg who msg
monadRandom [d|
instance MonadRandom LB where
getRandomWord8 = liftIO getRandomWord8
getRandomWord16 = liftIO getRandomWord16
getRandomWord32 = liftIO getRandomWord32
getRandomWord64 = liftIO getRandomWord64
getRandomDouble = liftIO getRandomDouble
getRandomNByteInteger n = liftIO (getRandomNByteInteger n)
|]