diff --git a/bot.lisp b/bot.lisp index fc0b3ca..a507fde 100644 --- a/bot.lisp +++ b/bot.lisp @@ -1,7 +1,120 @@ (in-package :cl-user) +;; (defpackage :birthday-boy +;; (:use :cl) +;; (:export main*)) +;; (in-package :birthday-boy) (load (sb-ext:posix-getenv "ASDF")) -(asdf:load-systems :dexador :cl-dotenv) -;; (print (dex:get "https://duck.com")) -(print (.env:load-env (merge-pathnames ".env"))) -(exit :code 0) +(asdf:load-systems :dexador :local-time :jonathan) +;; +;; (.env:load-env (merge-pathnames ".env")) +;; (ql:quickload '(:dexador :cl-dotenv :local-time :jonathan)) + +(defun now-string () + (local-time:format-timestring + nil + (local-time:now) + :format + local-time:+iso-8601-format+)) ;; 2008-03-01T19:42:34.608506+01:00 + +(defvar *txn-counter* 0) +(defun make-txn-id () + (format nil "~A~A" (now-string) (incf *txn-counter*))) + +(defun put-json-content (uri json-content) + (dex:put uri + :headers '((:content-type . "application/json")) + :content (jojo:to-json json-content))) + + +(defun put-json-content-auth (uri json-content) + (dex:put uri + :headers `((:|Authorization| . ,(format nil "Bearer ~A" (uiop:getenv "BOT_ACCESS_TOKEN")) ) + (:content-type . "application/json")) + :content (jojo:to-json json-content))) + +(defun post-json-content (uri json-content) + (dex:post uri + :headers '((:content-type . "application/json")) + :content (jojo:to-json json-content))) +(defun post-json-content-auth (uri json-content) + (dex:post uri + :headers `((:|Authorization| . ,(format nil "Bearer ~A" (uiop:getenv "BOT_ACCESS_TOKEN")) ) + (:content-type . "application/json")) + :content (jojo:to-json json-content))) + + +(defun make-homeserver-endpoint (endpoint) + (format nil "~a~a" (uiop:getenv "HOMESERVER_URL") endpoint)) + +(defun get-access-token () + (let ((res + (jojo:parse + (post-json-content (make-homeserver-endpoint "/_matrix/client/v3/login" ) + (list :|identifier| (list :|type| "m.id.user" :|user| (uiop:getenv "BOT_NAME")) + :|type| "m.login.password" + :|password| (uiop:getenv "BOT_PW")))))) + (values + (getf res :|access_token|) + (getf res :|device_id|)))) + +(defun message (msg &optional (room-id "GENERAL2_ROOM_ID")) + (put-json-content-auth + ;; (format nil "https://matrix.groupchattt.page/_matrix/client/v3/rooms/~a/send/m.room.message/~a" + ;; (uiop:getenv room-id) + ;; (make-txn-id)) + (make-homeserver-endpoint (format nil "/_matrix/client/v3/rooms/~a/send/m.room.message/~a" + (uiop:getenv room-id) + (make-txn-id))) + (list + :|msgtype| "m.text" + :|body| msg))) + + +;; (defun request-join (room) +;; (post-json-content-auth +;; (make-homeserver-endpoint (format nil "/_matrix/client/v3/knock/~A" room)) +;; (list +;; :|reason| "for birthday bot"))) + +(defvar *birthdays* '((:person "carl" :month 4 :day 13) + (:person "noellie" :month 7 :day 15) + (:person "joe" :month 9 :day 17) + (:person "daniel" :month 7 :day 18) + (:person "mike" :month 2 :day 13) + (:person "David Tennant" :month 4 :day 18) + (:person "famous actor Sean Bean" :month 4 :day 17) + (:person "bwandice" :month 10 :day 15))) + + +(defun is-today (tstamp) + "Check just the day and month of today and tstamp and return true if its today" + (let ((today (local-time:now))) + (if (and (eql (local-time:timestamp-day today) + (local-time:timestamp-day tstamp)) + (eql (local-time:timestamp-month today) + (local-time:timestamp-month tstamp))) + t + nil))) + +(defun is-today* (day month) + (is-today (local-time:encode-timestamp 0 0 0 0 day month 1900))) + + +(defun collect-bdays () + (loop for person in *birthdays* + when (is-today* (getf person :day) (getf person :month)) + collect person)) + + +(defun make-bday-message (person) + (format nil "Hey hey hey, its the birthday boy, and I am pleased to announce that it is ~A's today. Congratulation, I love you." person)) + +(defun main () + ;; (.env:load-env env-file) + (dolist (person (collect-bdays)) + (message (make-bday-message (getf person :person)) "ROOM_ID"))) + +(defun main* () + (unwind-protect (main) + (sb-ext:exit :code 0))) diff --git a/flake.nix b/flake.nix index 74159d7..0bc6752 100644 --- a/flake.nix +++ b/flake.nix @@ -19,20 +19,59 @@ ]; systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ]; - perSystem = { config, self', inputs', pkgs, system, ... }: { - # Per-system attributes can be defined here. The self' and inputs' - # module parameters provide easy access to attributes of the same - # system. + perSystem = { config, self', inputs', pkgs, system, ... }: + let + sbcl' = pkgs.sbcl.withPackages + (ps: with ps; [ dexador cl-dotenv jonathan local-time deploy ]); + in { + # Per-system attributes can be defined here. The self' and inputs' + # module parameters provide easy access to attributes of the same + # system. - # Equivalent to inputs'.nixpkgs.legacyPackages.hello; - packages.default = pkgs.hello; - devshells.default = { - env = [ ]; - commands = [ ]; - packages = with pkgs; - [ (sbcl.withPackages (p: [ p.dexador p.cl-dotenv ])) ]; + # Equivalent to inputs'.nixpkgs.legacyPackages.hello; + packages.default = pkgs.hello; + + packages.birthday-boy = pkgs.stdenv.mkDerivation { + name = "birthday-boy"; + src = ./.; + + nativeBuildInputs = with pkgs; [ openssl sbcl' ]; + dontStrip = true; + + buildPhase = '' + ${sbcl'}/bin/sbcl --load ./bot.lisp \ + --eval '(sb-ext:save-lisp-and-die #P"birthday-boy" :toplevel #'"'"'main* :executable t)' + ''; + + installPhase = '' + mkdir -p $out/bin + cp birthday-boy $out/bin/_birthday-boy + chmod +x $out/bin/_birthday-boy + + touch $out/bin/birthday-boy + echo "#!/usr/bin/env sh" >> $out/bin/birthday-boy + echo "env \$(grep -v '^#' \$1 | xargs -d '\n') LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:${ + pkgs.lib.makeLibraryPath [ pkgs.openssl ] + } $out/bin/_birthday-boy" >> $out/bin/birthday-boy + + # cp run.sh $out/bin/birthday-boy + chmod +x $out/bin/birthday-boy + ''; + }; + apps.birthday-boy = { + type = "app"; + program = "${self'.packages.birthday-boy}/bin/birthday-boy"; + }; + devshells.default = { + env = [ ]; + commands = [ ]; + packages = with pkgs; [ + openssl + (sbcl.withPackages + (p: with p; [ dexador cl-dotenv jonathan local-time deploy ])) + ]; + }; }; - }; flake = { # The usual flake attributes can be defined here, including system- # agnostic ones like nixosModule and system-enumerating ones, although diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..d1bcb50 --- /dev/null +++ b/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +export $(grep -v '^#' ${1:-.env} | xargs -d '\n') +$out/bin/_birthday-boy