-#!/usr/bin/guile \
--e main -s
-!#
-
;;; 8sync --- Asynchronous programming for Guile
-;;; Copyright (C) 2015 Christopher Allan Webber <cwebber@dustycloud.org>
+;;; Copyright © 2015, 2016, 2017 Christopher Allan Webber <cwebber@dustycloud.org>
;;;
;;; This file is part of 8sync.
;;;
(define-module (8sync systems irc)
#:use-module (8sync repl)
- #:use-module (8sync agenda)
#:use-module (8sync actors)
#:use-module (srfi srfi-9)
#:use-module (ice-9 getopt-long)
#:use-module (ice-9 match)
#:use-module (oop goops)
#:export (<irc-bot>
- irc-bot-username irc-bot-server irc-bot-channels
- irc-bot-port irc-bot-handler
+ irc-bot-username irc-bot-server irc-bot-channels irc-bot-port
+
+ irc-bot-send-line
+
+ handle-line handle-misc-input
+ handle-user-join handle-user-quit
default-irc-port))
(port #:init-keyword #:port
#:init-value default-irc-port
#:getter irc-bot-port)
- (line-handler #:init-keyword #:line-handler
- #:init-value (wrap-apply echo-message)
- #:getter irc-bot-line-handler)
(socket #:accessor irc-bot-socket)
(actions #:allocation #:each-subclass
- #:init-value (build-actions
- (init irc-bot-init)
+ #:init-thunk (build-actions
(main-loop irc-bot-main-loop)
- (send-line irc-bot-send-line))))
+ (handle-line handle-line)
+ (send-line irc-bot-send-line-action))))
(define (irc-bot-realname irc-bot)
(or (slot-ref irc-bot 'realname)
(irc-bot-username irc-bot)))
-(define (irc-bot-init irc-bot message)
+(define-method (actor-init! (irc-bot <irc-bot>))
"Initialize the IRC bot"
(define socket
(irc-socket-setup (irc-bot-server irc-bot)
(irc-bot-port irc-bot)))
+ (pk 'initing-irc)
(set! (irc-bot-socket irc-bot) socket)
(format socket "USER ~a ~a ~a :~a~a"
(irc-bot-username irc-bot)
(format socket "JOIN ~a~a" channel irc-eol))
(irc-bot-channels irc-bot))
- (<- irc-bot (actor-id irc-bot) 'main-loop))
+ (<- (actor-id irc-bot) 'main-loop))
+
+(define-method (actor-cleanup! (irc-bot <irc-bot>))
+ (close (irc-bot-socket irc-bot)))
(define (irc-bot-main-loop irc-bot message)
(define socket (irc-bot-socket irc-bot))
(define line (string-trim-right (read-line socket) #\return))
- (irc-bot-dispatch-line irc-bot line)
- (cond
- ;; The port's been closed for some reason, so stop looping
- ((port-closed? socket)
- 'done)
- ;; We've reached the EOF object, which means we should close
- ;; the port ourselves and stop looping
- ((eof-object? (peek-char socket))
- (close socket)
- 'done)
- ;; ;; Looks like we've been killed somehow... well, stop running
- ;; ;; then!
- ;; ((actor-am-i-dead? irc-bot)
- ;; (if (not (port-closed? socket))
- ;; (close socket))
- ;; 'done)
- ;; Otherwise, let's read till the next line!
- (else
- (<- irc-bot (actor-id irc-bot) 'main-loop))))
-
-(define-method (irc-bot-dispatch-line (irc-bot <irc-bot>) line)
+ (with-actor-nonblocking-ports
+ (lambda ()
+ (dispatch-raw-line irc-bot line)
+ (cond
+ ;; The port's been closed for some reason, so stop looping
+ ((port-closed? socket)
+ 'done)
+ ;; We've reached the EOF object, which means we should close
+ ;; the port ourselves and stop looping
+ ((eof-object? (peek-char socket))
+ (close socket)
+ 'done)
+ (else
+ (<- (actor-id irc-bot) 'main-loop))))))
+
+(define* (irc-bot-send-line-action irc-bot message
+ channel line #:key emote?)
+ "Action handler for sending lines. Real behavior happens in
+irc-bot-send-line."
+ (irc-bot-send-line irc-bot channel line #:emote? emote?))
+
+(define* (irc-bot-send-line irc-bot channel line #:key emote?)
+ ;; TODO: emote? handling
+ (format (irc-bot-socket irc-bot) "PRIVMSG ~a :~a~a"
+ channel line irc-eol))
+
+
+;;; Likely-to-be-overridden generic methods
+
+(define-method (dispatch-raw-line (irc-bot <irc-bot>) raw-line)
+ "Dispatch a raw line of input"
(receive (line-prefix line-command line-params)
- (parse-line line)
+ (parse-line raw-line)
(match line-command
("PING"
- (display "PONG" (irc-bot-socket irc-bot)))
+ (display (string-append "PONG" irc-eol)
+ (irc-bot-socket irc-bot)))
("PRIVMSG"
(receive (channel-name line-text emote?)
(condense-privmsg-line line-params)
(let ((username (irc-line-username line-prefix)))
- ((irc-bot-line-handler irc-bot) irc-bot username
- channel-name line-text emote?))))
- (_
- (display line)
- (newline)))))
-
-(define* (irc-bot-send-line irc-bot message
- channel line #:key emote?)
- ;; TODO: emote? handling
- (format (irc-bot-socket irc-bot) "PRIVMSG ~a :~a~a"
- channel line irc-eol))
+ (<- (actor-id irc-bot) 'handle-line
+ username channel-name
+ line-text emote?))))
+ (_ (handle-misc-input irc-bot raw-line)))))
+
+(define-method (handle-line (irc-bot <irc-bot>) message
+ username channel-name line-text emote?)
+ (echo-message irc-bot username channel-name line-text emote?))
+
+(define-method (handle-misc-input (irc-bot <irc-bot>) raw-line)
+ (display raw-line)
+ (newline))
+
+(define-method (handle-user-join (irc-bot <irc-bot>) user channel)
+ 'TODO)
+
+(define-method (handle-user-quit (irc-bot <irc-bot>) user channel)
+ 'TODO)
+