1 implementation module IRCBot
3 from Data.Func import $
10 from Text import class Text(split,join), instance Text String
17 bot :: (String, Int) [IRCMessage] [IRCMessage] a (IRCMessage a *World -> (Maybe [IRCMessage], a, *World)) *World -> (MaybeErrorString a, *World)
18 bot (host, port) start end state bot w
20 # (ip, w) = lookupIPAddress host w
21 | isNothing ip = (Error $ "DNS lookup for " +++ host +++ " failed", w)
23 # (rpt,chan,w) = connectTCP_MT TIMEOUT (fromJust ip, port) w
24 | rpt == TR_Expired = (Error $ "Connection to " +++ host +++ " timed out", w)
25 | rpt == TR_NoSuccess = (Error $ "Could not connect to " +++ host, w)
26 // Send startup commands
27 # (merr, chan, w) = send (map toString start) (fromJust chan) w
28 | isError merr = (Error $ fromError merr, w)
29 //Start processing function
30 # (mer, chan, state, w) = process chan "" state bot w
31 | isError mer = (Error $ fromError mer, w)
32 // Send shutdown commands
33 # (merr, {rChannel,sChannel}, w) = send (map toString end) chan w
34 | isError merr = (Error $ fromError merr, w)
36 = (Ok state, closeChannel sChannel (closeRChannel rChannel w))
38 import StdDebug,StdMisc
39 process :: TCP_DuplexChannel String a (IRCMessage a *World -> (Maybe [IRCMessage], a, *World)) *World -> (MaybeErrorString (), TCP_DuplexChannel, a, *World)
40 process chan acc state bot w
41 //See if we have a message
42 = case split "\r\n" acc of
43 //We only have one message that is not complete
46 # (merr_resp, chan, w) = recv chan w
47 | isError merr_resp = (Error (fromError merr_resp), chan, state, w)
48 # (Ok mresp) = merr_resp
49 | isNothing mresp = process chan acc state bot w
50 = process chan (m +++ fromJust mresp) state bot w
51 //We have a successfull split and therefore we process at least one message
53 # acc = join "\r\n" xs
54 | not (trace_tn $ "Full message: '" +++ m +++ "'") = undef
55 = case parseIRCMessage $ m +++ "\r\n" of
56 (Left err) = (Error $ "IRC Parsing error: " +++ join "\n" err, chan, state, w)
58 # (mircc, state, w) = bot msg state w
59 | isNothing mircc = (Ok (), chan, state, w) // Bot asks to quit
60 //Possible send the commands
61 # (merr, chan, w) = send (map toString $ fromJust mircc) chan w
62 | isError merr = (Error $ fromError merr, chan, state, w)
64 = process chan acc state bot w
66 send :: [String] TCP_DuplexChannel *World -> (MaybeErrorString (), TCP_DuplexChannel, *World)
67 send [] chan w = (Ok (), chan, w)
68 send [msg:msgs] {sChannel,rChannel} w
69 # (_, w) = sleep 500000 w
70 # (rpt,i,sChannel,w) = send_MT TIMEOUT (toByteSeq msg) sChannel w
71 | rpt <> TR_Success = (Error "Could not send message", {sChannel=sChannel,rChannel=rChannel}, w)
72 = send msgs {sChannel=sChannel,rChannel=rChannel} w
74 sleep :: !Int !*World -> (!Int, *World)
79 recv :: TCP_DuplexChannel *World -> (MaybeErrorString (Maybe String), TCP_DuplexChannel, *World)
80 recv {sChannel,rChannel} w
81 # (rpt, resp, rChannel, w) = receive_MT TIMEOUT rChannel w
82 | rpt == TR_Expired = (Ok Nothing, {sChannel=sChannel,rChannel=rChannel}, w)
83 | rpt == TR_NoSuccess || isNothing resp = (Error "Timeout recv fail", {sChannel=sChannel,rChannel=rChannel}, w)
84 = (Ok $ Just $ toString $ fromJust resp, {sChannel=sChannel,rChannel=rChannel}, w)