Simple IRC Bot The channel, server, port and nickname words are used to configure where the bot lives: > "irc.freenode.net" server set > "6667" port set > "#concatenative" channel set > "cfbot" nickname set When connected to the server we deal with an 'ircbot' structure. This is a list containing the following elements: 1. The line-channel used to read server responses 2. The socket used to write requests These helper words are used to extract this information: > [ '0`@ ] bot-line-channel set > [ '1`@ ] bot-socket set Send a string to the server > [ bot-socket.socket-writeln ] irc-write set Connect to the server, returning the bot structure > [ server;port;socket dup.'line-channel`, ] bot-connect set Initializes the connection by setting the nickname, and other IRC required setup. > [ "NICK " nickname;,over.irc-write. ] set-nick set > [ "USER "nickname;," +iw ",nickname;," :",nickname;,over.irc-write. ] set-status set > [ "JOIN " channel;,over.irc-write. ] join-channel set > [ set-nick.set-status.join-channel. ] bot-init set Send a message to the channel: > [ [[c m] "PRIVMSG " c , " :" , m , ] ( over.irc-write. ] say set Return the list of responses received from the server. Blocks if not responses have yet been received. > [ dup.bot-line-channel.line-channel-getall ] bot-responses set Utility words to evaluate cf code. These should probably be in the prelude: > [ > [[c]stack.[[]unstack.c.stack.[[]unstack.]`]`swap.unit.,unstack.] ( > ] infra set > [ tokenize parse infra. to-string ] eval set The following words operate on responses from the server. > [ dup. 32 ? 1 + sdrop dup. 32 ? stake ] response-type set > [ dup. 32 ? 1 + sdrop dup. 32 ? 1 + sdrop dup. 32 ? stake ] response-channel set > [ dup. 32 ? 1 + sdrop dup. 32 ? 1 + sdrop dup. 32 ? 2 + sdrop ] response-text set Is it a private message? > [ response-type. "PRIVMSG" swap. = ] privmsg? set Is it for the channel we are monitoring? > [ [response-channel.]`= ] channel? set Is it for us? > [ response-text. nickname; ",", swap. head?. ] for-bot? set Map expression used to pick up the responses we are interested in. Anything we aren't interested in results in a 0 which is later filtered out. > [ dup.privmsg?.[dup.channel;channel?.[dup.for-bot?.[response-text.nickname;count 1 + sdrop][drop.0]if][drop.0]if][drop.0]if] wanted-messages set Get all responses, filter for the messages we want > [bot-responses.[wanted-messages.]map.[]filter.] messages-to-eval set Build the expression to evaluate on another thread: > [ [[b c] c [[[b channel;]]`unit.,eval,'.,say,'.,[drop.],]map. [b]`] ( ] build-thread-queue set > [ messages-to-eval.build-thread-queue.[[]swap.make-thread spawn]map.drop.] handle-messages set > [ handle-messages.bot-loop. ] bot-loop set > [ bot-connect.bot-init. ] start-bot set > [ dup.unit. [ bot-loop. ] make-thread spawn ] bot-daemonize set