X-Git-Url: https://git.martlubbers.net/?p=cloogle-irc.git;a=blobdiff_plain;f=IRCBot.icl;h=daed82586df5af36c28df0f19245ee71edff92cb;hp=2be18ad094a2effd60625405a6cc437ec05e6b65;hb=38119fcb7be8437bc535665f20af8b641ee67e64;hpb=2b051d8c52d1d999a5ca902ef75f99635c80f540 diff --git a/IRCBot.icl b/IRCBot.icl index 2be18ad..daed825 100644 --- a/IRCBot.icl +++ b/IRCBot.icl @@ -4,82 +4,32 @@ from Data.Func import $ import Data.Either import Data.Error import Data.Maybe +import Data.Functor +import Data.Tuple +import StdTuple import IRC -import TCPIP - -from Text import class Text(split,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 -> *(Maybe String, .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", state, w) -//Connect -# (rpt,chan,w) = connectTCP_MT TIMEOUT (fromJust ip, port) w -| rpt == TR_Expired - = (Error $ "Connection to " +++ host +++ " timed out", state, w) -| rpt == TR_NoSuccess - = (Error $ "Could not connect to " +++ host, state, w) -// Send startup commands -# (merr, chan, w) = send (map toString start) (fromJust chan) w -| isError merr = (Error $ fromError merr, state, w) -//Start processing function -# (mer, chan, state, w) = process chan "" state bot w -| isError mer = (Error $ fromError mer, state, w) -// Send shutdown commands -# (merr, {rChannel,sChannel}, w) = send (map toString end) chan w -| isError merr = (Error $ fromError merr, state, w) -//Close channels -= (Ok state, state, closeChannel sChannel (closeRChannel rChannel w)) - -process :: TCP_DuplexChannel String .a (IRCMessage .a *World -> *(Maybe [IRCMessage], .a, *World)) *World -> *(MaybeErrorString (), TCP_DuplexChannel, .a, *World) -process chan acc state bot w -//See if we have a message -= case split "\r\n" acc of - //We only have one message that is not complete - [m] - //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 acc state bot w - = process chan (m +++ fromJust mresp) state bot w - //We have a successfull split and therefore we process at least one message - [m:xs] - # acc = join "\r\n" xs - = case parseIRCMessage $ m +++ "\r\n" 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 acc state bot w - -send :: ![String] !TCP_DuplexChannel !*World -> (!MaybeErrorString (), !TCP_DuplexChannel, !*World) -send [] chan w = (Ok (), chan, w) -send [msg:msgs] {sChannel,rChannel} 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) -# (_, w) = sleep 500000 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) +from Text import class Text(concat,split,join), instance Text String +import StdList, StdString +import TCPServer.Connection + +bot :: (String, Int) [IRCMessage] [IRCMessage] .a (IRCMessage -> (.a -> *(*World -> *(Maybe [IRCMessage], .a, *World)))) !*World -> *(Maybe String, .a, !*World) +bot (host, port) start end state bot w = appSnd3 snd $ connect host port + { emptyConnection + & onConnect = onConnect + , onData = onData + } ("", state) w +where + onConnect s w = (Just (concat (map toString start)), connectionResponse s, w) + onData d (acc, s) w = case split "\r\n" (acc +++ d) of + [m,rest:xs] + = case parseIRCMessage $ m +++ "\r\n" of + // Do something with the error + (Left err) = (Nothing, {connectionResponse ("", s) & stop=True}, w)// (Error $ "IRC Parsing error: " +++ join "\n" err, chan, state, w) + (Right msg) + # acc = join "\r\n" [rest:xs] + # (mircc, s, w) = bot msg s w + | isNothing mircc = (Just (concat (map toString end)), {connectionResponse (acc, s) & stop=True}, w) + # tosendthis = concat (map toString (fromJust mircc)) + # (tosend, cr, w) = onData "" (acc, s) w + = (Just (maybe tosendthis ((+++) tosendthis) tosend), cr, w) + [m] = (Nothing, connectionResponse (m, s), w)