summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ocicl.csv1
-rw-r--r--src/main.lisp60
-rw-r--r--src/transport.lisp38
3 files changed, 54 insertions, 45 deletions
diff --git a/ocicl.csv b/ocicl.csv
index 51113d8..3918f74 100644
--- a/ocicl.csv
+++ b/ocicl.csv
@@ -1,5 +1,4 @@
1alexandria, ghcr.io/ocicl/alexandria@sha256:e433c2e076ed3bcf8641b97b00192680db2201d305efac9293539dee88c7fbf7, alexandria-20240503-8514d8e/alexandria.asd 1alexandria, ghcr.io/ocicl/alexandria@sha256:e433c2e076ed3bcf8641b97b00192680db2201d305efac9293539dee88c7fbf7, alexandria-20240503-8514d8e/alexandria.asd
2anaphora, ghcr.io/ocicl/anaphora@sha256:55f1c61b7826c5451a60b4b4522e35e770504bbfa2036d8becbf21f6d654925a, anaphora-20240503-bcf0f74/anaphora.asd
3babel, ghcr.io/ocicl/babel@sha256:9d9fcde71acc2b5c39572de4f11756a08c1d8801caa86c581b85dabaa35928b3, babel-20250905-4eaf3f2/babel.asd 2babel, ghcr.io/ocicl/babel@sha256:9d9fcde71acc2b5c39572de4f11756a08c1d8801caa86c581b85dabaa35928b3, babel-20250905-4eaf3f2/babel.asd
4babel-streams, ghcr.io/ocicl/babel@sha256:9d9fcde71acc2b5c39572de4f11756a08c1d8801caa86c581b85dabaa35928b3, babel-20250905-4eaf3f2/babel-streams.asd 3babel-streams, ghcr.io/ocicl/babel@sha256:9d9fcde71acc2b5c39572de4f11756a08c1d8801caa86c581b85dabaa35928b3, babel-20250905-4eaf3f2/babel-streams.asd
5babel-tests, ghcr.io/ocicl/babel@sha256:9d9fcde71acc2b5c39572de4f11756a08c1d8801caa86c581b85dabaa35928b3, babel-20250905-4eaf3f2/babel-tests.asd 4babel-tests, ghcr.io/ocicl/babel@sha256:9d9fcde71acc2b5c39572de4f11756a08c1d8801caa86c581b85dabaa35928b3, babel-20250905-4eaf3f2/babel-tests.asd
diff --git a/src/main.lisp b/src/main.lisp
index cd9e755..94148a7 100644
--- a/src/main.lisp
+++ b/src/main.lisp
@@ -2,8 +2,8 @@
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/main 3(defpackage :ukkoclot/main
4 (:nicknames :ukkoclot) 4 (:nicknames :ukkoclot)
5 (:use :c2cl :ukkoclot/config :ukkoclot/inline-bots :ukkoclot/tg) 5 (:use :c2cl :iterate :ukkoclot/config :ukkoclot/inline-bots :ukkoclot/tg)
6 (:import-from :anaphora :acond :awhen :it) 6 (:import-from :alexandria :when-let)
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 :ukkoclot/db :with-db) 9 (:import-from :ukkoclot/db :with-db)
@@ -55,12 +55,12 @@
55 (loop for update across updates do 55 (loop for update across updates do
56 (unwind-protect 56 (unwind-protect
57 (progn 57 (progn
58 (awhen (update-message update) 58 (when-let (msg (update-message update))
59 (reporty (it) 59 (reporty (msg)
60 (on-message bot it))) 60 (on-message bot msg)))
61 (awhen (update-callback-query update) 61 (when-let (cbq (update-callback-query update))
62 (reporty (it) 62 (reporty (cbq)
63 (on-callback-query bot it)))) 63 (on-callback-query bot cbq))))
64 (setf gup-offset (1+ (update-update-id update))))))) 64 (setf gup-offset (1+ (update-update-id update)))))))
65 ;; One last getUpdates to make sure offset is stored on server 65 ;; One last getUpdates to make sure offset is stored on server
66 (get-updates bot :timeout 0 :limit 1 :offset gup-offset)) 66 (get-updates bot :timeout 0 :limit 1 :offset gup-offset))
@@ -74,10 +74,10 @@
74 (config-owner (bot-config bot)))) 74 (config-owner (bot-config bot))))
75 (let ((bot-id (read-from-string data t nil :start 4))) 75 (let ((bot-id (read-from-string data t nil :start 4)))
76 (blacklist-inline-bot bot bot-id)) 76 (blacklist-inline-bot bot bot-id))
77 (awhen (callback-query-message cb) 77 (when-let (msg (callback-query-message cb))
78 (delete-message bot 78 (delete-message bot
79 :chat-id (message-chat-id it) 79 :chat-id (message-chat-id msg)
80 :message-id (message-id it))) 80 :message-id (message-id msg)))
81 (answer-callback-query bot 81 (answer-callback-query bot
82 :callback-query-id (callback-query-id cb) 82 :callback-query-id (callback-query-id cb)
83 :text "OK")) 83 :text "OK"))
@@ -87,10 +87,10 @@
87 (config-owner (bot-config bot)))) 87 (config-owner (bot-config bot))))
88 (let ((bot-id (read-from-string data t nil :start 4))) 88 (let ((bot-id (read-from-string data t nil :start 4)))
89 (whitelist-inline-bot bot bot-id)) 89 (whitelist-inline-bot bot bot-id))
90 (awhen (callback-query-message cb) 90 (when-let (msg (callback-query-message cb))
91 (delete-message bot 91 (delete-message bot
92 :chat-id (message-chat-id it) 92 :chat-id (message-chat-id msg)
93 :message-id (message-id it))) 93 :message-id (message-id msg)))
94 (answer-callback-query bot 94 (answer-callback-query bot
95 :callback-query-id (callback-query-id cb) 95 :callback-query-id (callback-query-id cb)
96 :text "OK")) 96 :text "OK"))
@@ -104,15 +104,16 @@
104 104
105(defun on-message (bot msg) 105(defun on-message (bot msg)
106 (block nil 106 (block nil
107 (awhen (message-via-bot msg) 107 (when-let (inline-bot (message-via-bot msg))
108 (unless (on-inline-bot bot msg it) 108 (unless (on-inline-bot bot msg inline-bot)
109 (return))) 109 (return)))
110 110
111 (awhen (message-text msg) 111 (when-let (text (message-text msg))
112 (on-text-message bot msg it)) 112 (on-text-message bot msg text))
113 113
114 (awhen (message-new-chat-members msg) 114 (when-let (new-chat-members (message-new-chat-members msg))
115 (loop for new-chat-member across it do 115 (iter
116 (for new-chat-member in-vector new-chat-members)
116 (on-new-member bot msg new-chat-member))))) 117 (on-new-member bot msg new-chat-member)))))
117 118
118(defun on-new-member (bot msg new-member) 119(defun on-new-member (bot msg new-member)
@@ -145,11 +146,12 @@
145 ;; warn gets removed after a month of no warns 146 ;; warn gets removed after a month of no warns
146 (return)) 147 (return))
147 148
148 (awhen (message-entities msg) 149 (when-let (entities (message-entities msg))
149 (loop for entity across it 150 (iter
150 when (and (equal (message-entity-type entity) bot-command) 151 (for entity in-vector entities)
151 (= (message-entity-offset entity) 0)) 152 (when (and (eql (message-entity-type entity) bot-command)
152 do (on-text-command bot msg text (message-entity-extract entity text)))) 153 (zerop (message-entity-offset entity)))
154 (on-text-command bot msg text (message-entity-extract entity text)))))
153 155
154 ;; TODO: Replace this cond with a nicer dispatch. Something like string-case? 156 ;; TODO: Replace this cond with a nicer dispatch. Something like string-case?
155 (cond ((equal text ":3") 157 (cond ((equal text ":3")
@@ -241,15 +243,15 @@
241 (let ((simple-cmd (simplify-cmd bot cmd))) 243 (let ((simple-cmd (simplify-cmd bot cmd)))
242 (log:debug "text-command: ~A AKA ~A" cmd simple-cmd) 244 (log:debug "text-command: ~A AKA ~A" cmd simple-cmd)
243 ;; TODO: Replace this cond with a nicer dispatch. Something like string-case? 245 ;; TODO: Replace this cond with a nicer dispatch. Something like string-case?
244 (acond 246 (cond
245 ((equal simple-cmd "chatid") 247 ((equal simple-cmd "chatid")
246 (reply-message bot msg 248 (reply-message bot msg
247 #f"<code>{(message-chat-id msg)}</code>" 249 #f"<code>{(message-chat-id msg)}</code>"
248 :parse-mode html)) 250 :parse-mode html))
249 251
250 ((and (equal simple-cmd "msginfo") 252 ((equal simple-cmd "msginfo")
251 (message-reply-to-message msg)) 253 (when-let (replied (message-reply-to-message msg))
252 (reply-message bot it (let ((*print-pretty* t)) (fixup-value it)))) 254 (reply-message bot replied (let ((*print-pretty* t)) (fixup-value replied)))))
253 255
254 ((equal simple-cmd "ping") 256 ((equal simple-cmd "ping")
255 (let* ((start-time (get-internal-real-time)) 257 (let* ((start-time (get-internal-real-time))
diff --git a/src/transport.lisp b/src/transport.lisp
index 941341a..d47db4d 100644
--- a/src/transport.lisp
+++ b/src/transport.lisp
@@ -1,8 +1,8 @@
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/transport 3(defpackage :ukkoclot/transport
4 (:documentation "Package dealing with HTTP calls.")
4 (:use :c2cl) 5 (:use :c2cl)
5 (:import-from :anaphora :aand :acond :it)
6 (:import-from :cl+ssl) 6 (:import-from :cl+ssl)
7 (:import-from :dex) 7 (:import-from :dex)
8 (:import-from :log) 8 (:import-from :log)
@@ -14,6 +14,7 @@
14(in-package :ukkoclot/transport) 14(in-package :ukkoclot/transport)
15 15
16(defun req (uri method content) 16(defun req (uri method content)
17 "Wrapper function for making a request."
17 (let ((retrier (dex:retry-request 5 :interval 1)) 18 (let ((retrier (dex:retry-request 5 :interval 1))
18 ;; This is needed to avoid hangs, 19 ;; This is needed to avoid hangs,
19 ;; see https://github.com/fukamachi/dexador/issues/91#issuecomment-1093472364 20 ;; see https://github.com/fukamachi/dexador/issues/91#issuecomment-1093472364
@@ -25,22 +26,29 @@
25 (cl+ssl::ssl-error (e) (funcall retrier e))))) 26 (cl+ssl::ssl-error (e) (funcall retrier e)))))
26 27
27(defun do-call% (method uri out-type args-encoded) 28(defun do-call% (method uri out-type args-encoded)
28 (let ((body (req uri method args-encoded))) 29 "Internal function with the arguments already encoded.
29 (let ((hash (jzon:parse body))) 30
30 (acond 31See `do-call'."
31 ((gethash "ok" hash) (parse-value out-type (gethash "result" hash))) 32 (let* ((body (req uri method args-encoded))
32 ((aand (gethash "parameters" hash) 33 (hash (jzon:parse body)))
33 (gethash "retry_after" it)) 34 (if (gethash "ok" hash)
34 (log:info "Should sleep for ~A seconds" it) 35 (parse-value out-type (gethash "result" hash))
35 (sleep it) 36 (let* ((error-code (gethash "error_code" hash))
36 (log:info "Good morning!") 37 (description (gethash "description" hash))
37 (do-call% method uri out-type args-encoded)) 38 (parameters (gethash "parameters" hash))
38 (t (error "TG error ~A: ~A ~:A" 39 (retry-after (when parameters (gethash "retry_after" parameters))))
39 (gethash "error_code" hash) 40 (cond
40 (gethash "description" hash) 41 (retry-after
41 (gethash "parameters" hash))))))) 42 (log:info "Should sleep for ~A seconds" retry-after)
43 (sleep retry-after)
44 (log:info "Good morning!")
45 (do-call% method uri out-type args-encoded))
46 (t
47 (error "TG error ~A: ~A ~:A"
48 error-code description parameters)))))))
42 49
43(defun do-call (bot method path out-type args) 50(defun do-call (bot method path out-type args)
51 "Perform a HTTP call."
44 (let ((uri (concatenate 'string (bot-base-uri bot) path)) 52 (let ((uri (concatenate 'string (bot-base-uri bot) path))
45 (args-encoded (fixup-args args))) 53 (args-encoded (fixup-args args)))
46 (log:debug "~A .../~A ~S" method path args-encoded) 54 (log:debug "~A .../~A ~S" method path args-encoded)