aoc.lisp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. (in-package :cl-user)
  2. (defpackage chatikbot.plugins.aoc
  3. (:use :cl :chatikbot.common))
  4. (in-package :chatikbot.plugins.aoc)
  5. (defvar *year* 2021)
  6. (defvar *api-uri* (format nil "https://adventofcode.com/~A/leaderboard/private/view/24158.json" *year*))
  7. (defvar *leader-board-link* (format nil "https://adventofcode.com/~A/leaderboard/private/view/24158" *year*))
  8. (defvar *advent-time* (encode-universal-time 0 0 8 25 12 *year* -3))
  9. (defmethod poller-request ((module (eql :aoc)) method &rest params)
  10. (declare (ignorable params))
  11. (let ((cookie (format nil "session=~a" *poller-token*)))
  12. (handler-case
  13. (agets (json-request *api-uri* :headers `((:cookie . ,cookie))))
  14. (dex:http-request-failed (e) e))))
  15. (defmethod poller-validate ((module (eql :aoc)) response)
  16. (not (typep response 'dex:http-request-failed)))
  17. (defmethod poller-get-token ((module (eql :aoc)) secret)
  18. (let* ((*poller-token* secret))
  19. (poller-request :aoc "")
  20. (format nil "~a" secret)))
  21. (defun leaderboard ()
  22. (poller-call :aoc ""))
  23. (defun completion-state ()
  24. (loop for (uid . member) in (agets (leaderboard) "members")
  25. append (loop for (num . completion) in (agets member "completion_day_level")
  26. collect (list (parse-integer uid) (agets member "name") (parse-integer num) (length completion)))))
  27. (defun get-advent-days-active ()
  28. (max 0 (min 25 (- 25 (ceiling (/ (- *advent-time* (get-universal-time)) 86400))))))
  29. (defun format-stars(completions)
  30. (format nil "~{~a~}" (loop for daynum from 1 to (get-advent-days-active)
  31. for stars = (length (agets completions (write-to-string daynum)))
  32. collect (case stars (1 "☆") (2 "★") (t " • ")))))
  33. (defun format-leaderboard (json)
  34. (let ((sorted (sort (loop for (uid . member) in (agets json "members")
  35. collect (list (agets member "name")
  36. (agets member "local_score")
  37. (format-stars (agets member "completion_day_level"))))
  38. #'> :key #'second)))
  39. (format nil "🏆***Chad AoC Leaderboard***🏆~%~a~%~%~{~a. ~a: ~a ~% ~a~^~%~}" *leader-board-link*
  40. (apply 'append (mapcar #'cons (alexandria:iota (length sorted) :start 1) sorted)))))
  41. (defun handle-leaderboard ()
  42. (bot-send-message
  43. (handler-case
  44. (format-leaderboard (leaderboard))
  45. (poller-error ()
  46. "Надо обновить куки, старые истекли"))
  47. :parse-mode "markdown"))
  48. (defun format-completion-state-change (diff)
  49. (format nil "Обновился лидерборд 🏆***AoC*** 🏆~%~a~%~{~a!~^~%~}" *leader-board-link* (loop for (uid name daynum completed) in diff
  50. collect (format nil "***~a*** ебнул ~a задачку ~a дня" name completed daynum))))
  51. (defcron process-aoc (:minute '(member 0 15 30 45))
  52. (poller-poll-lists :aoc
  53. #'completion-state
  54. #'(lambda (diff)
  55. (log:info (list "Completion state diff:" diff))
  56. (bot-send-message (format-completion-state-change diff)
  57. :parse-mode "markdown"))
  58. :key #'first))
  59. (defun handle-set-cookie (cookie)
  60. (handler-case (progn
  61. (poller-authenticate :aoc cookie)
  62. (bot-send-message "Кука рабочая, теперь можешь делать запросы."))
  63. (poller-cant-authenticate ()
  64. (bot-send-message "Чот не смог, пропробуй другие."))))
  65. (defun handle-set-cron (enable)
  66. (lists-set-entry :aoc *chat-id* enable)
  67. (bot-send-message (if enable
  68. "Включил рассылку обновлений лидерборда. '/aoc updates off' чтобы выключить, /aoc - показать лидерборд."
  69. "Отключил рассылку обновлений лидерборда. '/aoc updates on' - включить, /aoc - показать лидерборд.")))
  70. (def-message-cmd-handler handle-cmd-aoc (:aoc)
  71. (cond
  72. ((= 1 (length *args*))
  73. (handle-set-cookie (car *args*)))
  74. ((= 2 (length *args*))
  75. (handle-set-cron (equal "on" (second *args*))))
  76. (:otherwise (handle-leaderboard))))