X-Git-Url: https://git.martlubbers.net/?p=cloogle-irc.git;a=blobdiff_plain;f=IRCBot.icl;fp=IRCBot.icl;h=9b6b32073e0882c067d294ac9eb90c747c7fbcb9;hp=0000000000000000000000000000000000000000;hb=3134ab7e61bcbc84560b4a5d613a92b1a48362c2;hpb=663ea3d6dfb6a70ddf1f3b6c41d4d39ed30c4440 diff --git a/IRCBot.icl b/IRCBot.icl new file mode 100644 index 0000000..9b6b320 --- /dev/null +++ b/IRCBot.icl @@ -0,0 +1,77 @@ +implementation module IRCBot + +from Data.Func import $ +import Data.Either +import Data.Error +import Data.Maybe +import IRC +import TCPIP + +from Text import class Text(join), instance Text String + +import StdList +import StdBool + +TIMEOUT :== Just 1000 + +bot :: (String, Int) [IRCMessage] [IRCMessage] a (IRCMessage a *World -> (Maybe [IRCMessage], a, *World)) *World -> (MaybeErrorString a, *World) +bot (host, port) start end state bot w +//Lookup hostname +# (ip, w) = lookupIPAddress host w +| isNothing ip = (Error $ "DNS lookup for " +++ host +++ " failed", w) +//Connect +# (rpt,chan,w) = connectTCP_MT TIMEOUT (fromJust ip, port) w +| rpt == TR_Expired = (Error $ "Connection to " +++ host +++ " timed out", w) +| rpt == TR_NoSuccess = (Error $ "Could not connect to " +++ host, w) +// Send startup commands +# (merr, chan, w) = send (map toString start) (fromJust chan) w +| isError merr = (Error $ fromError merr, w) +//Start processing function +# (mer, chan, state, w) = process chan state bot w +| isError mer = (Error $ fromError mer, w) +// Send shutdown commands +# (merr, {rChannel,sChannel}, w) = send (map toString end) chan w +| isError merr = (Error $ fromError merr, w) +//Close channels += (Ok state, closeChannel sChannel (closeRChannel rChannel w)) + +import StdDebug,StdMisc +process :: TCP_DuplexChannel a (IRCMessage a *World -> (Maybe [IRCMessage], a, *World)) *World -> (MaybeErrorString (), TCP_DuplexChannel, a, *World) +process chan state bot w +//Receive +# (merr_resp, chan, w) = recv chan w +| isError merr_resp = (Error (fromError merr_resp), chan, state, w) +# (Ok mresp) = merr_resp +| isNothing mresp = process chan state bot w +| not (trace_tn $ "Received: " +++ fromJust mresp) = undef +//Process += case parseIRCMessage (fromJust mresp) of + (Left err) = (Error $ "IRC Parsing error: " +++ join "\n" err, chan, state, w) + (Right msg) + # (mircc, state, w) = bot msg state w + | isNothing mircc = (Ok (), chan, state, w) // Bot asks to quit + //Possible send the commands + # (merr, chan, w) = send (map toString $ fromJust mircc) chan w + | isError merr = (Error $ fromError merr, chan, state, w) + //Recurse + = process chan state bot w + +send :: [String] TCP_DuplexChannel *World -> (MaybeErrorString (), TCP_DuplexChannel, *World) +send [] chan w = (Ok (), chan, w) +send [msg:msgs] {sChannel,rChannel} w +# (_, w) = sleep 250000 w +# (rpt,i,sChannel,w) = send_MT TIMEOUT (toByteSeq msg) sChannel w +| rpt <> TR_Success = (Error "Could not send message", {sChannel=sChannel,rChannel=rChannel}, w) += send msgs {sChannel=sChannel,rChannel=rChannel} w + where + sleep :: !Int !*World -> (!Int, *World) + sleep i w = code { + ccall usleep "I:I:A" + } + +recv :: TCP_DuplexChannel *World -> (MaybeErrorString (Maybe String), TCP_DuplexChannel, *World) +recv {sChannel,rChannel} w +# (rpt, resp, rChannel, w) = receive_MT TIMEOUT rChannel w +| rpt == TR_Expired = (Ok Nothing, {sChannel=sChannel,rChannel=rChannel}, w) +| rpt == TR_NoSuccess || isNothing resp = (Error "Timeout recv fail", {sChannel=sChannel,rChannel=rChannel}, w) += (Ok $ Just $ toString $ fromJust resp, {sChannel=sChannel,rChannel=rChannel}, w)