git @ Cat's Eye Technologies mzstorkipiwanbotbotbot / master bot.R
master

Tree @master (Download .tar.gz)

bot.R @masterraw · history · blame

# Rtype -- an IRC bot written in R, the Language of the Future.
# Written by Chris Pressey of Cat's Eye Technologies.
# This work is hereby placed in the public domain.

# This bot's personality is modeled after that of a cat I knew once.
# Please forgive its inhospitable nature; it had a hard life.

args <- commandArgs(trailing=TRUE)
if (length(args) != 3) {
    cat("Usage: R ... --args botname irc.server.net '#channel'\n", file=stderr())
    quit(status=1)
}

bot <- args[1]
server <- args[2]
channel <- args[3]

hunt <- function(haystack, needle) {
    return(length(grep(needle, haystack, fixed=TRUE)) > 0)
}

irc <- socketConnection(host=server, port=6667, blocking=TRUE, open="a+b")

shove <- function(s) {
    cat(s,file=irc)
    cat(s,file=stderr())
}

action <- function(channel, s) {
    shove(paste("PRIVMSG", channel, ":\x01ACTION", s, "\x01\n"))
}

grab <- function() {
    line <- readLines(con=irc, n=1)
    cat(paste(">", line, "\n"), file=stderr())
    return(line)
}

state <- 0
done <- FALSE

while (!done) {
    line <- grab()
    if (length(line) == 0) { next }
    if (state == 0) {
        # I suppose this might only apply to certain servers.
        # (And to the case where you are not running ident.)
        loc <- hunt(line, "No Ident response")
        if (loc) {
            shove(paste("USER", bot, bot, bot, bot, "\n"))
            shove(paste("NICK", bot, "\n"))
            shove(paste("JOIN", channel, "\n"))
            state <- 1
        }
    }
    if (state == 1) {
        xform <- gsub('^:(.*?)\\!(.*?)\\s+PRIVMSG\\s+(.*?)\\s+\\:(.*?)$', '\\1\u2603\\2\u2603\\3\u2603\\4', line, perl=TRUE)
        if (length(xform) == 0) { next }
        if (xform != line) {
            parts <- strsplit(xform, '\u2603', fixed=TRUE)
            nick <- parts[[1]][1]
            in_channel <- parts[[1]][3]
            message <- parts[[1]][4]
            if (in_channel == channel & length(grep(bot, message, fixed=TRUE)) > 0) {
                choice = sample(1:4, 1)
                if (choice == 1) {
                    action(channel, paste("scowls at", nick))
                } else if (choice == 2) {
                    action(channel, paste("groans"))
                } else if (choice == 3) {
                    action(channel, paste("hisses"))
                } else if (choice == 4) {
                    shove(paste("PRIVMSG", channel, ":groan\n"))
                }
            }
        }
    }
    loc <- hunt(line, "PING")
    if (loc) {
        shove("PONG :irc.irc.irc\n")
    }
    if (!isOpen(irc)) {
        done <- TRUE
    }
}