1
0

macros.lisp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. (in-package :cl-user)
  2. (defpackage chatikbot.macros
  3. (:use :cl :chatikbot.utils :chatikbot.telegram :chatikbot.crypto)
  4. (:export :def-db-init
  5. :def-message-handler
  6. :def-message-cmd-handler
  7. :def-message-admin-cmd-handler
  8. :def-callback-handler
  9. :def-callback-section-handler
  10. :def-oauth-handler
  11. :def-oauth-section-handler
  12. :defcron))
  13. (in-package #:chatikbot.macros)
  14. (defmacro def-db-init (&body body)
  15. `(add-hook :db-init #'(lambda ()
  16. (handler-case (progn ,@body)
  17. (error (e) (log:error e)))
  18. (values))))
  19. (defmacro def-message-handler (name (message) &body body)
  20. `(progn
  21. (defun ,name (,message)
  22. (let ((message-id (aget "message_id" ,message))
  23. (from-id (aget "id" (aget "from" ,message)))
  24. (chat-id (aget "id" (aget "chat" ,message)))
  25. (text (aget "text" ,message)))
  26. (declare (ignorable message-id from-id chat-id text))
  27. (handler-case (progn ,@body)
  28. (error (e)
  29. (log:error "~A" e)
  30. (bot-send-message chat-id
  31. (format nil "Ошибочка вышла~@[: ~A~]"
  32. (when (member chat-id *admins*) e)))))))
  33. (add-hook :update-message ',name)))
  34. (defmacro def-message-cmd-handler (name (&rest commands) &body body)
  35. `(def-message-handler ,name (message)
  36. (when (and text (equal #\/ (char text 0)))
  37. (multiple-value-bind (cmd args) (parse-cmd text)
  38. (when (member cmd (list ,@commands))
  39. (log:info cmd message-id chat-id from-id args)
  40. ,@body
  41. t)))))
  42. (defmacro def-message-admin-cmd-handler (name (&rest commands) &body body)
  43. `(def-message-handler ,name (message)
  44. (when (and (member chat-id *admins*)
  45. text (equal #\/ (char text 0)))
  46. (multiple-value-bind (cmd args) (parse-cmd text)
  47. (when (member cmd (list ,@commands))
  48. (log:info cmd message-id chat-id from-id args)
  49. ,@body
  50. t)))))
  51. (defmacro def-callback-handler (name (callback) &body body)
  52. `(progn
  53. (defun ,name (,callback)
  54. (let* ((query-id (aget "id" ,callback))
  55. (from (aget "from" ,callback))
  56. (raw-data (aget "data" ,callback))
  57. (message (aget "message" ,callback))
  58. (inline-message-id (aget "inline_message_id" ,callback))
  59. (from-id (aget "id" from))
  60. (chat-id (aget "id" (aget "chat" message)))
  61. (message-id (aget "message_id" message)))
  62. (declare (ignorable query-id from raw-data message inline-message-id from-id chat-id message-id))
  63. (handler-case (progn ,@body)
  64. (error (e)
  65. (log:error "~A" e)
  66. (bot-send-message (or chat-id from-id)
  67. (format nil "Ошибочка вышла~@[: ~A~]"
  68. (when (member chat-id *admins*) e)))))))
  69. (add-hook :update-callback-query ',name)))
  70. (defmacro def-callback-section-handler (name (&rest sections) &body body)
  71. `(def-callback-handler ,name (callback)
  72. (when chat-id
  73. (multiple-value-bind (data section) (decode-callback-data chat-id raw-data)
  74. (when (member section (list ,@sections))
  75. (log:info query-id from-id chat-id message-id section data)
  76. ,@body
  77. t)))))
  78. (defmacro def-oauth-handler (name (code error state) &body body)
  79. `(progn
  80. (defun ,name (,code ,error ,state)
  81. (declare (ignorable ,code ,error ,state))
  82. (handler-case (progn ,@body)
  83. (error (e)
  84. (log:error "~A" e)
  85. (hunchentoot:redirect "/error"))))
  86. (add-hook :oauth ',name)))
  87. (defmacro def-oauth-section-handler (name (&rest sections) &body body)
  88. `(def-oauth-handler ,name (code error raw-state)
  89. (multiple-value-bind (state section) (decode-oauth-state raw-state)
  90. (when (member section (list ,@sections))
  91. ,@body
  92. t))))
  93. ;; Schedule
  94. (defmacro defcron (name (&rest schedule) &body body)
  95. (let ((schedule (or schedule '(:minute '* :hour '*)))
  96. (scheduler (symbol-append name '-scheduler)))
  97. `(progn
  98. (defun ,name ()
  99. (unwind-protect
  100. (handler-case (progn ,@body)
  101. (error (e) (log:error e)))
  102. (dex:clear-connection-pool)))
  103. (defun ,scheduler ()
  104. (clon:schedule-function
  105. ',name (clon:make-scheduler
  106. (clon:make-typed-cron-schedule
  107. ,@schedule)
  108. :allow-now-p t)
  109. :name ',name :thread t)
  110. (values))
  111. (add-hook :starting ',scheduler))))