zsd.lisp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. (in-package :cl-user)
  2. (defpackage chatikbot.plugins.zsd
  3. (:use :cl :chatikbot.common))
  4. (in-package :chatikbot.plugins.zsd)
  5. (defparameter +zsd-api-url+ "https://mcabinet.nch-spb.com/onyma/system/api/json")
  6. (defparameter +zsd-auth-url+ "https://mcabinet.nch-spb.com/onyma/system/api/jsonex?function=open_session")
  7. (defun %zsd/api (token method &optional args)
  8. (let* ((f (concatenate 'string "onm_api_toll_api_" method))
  9. (params (loop for (k . v) in args when v
  10. collect (cons (princ-to-string k) (princ-to-string v))))
  11. (response
  12. (json-request
  13. +zsd-api-url+
  14. :parameters (append params `(("function" . ,f)
  15. ("auth_token" . ,token))))))
  16. (values (aget "return" response) (aget "more_rows" response))))
  17. (defun zsd/auth (login password)
  18. (aget "return"
  19. (json-request +zsd-auth-url+ :method :post
  20. :content (plist-json (list :realm "WHSD"
  21. :user login
  22. :pass password)))))
  23. (defun zsd/pan (token)
  24. (%zsd/api token "mobile_pan"))
  25. (defun zsd/contract (token)
  26. (%zsd/api token "contract_info"))
  27. (defun zsd/wall (token &optional (offset 0) (limit 5))
  28. (%zsd/api token "mobile_wall"
  29. `(("rows_skip" . ,offset) ("rows_limit" . ,limit))))
  30. (defun zsd/load-data (token &optional (limit 5))
  31. `(("contract" . ,(zsd/contract token))
  32. ("pan" . ,(zsd/pan token))
  33. ("wall" . ,(zsd/wall token 0 limit))))
  34. (defun %zsd/format-wall (item pans)
  35. (let* ((pan (aget "pan" item))
  36. (alias (aget "alias" (find pan pans :test #'equal :key (lambda (el) (aget "pan" el)))))
  37. (event (parse-integer (aget "event_type" item)))
  38. (amount (aget "amount" item))
  39. (entry (aget "entry_place" item))
  40. (place (aget "place" item))
  41. (cdt (aget "cdt" item)))
  42. (case event
  43. (1 (format nil "~A *~aр.*: 🚗 ~a, _~a → ~a_" cdt amount (or alias pan) entry place))
  44. (101 (format nil "~A *~aр.*: 💶 _~a_" cdt amount place)))))
  45. (defun zsd/format-changes (old new)
  46. (let ((wall-diff (set-difference (aget "wall" new) (aget "wall" old) :test #'equal)))
  47. (when wall-diff
  48. (format nil "ЗСД остаток: *~$р.*~%~%~{~A~^~%~}"
  49. (parse-float (aget "remainder" (car (aget "contract" new))))
  50. (loop for item in wall-diff
  51. collect (%zsd/format-wall item (aget "pan" new)))))))
  52. (defun zsd/handle-set-cron (chat-id enable)
  53. (lists-set-entry :zsd chat-id enable)
  54. (bot-send-message chat-id
  55. (if enable
  56. "Включил рассылку. '/zsd off' чтобы выключить, /zsd - показать последние."
  57. "Без рассылки. '/zsd on' - включить, /zsd - последние.")))
  58. (defun zsd/handle-auth (chat-id login pass)
  59. (let ((token (zsd/auth login pass)))
  60. (if token
  61. (progn
  62. (secret-set `(:zsd ,chat-id) token)
  63. (zsd/handle-set-cron chat-id t))
  64. (bot-send-message chat-id "Чот не смог, пропробуй другие."))))
  65. (defun zsd/handle-recent (chat-id)
  66. (with-secret (token (list :zsd chat-id))
  67. (bot-send-message chat-id
  68. (if token
  69. (let ((data (zsd/load-data token)))
  70. (if data
  71. (zsd/format-changes nil data)
  72. "Не смог получить данные. Попробуй перелогинься. /zsd <login> <pass>"))
  73. "Нужен логин-пароль. /zsd <login> <pass>")
  74. :parse-mode "markdown")))
  75. (def-message-cmd-handler handle-cmd-zsd (:zsd)
  76. (cond
  77. ((= 1 (length args))
  78. (zsd/handle-set-cron chat-id (equal "on" (car args))))
  79. ((= 2 (length args)) (apply 'zsd/handle-auth chat-id args))
  80. (:otherwise (zsd/handle-recent chat-id))))
  81. (defvar *zsd/last-results* (make-hash-table) "Last check results")
  82. (defcron process-zsd (:minute '(member 0 10 20 30 40 50))
  83. (dolist (chat-id (lists-get :zsd))
  84. (with-secret (token (list :zsd chat-id))
  85. (if token
  86. (let ((old (gethash chat-id *zsd/last-results*))
  87. (new (zsd/load-data token)))
  88. (when new
  89. (when old
  90. (alexandria:when-let ((changes (zsd/format-changes old new)))
  91. (bot-send-message chat-id changes :parse-mode "markdown")))
  92. (setf (gethash chat-id *zsd/last-results*) new)))
  93. (progn
  94. (log:warn "zsd no token for" chat-id))))))