summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hash-tables.lisp2
-rw-r--r--src/main.lisp14
-rw-r--r--src/serializing.lisp6
-rw-r--r--src/strings.lisp55
-rw-r--r--src/tg/method-macros.lisp6
-rw-r--r--src/tg/type-macros.lisp4
6 files changed, 25 insertions, 62 deletions
diff --git a/src/hash-tables.lisp b/src/hash-tables.lisp
index d3b66dd..84ffbfe 100644
--- a/src/hash-tables.lisp
+++ b/src/hash-tables.lisp
@@ -1,7 +1,7 @@
1;; SPDX-License-Identifier: EUPL-1.2 1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com> 2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/hash-tables 3(defpackage :ukkoclot/hash-tables
4 (:documentation "Utilities for dealing with hash tables.") 4 (:documentation "Hash-table-oriented utilities.")
5 (:use :c2cl) 5 (:use :c2cl)
6 (:import-from :alexandria :with-gensyms) 6 (:import-from :alexandria :with-gensyms)
7 (:export :alist->hash-table :gethash-lazy :plist->hash-table)) 7 (:export :alist->hash-table :gethash-lazy :plist->hash-table))
diff --git a/src/main.lisp b/src/main.lisp
index 28c3801..5d3cf76 100644
--- a/src/main.lisp
+++ b/src/main.lisp
@@ -7,11 +7,11 @@
7 (:import-from :com.dieggsy.f-string :enable-f-strings) 7 (:import-from :com.dieggsy.f-string :enable-f-strings)
8 (:import-from :log) 8 (:import-from :log)
9 (:import-from :serapeum :drop) 9 (:import-from :serapeum :drop)
10 (:import-from :str)
10 (:import-from :ukkoclot/db :with-db) 11 (:import-from :ukkoclot/db :with-db)
11 (:import-from :ukkoclot/serializing :fixup-value) 12 (:import-from :ukkoclot/serializing :fixup-value)
12 (:import-from :ukkoclot/state :make-bot :bot-config :bot-power-on) 13 (:import-from :ukkoclot/state :make-bot :bot-config :bot-power-on)
13 (:import-from :ukkoclot/strings 14 (:import-from :ukkoclot/strings :escape-xml :is-tg-whitespace :is-tg-whitespace-str)
14 :escape-xml :is-tg-whitespace :is-tg-whitespace-str :starts-with :starts-with-ignore-case)
15 (:local-nicknames 15 (:local-nicknames
16 (:jzon :com.inuoe.jzon)) 16 (:jzon :com.inuoe.jzon))
17 (:export :main)) 17 (:export :main))
@@ -70,7 +70,7 @@
70(defun on-callback-query (bot cb) 70(defun on-callback-query (bot cb)
71 (let ((data (callback-query-data cb))) 71 (let ((data (callback-query-data cb)))
72 (cond ((and data 72 (cond ((and data
73 (starts-with data "bbl:") 73 (str:starts-with-p "bbl:" data :ignore-case nil)
74 (= (user-id (callback-query-from cb)) 74 (= (user-id (callback-query-from cb))
75 (config-owner (bot-config bot)))) 75 (config-owner (bot-config bot))))
76 (let ((bot-id (read-from-string data t nil :start 4))) 76 (let ((bot-id (read-from-string data t nil :start 4)))
@@ -83,7 +83,7 @@
83 :callback-query-id (callback-query-id cb) 83 :callback-query-id (callback-query-id cb)
84 :text "OK")) 84 :text "OK"))
85 ((and data 85 ((and data
86 (starts-with data "bwl:") 86 (str:starts-with-p "bwl:" data :ignore-case nil)
87 (= (user-id (callback-query-from cb)) 87 (= (user-id (callback-query-from cb))
88 (config-owner (bot-config bot)))) 88 (config-owner (bot-config bot))))
89 (let ((bot-id (read-from-string data t nil :start 4))) 89 (let ((bot-id (read-from-string data t nil :start 4)))
@@ -161,7 +161,7 @@
161 ((equal text ">:3") 161 ((equal text ">:3")
162 (reply-message bot msg "<b>&gt;:3</b>" :parse-mode html)) 162 (reply-message bot msg "<b>&gt;:3</b>" :parse-mode html))
163 163
164 ((starts-with-ignore-case text "big ") 164 ((str:starts-with-p "big " text)
165 (let ((the-text (drop 4 text))) 165 (let ((the-text (drop 4 text)))
166 (unless (is-tg-whitespace-str the-text) 166 (unless (is-tg-whitespace-str the-text)
167 (reply-message bot msg 167 (reply-message bot msg
@@ -190,12 +190,12 @@
190 (or (message-reply-to-message msg) msg) 190 (or (message-reply-to-message msg) msg)
191 "dio cane")) 191 "dio cane"))
192 192
193 ((starts-with-ignore-case text "say ") 193 ((str:starts-with-p "say " text)
194 (let ((the-text (drop 4 text))) 194 (let ((the-text (drop 4 text)))
195 (unless (is-tg-whitespace-str the-text) 195 (unless (is-tg-whitespace-str the-text)
196 (reply-message bot msg the-text)))) 196 (reply-message bot msg the-text))))
197 197
198 ((starts-with-ignore-case text "tiny ") 198 ((str:starts-with-p "tiny " text)
199 (let ((the-text (drop 5 text))) 199 (let ((the-text (drop 5 text)))
200 (unless (is-tg-whitespace-str the-text) 200 (unless (is-tg-whitespace-str the-text)
201 (reply-message bot msg 201 (reply-message bot msg
diff --git a/src/serializing.lisp b/src/serializing.lisp
index 205190f..71b0fb2 100644
--- a/src/serializing.lisp
+++ b/src/serializing.lisp
@@ -3,7 +3,7 @@
3(defpackage :ukkoclot/serializing 3(defpackage :ukkoclot/serializing
4 (:use :c2cl :iterate) 4 (:use :c2cl :iterate)
5 (:import-from :log) 5 (:import-from :log)
6 (:import-from :ukkoclot/strings :lisp->snake-case) 6 (:import-from :str)
7 (:local-nicknames 7 (:local-nicknames
8 (:jzon :com.inuoe.jzon)) 8 (:jzon :com.inuoe.jzon))
9 (:export :fixup-args :fixup-value :parse-value :try-parse-value)) 9 (:export :fixup-args :fixup-value :parse-value :try-parse-value))
@@ -11,9 +11,7 @@
11 11
12(defun fixup-args (args) 12(defun fixup-args (args)
13 (iter (for (key . value) in args) 13 (iter (for (key . value) in args)
14 (collect 14 (collect (cons (str:snake-case key) (fixup-value value)))))
15 (cons (string-downcase (lisp->snake-case (symbol-name key)))
16 (fixup-value value)))))
17 15
18(defgeneric fixup-value (value) 16(defgeneric fixup-value (value)
19 (:documentation "Fixup outgoing *top-level* `value' before passing it to telegram.") 17 (:documentation "Fixup outgoing *top-level* `value' before passing it to telegram.")
diff --git a/src/strings.lisp b/src/strings.lisp
index b1b4f00..eae8ec0 100644
--- a/src/strings.lisp
+++ b/src/strings.lisp
@@ -1,33 +1,30 @@
1;; SPDX-License-Identifier: EUPL-1.2 1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com> 2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/strings 3(defpackage :ukkoclot/strings
4 (:documentation "String-oriented utilities.")
4 (:use :c2cl :iterate) 5 (:use :c2cl :iterate)
5 (:import-from :cl-unicode :general-category) 6 (:import-from :cl-unicode :general-category)
6 (:export 7 (:export
7 :ends-with
8 :escape-xml 8 :escape-xml
9 :is-tg-whitespace 9 :is-tg-whitespace
10 :is-tg-whitespace-str 10 :is-tg-whitespace-str))
11 :lisp->camel-case
12 :lisp->snake-case
13 :snake->lisp-case
14 :starts-with
15 :starts-with-ignore-case))
16(in-package :ukkoclot/strings) 11(in-package :ukkoclot/strings)
17 12
18;; These are very inefficient but I don't care until I profile 13;; These are very inefficient but I don't care until I profile
19 14
20(defun ends-with (str suffix)
21 (and (> (length str) (length suffix))
22 (string= str suffix :start1 (- (length str) (length suffix)))))
23
24(defun escape-xml (str &optional out) 15(defun escape-xml (str &optional out)
16 "Escape special XML characters in the STR.
17
18OUT is the output stream or `nil' for outputting to a string."
25 (if out 19 (if out
26 (escape-xml% str out) 20 (escape-xml% str out)
27 (with-output-to-string (out) 21 (with-output-to-string (out)
28 (escape-xml% str out)))) 22 (escape-xml% str out))))
29 23
30(defun escape-xml% (str out) 24(defun escape-xml% (str out)
25 "See `escape-xml'.
26
27OUT is always the stream."
31 (loop for ch across str do 28 (loop for ch across str do
32 (case ch 29 (case ch
33 (#\< (write-string "&lt;" out)) 30 (#\< (write-string "&lt;" out))
@@ -37,6 +34,7 @@
37 (otherwise (write-char ch out))))) 34 (otherwise (write-char ch out)))))
38 35
39(defun is-tg-whitespace (ch) 36(defun is-tg-whitespace (ch)
37 "Checks if CH on its own would be considered whitespace by telegram."
40 (let ((gc (general-category ch))) 38 (let ((gc (general-category ch)))
41 (or (string= gc "Zs") ; Separator, space 39 (or (string= gc "Zs") ; Separator, space
42 (string= gc "Zl") ; Separator, line 40 (string= gc "Zl") ; Separator, line
@@ -45,39 +43,6 @@
45 (= (char-code ch) #x2800)))) ; BRAILLE PATTERN BLANK 43 (= (char-code ch) #x2800)))) ; BRAILLE PATTERN BLANK
46 44
47(defun is-tg-whitespace-str (str) 45(defun is-tg-whitespace-str (str)
46 "Checks if message containing just STR would be considered whitespace by telegram."
48 (iter (for ch in-string str) 47 (iter (for ch in-string str)
49 (always (is-tg-whitespace ch)))) 48 (always (is-tg-whitespace ch))))
50
51(defun lisp->camel-case (str)
52 (with-output-to-string (out)
53 (let ((should-caps nil))
54 (iter (for ch in-string str)
55 (cond ((char= ch #\-)
56 (setf should-caps t))
57 (should-caps
58 (write-char (char-upcase ch) out)
59 (setf should-caps nil))
60 (t
61 (write-char (char-downcase ch) out)))))))
62
63(defun lisp->snake-case (str)
64 (with-output-to-string (out)
65 (loop for ch across str do
66 (case ch
67 (#\- (write-char #\_ out))
68 (otherwise (write-char ch out))))))
69
70(defun snake->lisp-case (str)
71 (with-output-to-string (out)
72 (loop for ch across str do
73 (case ch
74 (#\_ (write-char #\- out))
75 (otherwise (write-char ch out))))))
76
77(defun starts-with (str prefix)
78 (and (> (length str) (length prefix))
79 (string= str prefix :end1 (length prefix))))
80
81(defun starts-with-ignore-case (str prefix)
82 (and (> (length str) (length prefix))
83 (string-equal str prefix :end1 (length prefix))))
diff --git a/src/tg/method-macros.lisp b/src/tg/method-macros.lisp
index b924e15..0be6f00 100644
--- a/src/tg/method-macros.lisp
+++ b/src/tg/method-macros.lisp
@@ -6,8 +6,8 @@
6 (:import-from :alexandria :with-gensyms) 6 (:import-from :alexandria :with-gensyms)
7 (:import-from :com.dieggsy.f-string :enable-f-strings) 7 (:import-from :com.dieggsy.f-string :enable-f-strings)
8 (:import-from :serapeum :take) 8 (:import-from :serapeum :take)
9 (:import-from :str)
9 (:import-from :ukkoclot/state :bot) 10 (:import-from :ukkoclot/state :bot)
10 (:import-from :ukkoclot/strings :ends-with :lisp->camel-case)
11 (:import-from :ukkoclot/transport :do-call) 11 (:import-from :ukkoclot/transport :do-call)
12 (:export :define-tg-method)) 12 (:export :define-tg-method))
13(in-package :ukkoclot/tg/method-macros) 13(in-package :ukkoclot/tg/method-macros)
@@ -36,8 +36,8 @@
36 (collect (apply #'make-param param-spec)))) 36 (collect (apply #'make-param param-spec))))
37 37
38 (defun path-from-name (name) 38 (defun path-from-name (name)
39 (let ((str (lisp->camel-case (symbol-name name)))) 39 (let ((str (str:camel-case name)))
40 (if (ends-with str "%") 40 (if (str:ends-with-p "%" str :ignore-case nil)
41 (take (- (length str) 1) str) 41 (take (- (length str) 1) str)
42 str))) 42 str)))
43 43
diff --git a/src/tg/type-macros.lisp b/src/tg/type-macros.lisp
index 5f99cba..75afab0 100644
--- a/src/tg/type-macros.lisp
+++ b/src/tg/type-macros.lisp
@@ -5,9 +5,9 @@
5 (:use :c2cl :iterate) 5 (:use :c2cl :iterate)
6 (:import-from :alexandria :with-gensyms) 6 (:import-from :alexandria :with-gensyms)
7 (:import-from :com.dieggsy.f-string :enable-f-strings) 7 (:import-from :com.dieggsy.f-string :enable-f-strings)
8 (:import-from :str)
8 (:import-from :ukkoclot/serializing :parse-value) 9 (:import-from :ukkoclot/serializing :parse-value)
9 (:import-from :ukkoclot/hash-tables :gethash-lazy) 10 (:import-from :ukkoclot/hash-tables :gethash-lazy)
10 (:import-from :ukkoclot/strings :lisp->snake-case)
11 (:local-nicknames 11 (:local-nicknames
12 (:jzon :com.inuoe.jzon)) 12 (:jzon :com.inuoe.jzon))
13 (:export :define-tg-type)) 13 (:export :define-tg-type))
@@ -39,7 +39,7 @@
39 (intern (concatenate 'string (symbol-name name) "-" (symbol-name (field-name field))))) 39 (intern (concatenate 'string (symbol-name name) "-" (symbol-name (field-name field)))))
40 40
41 (defun field-hash-key (field) 41 (defun field-hash-key (field)
42 (string-downcase (lisp->snake-case (symbol-name (field-name field))))) 42 (str:snake-case (field-name field)))
43 43
44 (defun field-keyword (field) 44 (defun field-keyword (field)
45 (intern (symbol-name (field-name field)) :keyword)) 45 (intern (symbol-name (field-name field)) :keyword))