1
0

gazprom.lisp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. (in-package :cl-user)
  2. (defpackage chatikbot.plugins.gazprom
  3. (:use :cl :chatikbot.common :alexandria))
  4. (in-package :chatikbot.plugins.gazprom)
  5. (defparameter +gpn-api-url+ "https://api.gpnbonus.ru/ios/v2/")
  6. (defvar *api-os* "android")
  7. (defvar *api-ver* "1.7.4")
  8. (defvar *api-token* "21c733213e747611432154b1bf96e723")
  9. (defvar *session* nil "Currently active session")
  10. (defvar *credentials-provider* nil "Active credentials provider")
  11. (defun filled (alist)
  12. (remove nil alist :key #'cdr))
  13. (defun %api (method &optional params)
  14. (let* ((response
  15. (json-request (concatenate 'string +gpn-api-url+ method)
  16. :parameters (filled (append `(("session" . ,*session*)
  17. ("os" . ,*api-os*)
  18. ("ver" . ,*api-ver*))
  19. params))))
  20. (message (agets response "message")))
  21. (if (equal message "Необходимо авторизоваться")
  22. (if *credentials-provider*
  23. (progn
  24. (funcall *credentials-provider*
  25. (lambda (login password)
  26. (setf *session* (^auth login password))))
  27. (let (*credentials-provider*) ;; Retry call resetting *credentials-provider* to prevent loop
  28. (%api method params)))
  29. (error message))
  30. response)))
  31. (defun ^auth (login pass)
  32. (let* ((resp
  33. (json-request (concatenate 'string +gpn-api-url+ "auth.php")
  34. :method :post
  35. :content `(("login" . ,login)
  36. ("passw" . ,pass)
  37. ("token" . ,*api-token*)
  38. ("os" . ,*api-os*)
  39. ("ver" . ,*api-ver*))))
  40. (status (agets resp "status")))
  41. (unless (= status 1)
  42. (error (agets resp "message")))
  43. (agets resp "session")))
  44. (defun ^get-card-info ()
  45. (%api "getCardInfo.php"))
  46. (defun ^get-order (&key (count 20) (offset 0))
  47. (%api "getOrder.php" `(("count" . ,count) ("offset" . ,offset))))
  48. ;; Cron
  49. (defvar *last-entries* (make-hash-table) "Last per-chat entries")
  50. (defvar *sessions* (make-hash-table) "Per-chat sessions")
  51. (defmacro with-chat-credentials ((chat-id) &body body)
  52. `(let* ((*session* (gethash ,chat-id *sessions*))
  53. (*credentials-provider* (lambda (authenticator)
  54. (with-secret (login-pass (list :gazprom ,chat-id))
  55. (if login-pass
  56. (apply authenticator login-pass)
  57. (error "no gazprom credentials for ~A" ,chat-id))))))
  58. (prog1 (progn ,@body)
  59. (setf (gethash chat-id *sessions*) *session*))))
  60. (defun get-chat-last-n-entries (chat-id &optional (count 10))
  61. (with-chat-credentials (chat-id)
  62. (let ((accounts (^account))
  63. (transactions (remove nil (agets (^transaction :size count) "list")
  64. :key (agetter "type"))))
  65. (sort (loop for tr in transactions
  66. collect (move->entry (append tr (list (cons "account" (get-transaction-account tr accounts))))))
  67. #'< :key #'pta-ledger:entry-date))))
  68. (defun get-chat-accounts (chat-id)
  69. (with-chat-credentials (chat-id)
  70. (concatenate 'list (^account) (^loan))))
  71. (defcron process-gazprom (:minute '(member 0 5 10 15 20 25 30 35 40 45 50 55))
  72. (dolist (chat-id (lists-get :gazprom))
  73. (let ((old (gethash chat-id *last-entries*))
  74. (new (get-chat-last-n-entries chat-id 20))
  75. (ledger-package (find-package :chatikbot.plugins.ledger)))
  76. (when new
  77. (when old
  78. (when-let (changes (set-difference new old :test #'equalp))
  79. (log:info changes)
  80. (if ledger-package
  81. (let ((new-chat-entry (symbol-function
  82. (intern "LEDGER/NEW-CHAT-ENTRY" ledger-package))))
  83. (dolist (entry changes)
  84. (funcall new-chat-entry chat-id (pta-ledger:clone-entry entry))))
  85. (bot-send-message chat-id (format-entries changes) :parse-mode "markdown"))))
  86. (setf (gethash chat-id *last-entries*) new)))))
  87. (def-message-cmd-handler handler-gazprom (:gpn :gazprom)
  88. (let ((arg (car args)))
  89. (if (string= arg "bal")
  90. (bot-send-message chat-id (format-balance (get-chat-accounts chat-id)) :parse-mode "markdown")
  91. (let ((last (get-chat-last-n-entries chat-id (if arg (parse-integer arg) 10))))
  92. (bot-send-message chat-id (format-entries last) :parse-mode "markdown")))))