summaryrefslogtreecommitdiff
path: root/Hsbot/Irc/Plugin.hs
blob: b12d92215344ef20f9d796b3174cd899c597c14b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
module Hsbot.Irc.Plugin
    ( IrcPlugin
    , IrcPluginState (..)
    , listPlugins
    , loadIrcPlugin
    , sendToPlugin
    , spawnIrcPlugins
    , unloadPlugin
    ) where

import Control.Concurrent
import Control.Concurrent.Chan ()
import Control.Exception
import Control.Monad.State
import qualified Data.Map as M

import Hsbot.Irc.Config
import Hsbot.Irc.Message
import Hsbot.Irc.PluginCommons
import Hsbot.Irc.Plugin.Core
import Hsbot.Irc.Plugin.Dummy
import Hsbot.Irc.Plugin.Ping
import Hsbot.Irc.Plugin.Quote
import Hsbot.Irc.Types

-- | Sends a msg to a plugin
sendToPlugin :: IrcBotMsg -> IrcPluginState -> IrcBot ()
sendToPlugin ircBotMsg plugin = do
    liftIO $ writeChan (ircPluginChan plugin) ircBotMsg

-- | spawns IrcPlugins
spawnIrcPlugins :: IrcBot ()
spawnIrcPlugins = do
    config <- gets ircBotConfig
    mapM_ (loadIrcPlugin) (ircConfigPlugins config)

-- | loads an ircbot plugin
loadIrcPlugin :: String -> IrcBot ()
loadIrcPlugin pluginName = do
    ircbot <- get
    let masterChan  = ircBotChan ircbot
    pluginChan <- liftIO (newChan :: IO (Chan IrcBotMsg))
    let entryPoint = case pluginName of
                        "Core"  -> ircBotPluginCore
                        "Ping"  -> ircBotPluginPing
                        "Quote" -> ircBotPluginQuote
                        _       -> ircBotPluginDummy
    let oldPlugins = ircBotPlugins ircbot
    -- We check for unicity
    case M.lookup pluginName oldPlugins of
        Just plugin -> return ()
        Nothing     -> do
            threadId <- liftIO $ forkIO (entryPoint pluginChan masterChan)
            let plugin  = IrcPluginState { ircPluginName       = pluginName
                                         , ircPluginThreadId   = threadId
                                         , ircPluginChan       = pluginChan
                                         , ircPluginMasterChan = masterChan }
            put $ ircbot { ircBotPlugins = M.insert pluginName plugin oldPlugins }

-- | Sends a list of loaded plugins
listPlugins :: IrcMsg -> String -> IrcBot ()
listPlugins originalRequest dest = do
    plugins <- gets ircBotPlugins
    let listing = unwords $ M.keys plugins
    case M.lookup dest plugins of
        Just plugin -> sendToPlugin (IntIrcCmd $ IrcCmd "ANSWER" "CORE" dest listing originalRequest) plugin
        Nothing     -> return ()

-- | Unloads a plugin
unloadPlugin :: String -> IrcBot ()
unloadPlugin name = do
    bot <- get
    let oldPlugins = ircBotPlugins bot
    case M.lookup name oldPlugins of
        Just plugin -> do
            let newPlugins = M.delete name oldPlugins
            liftIO $ throwTo (ircPluginThreadId plugin) UserInterrupt
            put $ bot { ircBotPlugins = newPlugins }
        Nothing     -> return ()