File: Commands.hs

package info (click to toggle)
haskell-ircbot 0.6.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 144 kB
  • sloc: haskell: 881; makefile: 2
file content (112 lines) | stat: -rw-r--r-- 3,264 bytes parent folder | download
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
{-# LANGUAGE DeriveDataTypeable, OverloadedStrings #-}
module Network.IRC.Bot.Commands where

import Control.Applicative
import Control.Monad
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.Data
import Data.Monoid ((<>))
import Network.IRC (Message(Message, msg_prefix, msg_command, msg_params), Command, Prefix(NickName))
import Network.IRC.Bot.BotMonad (BotMonad, askMessage, sendMessage)

type HostName = ByteString

-- * Commands

cmd :: (Functor m, MonadPlus m, BotMonad m) => Command -> m ()
cmd cmdName =
  do command' <- msg_command <$> askMessage
     if cmdName == command'
       then return ()
       else mzero

data Ping
  = Ping HostName
  deriving (Eq, Ord, Read, Show, Data, Typeable)

ping :: (Functor m, MonadPlus m, BotMonad m) => m Ping
ping =
  do cmd "PING"
     params <- msg_params  <$> askMessage
     case params of
       (hostName:_) -> return $ Ping hostName
       _ -> mzero


data PrivMsg
  = PrivMsg { prefix     :: (Maybe Prefix)
            , receivers  :: [ByteString]
            , msg        :: ByteString
            }
      deriving (Eq, Read, Show)

privMsg :: (Functor m, MonadPlus m, BotMonad m) => m PrivMsg
privMsg =
  do msg' <- askMessage
     maybe mzero return (toPrivMsg msg')

toPrivMsg :: Message -> Maybe PrivMsg
toPrivMsg m =
  let cmd'    = msg_command m
      params  = msg_params  m
      prefix' = msg_prefix  m
  in case cmd' of
      "PRIVMSG" -> Just $ PrivMsg prefix' (init params) (last params)
      _         -> Nothing

class ToMessage a where
  toMessage :: a -> Message

sendCommand :: (ToMessage c, BotMonad m, Functor m) => c -> m ()
sendCommand c = sendMessage (toMessage c)

data Pong
  = Pong HostName
      deriving (Eq, Ord, Read, Show, Data, Typeable)

instance ToMessage Pong where
    toMessage (Pong hostName) = Message Nothing "PONG" [hostName]

instance ToMessage PrivMsg where
    toMessage (PrivMsg prefix' receivers' msg') = Message prefix' "PRIVMSG" (receivers' <> [msg'])

data Notice
  = Notice  { noticePrefix     :: (Maybe Prefix)
            , noticeReceivers  :: [ByteString]
            , noticeMsg        :: ByteString
            }
      deriving (Eq, Read, Show)

instance ToMessage Notice where
    toMessage (Notice prefix' receivers' msg') = Message prefix' "NOTICE" (receivers' <> [msg'])

-- | get the nickname of the user who sent the message
askSenderNickName :: (BotMonad m) => m (Maybe ByteString)
askSenderNickName =
    do msg' <- askMessage
       case msg_prefix msg' of
         (Just (NickName nick _ _)) -> return (Just nick)
         _ -> return Nothing

-- | figure out who to reply to for a given `Message`
--
-- If message was sent to a #channel reply to the channel. Otherwise reply to the sender.
replyTo :: (BotMonad m) => m (Maybe ByteString)
replyTo =
    do priv <- privMsg
       let receiver = head (receivers priv)
       if ("#" `B.isPrefixOf` receiver)
          then return (Just receiver)
          else askSenderNickName

-- | returns the receiver of a message
--
-- if multiple receivers, it returns only the first
askReceiver :: (Alternative m, BotMonad m) => m (Maybe ByteString)
askReceiver =
    do priv <- privMsg
       return (Just (head $ receivers priv))
    <|>
    do return Nothing