anna/anna.scm

95 lines
2.6 KiB
Scheme

#!/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))