blob: 43da951ceae339ec899b690c4ab39042552c6f01 (
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
81
82
83
84
85
86
87
88
|
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)
|