module Lib ( runBirch ) where import System.IO -- base import qualified Network.Socket as N -- network import Control.Monad.Trans.Reader -- transformers import Data.List import System.Exit data Bot = Bot { botSocket :: Handle } type Net = ReaderT Bot IO type Nick = String type User = String type Realname = String -- Toplevel program runBirch :: String -> N.PortNumber -> String -> [String] -> IO () runBirch myServer myPort myNick myChannels = do h <- connectTo myServer myPort register h myNick "tutorial bot" line <- hGetLine h putStrLn line let s = init line if isPing s then pong h s else eval h (clean s) -- map (write h "JOIN") myChannels write h "JOIN" (head myChannels) listen h -- Connect to a server given its name and port number connectTo :: N.HostName -> N.PortNumber -> IO Handle connectTo host port = do addr : _ <- N.getAddrInfo Nothing (Just host) (Just (show port)) sock <- N.socket (N.addrFamily addr) (N.addrSocketType addr) (N.addrProtocol addr) N.connect sock (N.addrAddress addr) N.socketToHandle sock ReadWriteMode -- Send a message to a handle write :: Handle -> String -> String -> IO () write h cmd args = do let msg = cmd ++ " " ++ args ++ "\r\n" hPutStr h msg -- Send message on the wire putStr ("> " ++ msg) -- Show sent message on the command line -- Process each line from the server listen :: Handle -> IO () listen h = forever $ do line <- hGetLine h putStrLn line let s = init line if isPing s then pong h s else eval h (clean s) where forever :: IO () -> IO () forever a = do a; forever a clean :: String -> String clean = drop 1 . dropWhile (/= ':') . drop 1 isPing :: String -> Bool isPing x = "PING :" `isPrefixOf` x pong :: Handle -> String -> IO () pong h x = write h "PONG" (':' : drop 6 x) -- Dispatch a command eval :: Handle -> String -> IO () eval h "!quit" = write h "QUIT" ":Exiting" >> exitSuccess eval h x | "!id " `isPrefixOf` x = privmsg h (drop 4 x) eval _ _ = return () -- ignore everything else -- Send a privmsg to a channel privmsg :: Handle -> String -> IO () privmsg h s = write h "PRIVMSG" ("#nais-testing" ++ " :" ++ s) -- Register with the server register :: Handle -> Nick -> Realname -> IO () register h nick realname = do sendNICK h nick sendUSER h nick realname -- Send NICK command sendNICK :: Handle -> Nick -> IO () sendNICK h nick = write h "NICK" nick -- Send USER command sendUSER :: Handle -> Nick -> Realname -> IO () sendUSER h nick realname = write h "USER" (nick ++ " 0 * :" ++ realname)