|
|
@@ -1,5 +1,28 @@
|
|
|
(in-package #:chatikbot)
|
|
|
|
|
|
+(defvar *hooks* (make-hash-table) "Hooks storage")
|
|
|
+
|
|
|
+(defun run-hooks (event &rest arguments)
|
|
|
+ (let ((hooks (gethash event *hooks*)))
|
|
|
+ (labels ((try-handle (func)
|
|
|
+ (apply func arguments)))
|
|
|
+ (unless (some #'try-handle hooks)
|
|
|
+ (log:info "unhandled" event arguments)))))
|
|
|
+
|
|
|
+(defun add-hook (event hook &optional append)
|
|
|
+ (let ((existing (gethash event *hooks*)))
|
|
|
+ (unless (member hook existing)
|
|
|
+ (setf (gethash event *hooks*)
|
|
|
+ (if append (append existing (list hook))
|
|
|
+ (cons hook existing))))))
|
|
|
+
|
|
|
+(defun remove-hook (event hook)
|
|
|
+ (setf (gethash event *hooks*)
|
|
|
+ (remove hook (gethash event *hooks*))))
|
|
|
+
|
|
|
+(defun string-to-event (key)
|
|
|
+ (intern (string-upcase (substitute #\- #\_ key)) :keyword))
|
|
|
+
|
|
|
(defmacro def-message-handler (name (message) &body body)
|
|
|
`(progn
|
|
|
(defun ,name (,message)
|
|
|
@@ -35,6 +58,49 @@
|
|
|
,@body
|
|
|
t)))))
|
|
|
|
|
|
+;; Schedule
|
|
|
+(defmacro defcron (name (&rest schedule) &body body)
|
|
|
+ (let ((schedule (or schedule '(:minute '* :hour '*))))
|
|
|
+ `(progn
|
|
|
+ (defun ,name ()
|
|
|
+ (handler-case (progn ,@body)
|
|
|
+ (error (e) (log:error e))))
|
|
|
+ (add-hook :starting #'(lambda ()
|
|
|
+ (clon:schedule-function
|
|
|
+ ',name (clon:make-scheduler
|
|
|
+ (clon:make-typed-cron-schedule
|
|
|
+ ,@schedule)
|
|
|
+ :allow-now-p t)
|
|
|
+ :name ',name :thread t)
|
|
|
+ (values))))))
|
|
|
+
|
|
|
+;; Settings
|
|
|
+(defvar *settings* nil "List of plugin's settings symbols")
|
|
|
+(defmacro defsetting (var &optional val doc)
|
|
|
+ `(progn (defvar ,var ,val ,doc)
|
|
|
+ (push ',var *settings*)))
|
|
|
+
|
|
|
+(defun load-settings ()
|
|
|
+ (loop for (var val) in (db-select "select var, val from settings")
|
|
|
+ do (setf (symbol-value (intern var))
|
|
|
+ (handler-case (read-from-string val)
|
|
|
+ (error (e) (log:error e))))))
|
|
|
+
|
|
|
+(defun set-setting (symbol value)
|
|
|
+ (handler-case
|
|
|
+ (progn
|
|
|
+ (db-execute "replace into settings (var, val) values (?, ?)"
|
|
|
+ (symbol-name symbol)
|
|
|
+ (write-to-string value))
|
|
|
+ (setf (symbol-value symbol) value))
|
|
|
+ (error (e) (log:error e))))
|
|
|
+
|
|
|
+(def-message-admin-cmd-handler handle-admin-settings (:settings)
|
|
|
+ (send-response chat-id
|
|
|
+ (format nil "~{~{~A~@[ (~A)~]: ~A~}~^~%~}"
|
|
|
+ (loop for symbol in *settings*
|
|
|
+ collect (list symbol (documentation symbol 'variable) (symbol-value symbol))))))
|
|
|
+
|
|
|
(defvar *backoff-start* 1 "Initial back-off")
|
|
|
(defvar *backoff-max* 64 "Maximum back-off delay")
|
|
|
|