(in-package :jbominji) (defclass jbominji-event-handler () ()) (defgeneric process-event (handler text pr type channel source response-hook)) (defgeneric process-error-event (handler text type channel source response-hook condition errmsg)) (defmethod process-error-event ((handler jbominji-event-handler) text type channel source response-hook condition errmsg) (defvar *jbominji-event-listeners* nil) (defun add-listener (event-handler) (push event-handler *jbominji-event-listeners*)) (defun clear-listeners () (setf *jbominji-event-listeners* nil)) ; incoming events (defun incoming-event (text type channel source response-hook) (sb-thread:with-mutex ((lojban-parser:get-mutex)) (handler-case (progn (lojban-parser:initialize-parser) (let* ((pr (lojban-parser:parse-lojban text :save-parse-tree t)) ) (loop for handler in *jbominji-event-listeners* do (process-event handler text pr type channel source response-hook)) ) ) (cl-peg:missing-non-terminal (condition) (progn (let ((errmsg (format nil "Grammar failure \"~A\" while parsing \"~A\", condition ~A" (cl-peg::text condition) text condition))) (loop for handler in *jbominji-event-listeners* do (process-error-event handler text type channel source response-hook condition errmsg)) )))))) ;---------------------------------------- ; Logging handler ;---------------------------------------- (defclass logging-handler (jbominji-event-handler) ()) (defvar *log-events-wait-queue* (sb-thread:make-waitqueue :name "log events waitqueue")) (defvar *log-events-mutex* (sb-thread:make-mutex)) (defvar *log-events* nil) (defvar *log-counter* 0) (defmethod process-event ((handler logging-handler) text pr type channel source response-hook) (sb-thread:with-mutex (*log-events-mutex*) (let ((newcounter (incf *log-counter*))) (push (list newcounter source text pr) *log-events*) (setf *log-events* (butlast *log-events* (list-length (nthcdr 30 *log-events*)))) ; ugly! (sb-thread:condition-broadcast *log-events-wait-queue*) ) ) (with-open-file (stream "mylog.txt" :direction :output :if-does-not-exist :create :if-exists :append) (handler-case (format stream "did ~A ~%" text) (sb-int:stream-encoding-error () (format stream "unprintable"))) ) ) ;(defun my-notify-thread (input) ; (with-open-file (stream "mylog.txt" :direction :output :if-exists :append) ; (format stream "notify thread ~%") ; ) ; (create-log-output 'manual input nil) ;) (defun my-listen-thread () (sb-thread:with-mutex (*log-events-mutex*) (progn (sb-thread:condition-wait *log-events-wait-queue* *log-events-mutex*) (with-open-file (stream "mylistener.txt" :direction :output :if-exists :append) (format stream "wait thread ~%") ) (format t "my-listen-thread has notified~%") )) (my-listen-thread) ) ;---------------------------------------- ; handler ;---------------------------------------- (defclass event-handler (jbominji-event-handler) ()) (defmethod process-event ((handler event-handler) text pr type channel source response-hook) (handler-case (format t "process-event ~A ~A ~A~%" handler text type) (t () ())) ; first check if this event was directed at us (when (eq type :irc-private) ; (funcall response-hook "hey dawg") (jbominji-irc::do-gloss tree pr response-hook) ) ) ) (defun test-input-event (text) ; (incoming-event text 'jemna ; #'(lambda (pr) ; (format t "matched ~A text ~A~%" (cl-peg:parse-result-matched pr) text)) ; nil) ) ;(defvar *site-host-name* "localhost") (defvar *site-host-name* "subvert-the-dominant-paradigm.net") (defun start-jbominji () (clear-listeners) (add-listener (make-instance 'logging-handler)) (add-listener (make-instance 'event-handler)) )