summaryrefslogtreecommitdiff
path: root/src/state.lisp
blob: e2052e3a3b837fec486ad5fbda44a9588faec56e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
;; SPDX-License-Identifier: EUPL-1.2
;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
(defpackage :ukkoclot/src/state
  (:documentation "Holds the global state")
  (:nicknames :state)
  (:use :c2cl :ukkoclot/src/rw-lock)
  (:import-from :conf :config :*config* :bot-token)
  (:import-from :named-readtables :in-readtable)
  (:import-from :serapeum :->)
  (:import-from :ukkoclot/src/db :db)
  (:import-from :ukkoclot/src/readtable :readtable)
  (: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)
(in-readtable readtable)

(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))