;; SPDX-License-Identifier: EUPL-1.2 ;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs (defpackage :ukkoclot/src/state (:documentation "Holds the global state") (:nicknames :state) (:use :c2cl :ukkoclot/src/rw-lock) (:import-from :com.dieggsy.f-string :enable-f-strings) (:import-from :conf :config :*config* :bot-token) (:import-from :serapeum :->) (:import-from :ukkoclot/src/db :db) (:export #:*state* #:state #:make-state #:state-p #:db #:base-uri #:power-on #:set-power-on #:username% #:set-username% #:id% #:set-id%)) (in-package :ukkoclot/src/state) (enable-f-strings) (defstruct (state (:constructor make-state%)) (lock (make-rw-lock :name "state's lock") :type rw-lock :read-only t) (db (error "No value given for DB") :type db :read-only t) (base-uri (error "No value given for base-uri") :type string :read-only t) (power-on t :type boolean) (username% nil :type (or string null)) (id% nil :type (or integer null))) (-> make-state (db &optional config) state) (defun make-state (db &optional (config *config*)) (check-type db db) (let ((base-uri #f"https://api.telegram.org/bot{(bot-token config)}/")) (make-state% :db db :base-uri base-uri))) (defvar *state* nil "Bot's general state. You should initialise this with a value before doing anything fun.") (declaim (type (or state null) *state*)) (-> db (&optional state) db) (defun db (&optional (state *state*)) "Get the database handle of the bot." (with-slots (lock db) state (with-read-lock (lock) db))) (-> base-uri (&optional state) string) (defun base-uri (&optional (state *state*)) "Get the base URI of the bot." (with-slots (lock base-uri) state (with-read-lock (lock) base-uri))) (-> power-on (&optional state) boolean) (defun power-on (&optional (state *state*)) "Get whether the bot is running" (with-slots (lock power-on) state (with-read-lock (lock) power-on))) (-> set-power-on (boolean &optional state) boolean) (defun set-power-on (new-value &optional (state *state*)) "Set the value of the power-on" (with-slots (lock power-on) state (with-write-lock (lock) (setf power-on new-value)))) (defsetf power-on (&optional (state '*state*)) (new-value) `(set-power-on ,new-value ,state)) (-> username% (&optional state) (or string null)) (defun username% (&optional (state *state*)) "Get the cached bot's username, you should probably use `ukkoclot/src/tg:bot-username' instead." (with-slots (lock username%) state (with-read-lock (lock) username%))) (-> set-username% (string &optional state) string) (defun set-username% (new-value &optional (state *state*)) (with-slots (lock username%) state (with-write-lock (lock) (setf username% new-value)))) (defsetf username% (&optional (state '*state*)) (new-value) `(set-username% ,new-value ,state)) (-> id% (&optional state) (or integer null)) (defun id% (&optional (state *state*)) "Get the cached bot's ID, you should probably use `ukkoclot/src/tg:bot-id' instead." (with-slots (lock id%) state (with-read-lock (lock) id%))) (-> set-id% (integer &optional state) integer) (defun set-id% (new-value &optional (state *state*)) (with-slots (lock id%) state (with-write-lock (lock) (setf id% new-value)))) (defsetf id% (&optional (state '*state*)) (new-value) `(set-id% ,new-value ,state))