5 import System.IO -- base
6 import qualified Network.Socket as N -- network
7 import Control.Monad.Trans.Reader -- transformers
11 data Bot = Bot { botSocket :: Handle }
12 type Net = ReaderT Bot IO
16 type Realname = String
19 runBirch :: String -> N.PortNumber -> String -> [String] -> IO ()
20 runBirch myServer myPort myNick myChannels = do
21 h <- connectTo myServer myPort
22 register h myNick "tutorial bot"
26 if isPing s then pong h s else eval h (clean s)
27 -- map (write h "JOIN") myChannels
28 write h "JOIN" (head myChannels)
31 -- Connect to a server given its name and port number
32 connectTo :: N.HostName -> N.PortNumber -> IO Handle
33 connectTo host port = do
34 addr : _ <- N.getAddrInfo Nothing (Just host) (Just (show port))
35 sock <- N.socket (N.addrFamily addr) (N.addrSocketType addr) (N.addrProtocol addr)
36 N.connect sock (N.addrAddress addr)
37 N.socketToHandle sock ReadWriteMode
39 -- Send a message to a handle
40 write :: Handle -> String -> String -> IO ()
42 let msg = cmd ++ " " ++ args ++ "\r\n"
43 hPutStr h msg -- Send message on the wire
44 putStr ("> " ++ msg) -- Show sent message on the command line
46 -- Process each line from the server
47 listen :: Handle -> IO ()
48 listen h = forever $ do
52 if isPing s then pong h s else eval h (clean s)
54 forever :: IO () -> IO ()
55 forever a = do a; forever a
57 clean :: String -> String
58 clean = drop 1 . dropWhile (/= ':') . drop 1
60 isPing :: String -> Bool
61 isPing x = "PING :" `isPrefixOf` x
63 pong :: Handle -> String -> IO ()
64 pong h x = write h "PONG" (':' : drop 6 x)
67 eval :: Handle -> String -> IO ()
68 eval h "!quit" = write h "QUIT" ":Exiting" >> exitSuccess
69 eval h x | "!id " `isPrefixOf` x = privmsg h (drop 4 x)
70 eval _ _ = return () -- ignore everything else
72 -- Send a privmsg to a channel
73 privmsg :: Handle -> String -> IO ()
74 privmsg h s = write h "PRIVMSG" ("#nais-testing" ++ " :" ++ s)
76 -- Register with the server
77 register :: Handle -> Nick -> Realname -> IO ()
78 register h nick realname = do
80 sendUSER h nick realname
83 sendNICK :: Handle -> Nick -> IO ()
84 sendNICK h nick = write h "NICK" nick
87 sendUSER :: Handle -> Nick -> Realname -> IO ()
88 sendUSER h nick realname = write h "USER" (nick ++ " 0 * :" ++ realname)