summaryrefslogtreecommitdiff
path: root/src/config.lisp
blob: 7117de32e54c5c3bd670eb00c24df5a232bd587a (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
;; SPDX-License-Identifier: EUPL-1.2
;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
(defpackage :ukkoclot/src/config
  (:documentation "Stuff for loading the configuration of the bot")
  (:nicknames :conf)
  (:use :c2cl :iterate :ukkoclot/src/rw-lock)
  (:import-from :alexandria :make-keyword)
  (:import-from :serapeum :->)
  (:export
   #:*config*
   #:config
   #:make-config
   #:config-p
   #:copy-config
   #:load-config
   #:print-default
   #:bot-name
   #:bot-token
   #:db-path
   #:dev-group
   #:owner))
(in-package :ukkoclot/src/config)

(defstruct config
  (lock (make-rw-lock :name "config's lock") :type rw-lock :read-only t)
  (bot-name "Ukko's Clot" :type string)
  (bot-token "123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi" :type string)
  (db-path #P"./data.db" :type (or pathname string))
  (dev-group -1001234567890 :type integer)
  (owner 12345678 :type integer))

(defvar *config* (make-config)
  "Bot's configuration")

(-> bot-name (&optional config) string)
(defun bot-name (&optional (config *config*))
  "Get the desired name for the bot"
  (with-slots (lock bot-name) config
    (with-read-lock (lock)
      bot-name)))

(-> bot-token (&optional config) string)
(defun bot-token (&optional (config *config*))
  "Get the API token for the bot"
  (with-slots (lock bot-token) config
    (with-read-lock (lock)
      bot-token)))

(-> db-path (&optional config) pathname)
(defun db-path (&optional (config *config*))
  "Get the path to the bot's database"
  (with-slots (lock db-path) config
    (with-read-lock (lock)
      (pathname db-path))))

(-> dev-group (&optional config) integer)
(defun dev-group (&optional (config *config*))
  "Get the ID of the dev/testing group"
  (with-slots (lock dev-group) config
    (with-read-lock (lock)
      dev-group)))

(-> owner (&optional config) integer)
(defun owner (&optional (config *config*))
  "Get the ID of the bot's owner"
  (with-slots (lock owner) config
    (with-read-lock (lock)
      owner)))

(-> load-config (pathname &optional config) config)
(defun load-config (filename &optional (config *config*))
  "Load config from the given `filename'."
  (prog1 config
    (let ((data (with-open-file (f filename) (read f))))
      (with-write-lock ((config-lock config))
        (iter
          (for (kw-name value) on data by #'cddr)
          (let ((name (intern (symbol-name kw-name) :ukkoclot/src/config)))
            (setf (slot-value config name) value)))))))

(-> serialize (config) list)
(defun serialize (config)
  "Serializes the config to a plist."
  (with-read-lock ((config-lock config))
    (iter
      (for slot in (class-direct-slots (class-of config)))
      (let ((name (slot-definition-name slot)))
        (unless (eql name 'lock)
          (appending (list (make-keyword name)
                           (slot-value config name))))))))

(-> print-default (pathname) (values &optional))
(defun print-default (filename)
  "Prints the default config to the given `filename'."
  (with-open-file (f filename :direction :output :if-exists :supersede)
    (format f ";; lint:suppress in-package spdx-license-identifier~%")
    (format f ";; Copy this file to config.lisp and modify it there~%")
    (let ((data (serialize (make-config))))
      (format f "~<(~;~@{~(~W~) ~W~^ ~_~}~;)~:>~%" data)))
  (values))