1
0
Преглед на файлове

[poller] Base polling plugins framework.

Innocenty Enikeew преди 6 години
родител
ревизия
ecf841e9f5
променени са 2 файла, в които са добавени 92 реда и са изтрити 2 реда
  1. 17 2
      common.lisp
  2. 75 0
      poller.lisp

+ 17 - 2
common.lisp

@@ -10,7 +10,8 @@
         :chatikbot.macros
         :chatikbot.bot
         :chatikbot.inline
-        :chatikbot.chat-cron)
+        :chatikbot.chat-cron
+        :chatikbot.poller)
   (:export :db-transaction
            :db-execute
            :db-select
@@ -168,6 +169,20 @@
            :add-chat-cron
            :get-chat-crons
            :delete-chat-cron
-           :def-chat-cron-handler))
+           :def-chat-cron-handler
 
+           :*poller-token*
+           :*poller-module*
+           :rest-parameters
+
+           :poller-request
+           :poller-validate
+           :poller-authenticate
+
+           :poller-error
+           :poller-no-secret
+           :poller-cant-authenticate
+
+           :poller-call
+           :poller-poll-list))
 (in-package :chatikbot.common)

+ 75 - 0
poller.lisp

@@ -0,0 +1,75 @@
+(in-package :cl-user)
+(defpackage chatikbot.poller
+  (:use :cl :chatikbot.utils)
+  (:export :*poller-token*
+           :*poller-module*
+           :filled
+           :rest-parameters
+
+           :poller-request
+           :poller-validate
+           :poller-authenticate
+
+           :poller-error
+           :poller-no-secret
+           :poller-cant-authenticate
+
+           :poller-call
+           :poller-poll-list))
+
+(defvar *tokens* (make-hash-table) "Module's tokens store")
+(defvar *state* (make-hash-table) "Module's state store")
+(defvar *poller-token* nil "Current user's API token")
+(defvar *poller-module* nil "Current module")
+
+(defun rest-parameters (rest)
+  (loop for (param value) on rest by #'cddr
+     when value collect (cons (dekeyify param) value)))
+
+(defun get-data (store chat-id &optional (module *poller-module*))
+  (let ((module-store (gethash module store)))
+    (when module-store (gethash chat-id module-store))))
+
+(defun set-data (store chat-id data &optional (module *poller-module*))
+  (let ((module-store (or (gethash module store)
+                          (setf (gethash module store)
+                                (make-hash-table)))))
+    (setf (gethash chat-id module-store) data)))
+
+(defgeneric poller-request (module method &rest params)
+  (:documentation "Performs api request to module"))
+(defgeneric poller-validate (module response)
+  (:documentation "Performs api result validation"))
+(defgeneric poller-authenticate (module secret)
+  (:documentation "Performs api request to module"))
+
+(define-condition poller-error (error) ())
+(define-condition poller-no-secret (poller-error) ())
+(define-condition poller-cant-authenticate (poller-error) ())
+
+(defun poller-call (module method &rest params)
+  (let* ((chat-id *chat-id*)
+         (*poller-module* module)
+         (*poller-token* (get-data *tokens* chat-id module))
+         (response (apply 'poller-request module method params)))
+    (if (poller-validate module response) response
+        (with-secret (secret (list module chat-id))
+          (unless secret (error 'polller-no-secret))
+          (let ((*poller-token* (poller-authenticate module secret)))
+            (unless *poller-token* (error 'poller-cant-authenticate))
+            (set-data *tokens* chat-id *poller-token* module)
+            (values (apply 'poller-request module method params)))))))
+
+(defun poller-poll-lists (module get-state-fn process-diff-fn &key (test #'equalp) (predicate #'<) key (max-store 200))
+  (dolist (*chat-id* (lists-get module))
+    (let* ((old (get-data *state* *chat-id* module))
+           (new (funcall get-state-fn))
+           (diff (sort (set-difference new old :test test)
+                       predicate :key key)))
+      (when diff
+        (when old
+          (funcall process-diff-fn diff))
+        (let ((merged (merge 'list old diff predicate :key key)))
+          (set-data *state* *chat-id*
+                    (subseq merged (max (- (length merged) max-store) 0))
+                    module))))))