diff --git a/anna.scm b/anna.scm new file mode 100644 index 0000000..d761362 --- /dev/null +++ b/anna.scm @@ -0,0 +1,94 @@ +#!/usr/bin/guile +!# + +(use-modules (ice-9 rdelim) + (ice-9 textual-ports) + (ice-9 format)) + +(define +channel+ "#bots") + +(define (scdr lst) + "Safe CDR which will return the empty list if it is passed the empty list instead of throwing an error." + (if (null? lst) + lst + (cdr lst))) + +(define (slist-ref lst index) + "Safe list-ref, see scdr" + (if (< (length lst) (+ index 1)) + '() + (list-ref lst index))) + +(define (slist-tail lst index) + "Safe list-tail, see scdr" + (if (< (length lst) (+ index 1)) + '() + (list-tail lst index))) + +(define (string-tail str index) + "List-tail for strings." + (list->string (list-tail (string->list str) index))) + +(define (intersperse sep lst) + "Returns a new list with sep between each element of lst." + (cond + ((or (null? lst) + (null? (cdr lst))) lst) + (else (cons (car lst) + (cons sep + (intersperse sep (cdr lst))))))) + +(define (make-connection host port) + "Connect to irc server on host:port, returns a socket for reading and writing." + (let* ((sock (socket PF_INET SOCK_STREAM 0)) + (con (connect sock + AF_INET + (car (vector-ref (gethost host) 4)) + port))) + sock)) + +(define (pong stream) + (format stream "PONG :anna\r\n")) + +(define (send-nick stream) + (format stream "NICK anna\r\n")) + +(define (send-user stream) + (format stream "USER anna 0.0.0.0 anna :Anna\r\n")) + +(define (join-channel stream) + (format stream "JOIN ~a\r\n" +channel+)) + +(define (send-message stream chn msg) + (format stream "PRIVMSG ~a :~a\r\n" chn msg)) + +(define (send-action stream chn action) + (format stream "PRIVMSG ~a :\x01ACTION ~a\x01\r\n" chn action)) + +(define (main-loop stream) + (let* ((inl (read-line stream)) + (data (string-tokenize inl))) + ;; debug print + (format #t "~s~%" data) + (cond + ((equal? (car data) "PING") + (pong stream)) + ((equal? ":.hello" (slist-ref data 3)) + (send-message stream +channel+ "hello, world")) + ((equal? ":.eval" (slist-ref data 3)) + (let* ((expr (string-concatenate (intersperse " " (cdr (member ":eval" data)))))) + (send-message stream +channel+ (eval (read (open-input-string expr)) + (interaction-environment))))) + ((and (= 7 (length data)) + (equal? (list-tail data 4) '("ACTION" "shoots" "anna"))) + (send-action stream +channel+ "dies") + (close-port stream) + (exit))) + (main-loop stream))) + +(let* ((io (make-connection "127.0.0.1" 6667))) + (send-nick io) + (send-user io) + (join-channel io) + + (main-loop io))