poller.lisp 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. (in-package :cl-user)
  2. (defpackage chatikbot.poller
  3. (:use :cl :chatikbot.db :chatikbot.utils :chatikbot.secrets)
  4. (:export :*poller-token*
  5. :*poller-module*
  6. :rest-parameters
  7. :poller-request
  8. :poller-validate
  9. :poller-get-token
  10. :poller-error
  11. :poller-no-secret
  12. :poller-cant-get-token
  13. :poller-cant-authenticate
  14. :poller-call
  15. :poller-poll-lists
  16. :poller-authenticate))
  17. (in-package :chatikbot.poller)
  18. (defvar *tokens* (make-hash-table) "Module's tokens store")
  19. (defvar *state* (make-hash-table) "Module's state store")
  20. (defvar *poller-token* nil "Current user's API token")
  21. (defvar *poller-module* nil "Current module")
  22. (defun rest-parameters (rest &optional raw)
  23. (loop for (param value) on rest by #'cddr
  24. when value collect (cons (if raw (string param)
  25. (dekeyify param))
  26. value)))
  27. (defun get-data (store chat-id &optional (module *poller-module*))
  28. (let ((module-store (gethash module store)))
  29. (when module-store (gethash chat-id module-store))))
  30. (defun set-data (store chat-id data &optional (module *poller-module*))
  31. (let ((module-store (or (gethash module store)
  32. (setf (gethash module store)
  33. (make-hash-table)))))
  34. (setf (gethash chat-id module-store) data)))
  35. (defgeneric poller-request (module method &rest params)
  36. (:documentation "Performs api request to module"))
  37. (defgeneric poller-validate (module response)
  38. (:documentation "Performs api result validation"))
  39. (defgeneric poller-get-token (module secret)
  40. (:documentation "Performs token generation out of module"))
  41. (define-condition poller-error (error) ())
  42. (define-condition poller-no-secret (poller-error) ())
  43. (define-condition poller-cant-get-token (poller-error) ())
  44. (define-condition poller-cant-authenticate (poller-error) ())
  45. (defun poller-call (module method &rest params)
  46. (let* ((chat-id *chat-id*)
  47. (*poller-module* module)
  48. (*poller-token* (get-data *tokens* chat-id module))
  49. (response (apply 'poller-request module method params)))
  50. (if (poller-validate module response) response
  51. (with-secret (secret (list module chat-id))
  52. (unless secret (error 'poller-no-secret))
  53. (let ((*poller-token* (poller-get-token module secret)))
  54. (unless *poller-token* (error 'poller-cant-get-token))
  55. (set-data *tokens* chat-id *poller-token* module)
  56. (values (apply 'poller-request module method params)))))))
  57. (defun poller-authenticate (module secret)
  58. (let ((token (poller-get-token module secret)))
  59. (unless token (error 'poller-cant-authenticate))
  60. (secret-set (list module *chat-id*) secret)
  61. token))
  62. (defun poller-poll-lists (module get-state-fn process-diff-fn &key (test #'equalp) (predicate #'<) key (max-store 200))
  63. (dolist (*chat-id* (lists-get module))
  64. (handler-case
  65. (let* ((old (get-data *state* *chat-id* module))
  66. (new (funcall get-state-fn))
  67. (diff (sort (set-difference new old :test test)
  68. predicate :key key)))
  69. (when diff
  70. (when old
  71. (funcall process-diff-fn diff))
  72. (let ((merged (merge 'list old diff predicate :key key)))
  73. (set-data *state* *chat-id*
  74. (subseq merged (max (- (length merged) max-store) 0))
  75. module))))
  76. (error (e) (log:error e)))))