;;;; trilemabot.lisp (in-package #:trilemabot) ;; These are used to check that we're joining #trilema; make sure that ;; your bot is configured accordingly if you want to use ;; #trilema-specific functionality. (defparameter *trilema-server* ".freenode.net") (defparameter *trilema-channel* "#trilema") (defparameter *trilema-deedbot-nick* "deedbot") (defclass trilemabot (ircbot) ((in-chan :accessor trilemabot-in-chan :initform nil) (voiced :accessor trilemabot-voiced :initform nil) (voice-otp-stash :accessor trilemabot-voice-otp-stash :initarg :voice-otp-stash :initform nil) (inbox :accessor trilemabot-inbox :initform nil))) (defmethod ircbot-connect :after ((bot trilemabot)) (with-slots (connection) bot (add-hook connection 'irc-join-message #'(lambda (message) (trilemabot-join-channel bot message))) (add-hook connection 'irc-part-message #'(lambda (message) (trilemabot-part-channel bot message))) (add-hook connection 'irc-privmsg-message #'(lambda (message) (trilemabot-handle-privmsg bot message))) (add-hook connection 'irc-mode-message #'(lambda (message) (trilemabot-check-mode bot message))))) (defmethod ircbot-disconnect :after ((bot trilemabot) &optional (quit-msg "")) (declare (ignore quit-msg)) (with-slots (in-chan voiced) bot (setf in-chan nil voiced nil))) (defmethod trilemabot-join-channel ((bot trilemabot) message) (destructuring-bind (channel) (arguments message) (when (and (string= (source message) (ircbot-nick bot)) (string= channel *trilema-channel*) (search *trilema-server* (ircbot-server bot))) (setf (trilemabot-in-chan bot) t) (trilemabot-voice bot)))) (defmethod trilemabot-part-channel ((bot trilemabot) message) (let ((channel (car (arguments message)))) (when (and (string= (source message) (ircbot-nick bot)) (string= channel *trilema-channel*) (search *trilema-server* (ircbot-server bot))) (setf (trilemabot-in-chan bot) nil (trilemabot-voiced bot) nil)))) (defmethod trilemabot-handle-privmsg ((bot trilemabot) message) (destructuring-bind (target message-text) (arguments message) (when (and (string= (source message) *trilema-deedbot-nick*) (string= target (ircbot-nick bot))) (format *standard-output* "<~a>: ~a~%" (source message) message-text) (push (list :from (source message) :time (received-time message) :message message-text) (trilemabot-inbox bot))))) (defmethod trilemabot-check-mode ((bot trilemabot) message) (when (= 3 (length (arguments message))) ; mode change for user in chan (destructuring-bind (channel mode nick) (arguments message) (when (and (string= channel *trilema-channel*) (string= nick (ircbot-nick bot))) (cond ((or (string= mode "+o") (string= mode "+v")) (setf (trilemabot-voiced bot) t)) ((or (string= mode "-o") (string= mode "-v")) (setf (trilemabot-voiced bot) nil))))))) (defmethod trilemabot-add-voice-otps ((bot trilemabot) &rest otps) (with-slots (voice-otp-stash) bot (setf voice-otp-stash (nconc voice-otp-stash otps)))) (defmethod trilemabot-voice ((bot trilemabot)) (with-slots (voice-otp-stash) bot (if voice-otp-stash (trilemabot-send-otp bot (pop voice-otp-stash)) (format *standard-output* "[trilemabot ~a@~a] No OTPs available.~%" (ircbot-nick bot) (ircbot-server bot))))) (defmethod trilemabot-send-up ((bot trilemabot) &optional nick) (ircbot-send-message bot *trilema-deedbot-nick* (make-bot-command "!!up" (or nick (ircbot-nick bot))))) (defmethod trilemabot-send-otp ((bot trilemabot) otp) (ircbot-send-message bot *trilema-deedbot-nick* (make-bot-command "!!v" otp))) (defun make-bot-command (command &rest arguments) "Make raw bot command string consisting of `command' and space-separated `arguments'." (with-output-to-string (out) (write-string command out) (dolist (arg arguments) (write-string " " out) (write-string arg out)))) (defmethod trilemabot-save-voice-otp-stash ((bot trilemabot) filespec) (with-open-file (out filespec :direction :output :if-exists :supersede :if-does-not-exist :create) (print (trlb:trilemabot-voice-otp-stash bot) out) (finish-output out))) (defun make-trilemabot (server port nick password channels &optional voice-otps) (make-instance 'trilemabot :server server :port port :nick nick :password password :channels channels :voice-otp-stash voice-otps))