summaryrefslogtreecommitdiff
path: root/src/tg
diff options
context:
space:
mode:
Diffstat (limited to 'src/tg')
-rw-r--r--src/tg/animation.lisp30
-rw-r--r--src/tg/bot-name.lisp14
-rw-r--r--src/tg/business-bot-rights.lisp40
-rw-r--r--src/tg/business-connection.lisp28
-rw-r--r--src/tg/callback-query.lisp29
-rw-r--r--src/tg/chat-administrator-rights.lisp44
-rw-r--r--src/tg/chat-type.lisp12
-rw-r--r--src/tg/chat.lisp28
-rw-r--r--src/tg/force-reply.lisp18
-rw-r--r--src/tg/inline-keyboard-button.lisp30
-rw-r--r--src/tg/inline-keyboard-markup.lisp14
-rw-r--r--src/tg/keyboard-button-poll-type.lisp14
-rw-r--r--src/tg/keyboard-button-request-chat.lisp32
-rw-r--r--src/tg/keyboard-button-request-users.lisp24
-rw-r--r--src/tg/keyboard-button.lisp32
-rw-r--r--src/tg/link-preview-options.lisp22
-rw-r--r--src/tg/macros.lisp142
-rw-r--r--src/tg/message-entity-type.lisp47
-rw-r--r--src/tg/message-entity.lisp59
-rw-r--r--src/tg/message-reaction-updated.lisp31
-rw-r--r--src/tg/message.lisp172
-rw-r--r--src/tg/parse-mode.lisp11
-rw-r--r--src/tg/photo-size.lisp22
-rw-r--r--src/tg/reaction-type-custom-emoji.lisp20
-rw-r--r--src/tg/reaction-type-emoji.lisp20
-rw-r--r--src/tg/reaction-type-paid.lisp18
-rw-r--r--src/tg/reaction-type.lisp14
-rw-r--r--src/tg/reply-keyboard-markup.lisp24
-rw-r--r--src/tg/reply-keyboard-remove.lisp16
-rw-r--r--src/tg/reply-parameters.lisp29
-rw-r--r--src/tg/suggested-post-parameters.lisp16
-rw-r--r--src/tg/suggested-post-price.lisp16
-rw-r--r--src/tg/update.lisp52
-rw-r--r--src/tg/user.lisp59
-rw-r--r--src/tg/web-app-info.lisp14
35 files changed, 1193 insertions, 0 deletions
diff --git a/src/tg/animation.lisp b/src/tg/animation.lisp
new file mode 100644
index 0000000..d17db94
--- /dev/null
+++ b/src/tg/animation.lisp
@@ -0,0 +1,30 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/animation
4 (:use :c2cl :ukkoclot/tg/macros :ukkoclot/tg/photo-size)
5 (:export
6 #:animation
7 #:make-animation
8 #:animation-p
9 #:copy-animation
10 #:animation-file-id
11 #:animation-file-unique-id
12 #:animation-width
13 #:animation-height
14 #:animation-duration
15 #:animation-thumbnail
16 #:animation-file-name
17 #:animation-mime-type
18 #:animation-file-size))
19(in-package :ukkoclot/tg/animation)
20
21(define-tg-type animation
22 (file-id string)
23 (file-unique-id string)
24 (width integer)
25 (height integer)
26 (duration integer)
27 (thumbnail (or photo-size null) nil)
28 (file-name (or string null) nil)
29 (mime-type (or string null) nil)
30 (file-size (or integer null) nil))
diff --git a/src/tg/bot-name.lisp b/src/tg/bot-name.lisp
new file mode 100644
index 0000000..933ce8c
--- /dev/null
+++ b/src/tg/bot-name.lisp
@@ -0,0 +1,14 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/bot-name
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:bot-name
7 #:make-bot-name
8 #:bot-name-p
9 #:copy-bot-name
10 #:bot-name-name))
11(in-package :ukkoclot/tg/bot-name)
12
13(define-tg-type bot-name
14 (name string))
diff --git a/src/tg/business-bot-rights.lisp b/src/tg/business-bot-rights.lisp
new file mode 100644
index 0000000..f5a44c0
--- /dev/null
+++ b/src/tg/business-bot-rights.lisp
@@ -0,0 +1,40 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/business-bot-rights
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:business-bot-rights
7 #:make-business-bot-rights
8 #:business-bot-rights-p
9 #:copy-business-bot-rights
10 #:business-bot-rights-can-reply
11 #:business-bot-rights-can-read-messages
12 #:business-bot-rights-can-delete-sent-messages
13 #:business-bot-rights-can-delete-all-messages
14 #:business-bot-rights-can-edit-name
15 #:business-bot-rights-can-edit-bio
16 #:business-bot-rights-can-edit-profile-photo
17 #:business-bot-rights-can-edit-username
18 #:business-bot-rights-can-change-gift-settings
19 #:business-bot-rights-can-view-gifts-and-stars
20 #:business-bot-rights-can-convert-gifts-to-stars
21 #:business-bot-rights-can-transfer-and-upgrade-gifts
22 #:business-bot-rights-can-transfer-stars
23 #:business-bot-rights-can-manage-stories))
24(in-package :ukkoclot/tg/business-bot-rights)
25
26(define-tg-type business-bot-rights
27 (can-reply boolean nil)
28 (can-read-messages boolean nil)
29 (can-delete-sent-messages boolean nil)
30 (can-delete-all-messages boolean nil)
31 (can-edit-name boolean nil)
32 (can-edit-bio boolean nil)
33 (can-edit-profile-photo boolean nil)
34 (can-edit-username boolean nil)
35 (can-change-gift-settings boolean nil)
36 (can-view-gifts-and-stars boolean nil)
37 (can-convert-gifts-to-stars boolean nil)
38 (can-transfer-and-upgrade-gifts boolean nil)
39 (can-transfer-stars boolean nil)
40 (can-manage-stories boolean nil))
diff --git a/src/tg/business-connection.lisp b/src/tg/business-connection.lisp
new file mode 100644
index 0000000..74f6c9e
--- /dev/null
+++ b/src/tg/business-connection.lisp
@@ -0,0 +1,28 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/business-connection
4 (:use
5 :c2cl
6 :ukkoclot/tg/macros
7 :ukkoclot/tg/business-bot-rights
8 :ukkoclot/tg/user)
9 (:export
10 #:business-connection
11 #:make-business-connection
12 #:business-connection-p
13 #:copy-business-connection
14 #:business-connection-id
15 #:business-connection-user
16 #:business-connection-user-chat-id
17 #:business-connection-date
18 #:business-connection-rights
19 #:business-connection-is-enabled))
20(in-package :ukkoclot/tg/business-connection)
21
22(define-tg-type business-connection
23 (id string)
24 (user user)
25 (user-chat-id integer)
26 (date integer)
27 (rights (or business-bot-rights null) nil)
28 (is-enabled boolean))
diff --git a/src/tg/callback-query.lisp b/src/tg/callback-query.lisp
new file mode 100644
index 0000000..6b89755
--- /dev/null
+++ b/src/tg/callback-query.lisp
@@ -0,0 +1,29 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/callback-query
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:use
6 :ukkoclot/tg/message
7 :ukkoclot/tg/user)
8 (:export
9 #:callback-query
10 #:make-callback-query
11 #:callback-query-p
12 #:copy-callback-query
13 #:callback-query-id
14 #:callback-query-from
15 #:callback-query-message
16 #:callback-query-inline-message-id
17 #:callback-query-chat-instance
18 #:callback-query-data
19 #:callback-query-game-short-name))
20(in-package :ukkoclot/tg/callback-query)
21
22(define-tg-type callback-query
23 (id string)
24 (from user)
25 (message (or message null) nil)
26 (inline-message-id (or string null) nil)
27 (chat-instance string)
28 (data (or string null) nil)
29 (game-short-name (or string null) nil))
diff --git a/src/tg/chat-administrator-rights.lisp b/src/tg/chat-administrator-rights.lisp
new file mode 100644
index 0000000..2c37757
--- /dev/null
+++ b/src/tg/chat-administrator-rights.lisp
@@ -0,0 +1,44 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/chat-administrator-rights
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:chat-administrator-rights
7 #:make-chat-administrator-rights
8 #:chat-administrator-rights-p
9 #:copy-chat-administrator-rights
10 #:chat-administrator-rights-is-anonymous
11 #:chat-administrator-rights-can-manage-chat
12 #:chat-administrator-rights-can-delete-messages
13 #:chat-administrator-rights-can-manage-video-chats
14 #:chat-administrator-rights-can-restrict-members
15 #:chat-administrator-rights-can-promote-members
16 #:chat-administrator-rights-can-change-info
17 #:chat-administrator-rights-can-invite-users
18 #:chat-administrator-rights-can-post-stories
19 #:chat-administrator-rights-can-edit-stories
20 #:chat-administrator-rights-can-delete-stories
21 #:chat-administrator-rights-can-post-messages
22 #:chat-administrator-rights-can-edit-messages
23 #:chat-administrator-rights-can-pin-messages
24 #:chat-administrator-rights-can-manage-topics
25 #:chat-administrator-rights-can-manage-direct-messages))
26(in-package :ukkoclot/tg/chat-administrator-rights)
27
28(define-tg-type chat-administrator-rights
29 (is-anonymous boolean)
30 (can-manage-chat boolean)
31 (can-delete-messages boolean)
32 (can-manage-video-chats boolean)
33 (can-restrict-members boolean)
34 (can-promote-members boolean)
35 (can-change-info boolean)
36 (can-invite-users boolean)
37 (can-post-stories boolean)
38 (can-edit-stories boolean)
39 (can-delete-stories boolean)
40 (can-post-messages boolean nil)
41 (can-edit-messages boolean nil)
42 (can-pin-messages boolean nil)
43 (can-manage-topics boolean nil)
44 (can-manage-direct-messages boolean nil))
diff --git a/src/tg/chat-type.lisp b/src/tg/chat-type.lisp
new file mode 100644
index 0000000..daf135a
--- /dev/null
+++ b/src/tg/chat-type.lisp
@@ -0,0 +1,12 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/chat-type
4 (:use :c2cl :ukkoclot/enum)
5 (:export :channel :chat-type :group :private :supergroup))
6(in-package :ukkoclot/tg/chat-type)
7
8(define-enum chat-type
9 (private "private")
10 (group "group")
11 (supergroup "supergroup")
12 (channel "channel"))
diff --git a/src/tg/chat.lisp b/src/tg/chat.lisp
new file mode 100644
index 0000000..1fa3f7e
--- /dev/null
+++ b/src/tg/chat.lisp
@@ -0,0 +1,28 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/chat
4 (:use :c2cl :ukkoclot/tg/chat-type :ukkoclot/tg/macros)
5 (:export
6 #:chat
7 #:make-chat
8 #:chat-p
9 #:copy-chat
10 #:chat-id
11 #:chat-type
12 #:chat-title
13 #:chat-username
14 #:chat-first-name
15 #:chat-last-name
16 #:chat-is-forum
17 #:chat-is-direct-messages))
18(in-package :ukkoclot/tg/chat)
19
20(define-tg-type chat
21 (id integer)
22 (type chat-type)
23 (title (or string null) nil)
24 (username (or string null) nil)
25 (first-name (or string null) nil)
26 (last-name (or string null) nil)
27 (is-forum boolean nil)
28 (is-direct-messages boolean nil))
diff --git a/src/tg/force-reply.lisp b/src/tg/force-reply.lisp
new file mode 100644
index 0000000..816eb75
--- /dev/null
+++ b/src/tg/force-reply.lisp
@@ -0,0 +1,18 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/force-reply
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:force-reply
7 #:make-force-reply
8 #:force-reply-p
9 #:copy-force-reply
10 #:force-reply-force-reply
11 #:force-reply-input-field-placeholder
12 #:force-reply-selective))
13(in-package :ukkoclot/tg/force-reply)
14
15(define-tg-type force-reply
16 (force-reply boolean t :skip-if-default nil)
17 (input-field-placeholder (or string null) nil)
18 (selective boolean nil))
diff --git a/src/tg/inline-keyboard-button.lisp b/src/tg/inline-keyboard-button.lisp
new file mode 100644
index 0000000..e403f2a
--- /dev/null
+++ b/src/tg/inline-keyboard-button.lisp
@@ -0,0 +1,30 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/inline-keyboard-button
4 (:use :c2cl :ukkoclot/tg/macros :ukkoclot/tg/web-app-info)
5 (:export
6 #:inline-keyboard-button
7 #:make-inline-keyboard-button
8 #:inline-keyboard-button-p
9 #:copy-inline-keyboard-button
10 #:inline-keyboard-button-text
11 #:inline-keyboard-button-url
12 #:inline-keyboard-button-callback-data
13 #:inline-keyboard-button-web-app
14 #:inline-keyboard-button-switch-inline-query
15 #:inline-keyboard-button-switch-inline-query-current-chat
16 #:inline-keyboard-button-pay))
17(in-package :ukkoclot/tg/inline-keyboard-button)
18
19(define-tg-type inline-keyboard-button
20 (text string)
21 (url (or string null) nil)
22 (callback-data string)
23 (web-app (or web-app-info null) nil)
24 ;; TODO: (login-url (or login-url null) nil)
25 (switch-inline-query (or string null) nil)
26 (switch-inline-query-current-chat (or string null) nil)
27 ;; TODO: (switch-inline-query-chosen-chat (or switch-inline-query-chosen-chat null) nil)
28 ;; TODO: (copy-text (or copy-text-button null) nil)
29 ;; TODO: (callback-game (or callback-game null) nil)
30 (pay boolean nil))
diff --git a/src/tg/inline-keyboard-markup.lisp b/src/tg/inline-keyboard-markup.lisp
new file mode 100644
index 0000000..023b87f
--- /dev/null
+++ b/src/tg/inline-keyboard-markup.lisp
@@ -0,0 +1,14 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/inline-keyboard-markup
4 (:use :c2cl :ukkoclot/tg/inline-keyboard-button :ukkoclot/tg/macros)
5 (:export
6 #:inline-keyboard-markup
7 #:make-inline-keyboard-markup
8 #:inline-keyboard-markup-p
9 #:copy-inline-keyboard-markup
10 #:inline-keyboard-markup-inline-keyboard))
11(in-package :ukkoclot/tg/inline-keyboard-markup)
12
13(define-tg-type inline-keyboard-markup
14 (inline-keyboard (array (array inline-keyboard-button))))
diff --git a/src/tg/keyboard-button-poll-type.lisp b/src/tg/keyboard-button-poll-type.lisp
new file mode 100644
index 0000000..7b5b063
--- /dev/null
+++ b/src/tg/keyboard-button-poll-type.lisp
@@ -0,0 +1,14 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/keyboard-button-poll-type
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:keyboard-button-poll-type
7 #:make-keyboard-button-poll-type
8 #:keyboard-button-poll-type-p
9 #:copy-keyboard-button-poll-type
10 #:keyboard-button-poll-type-type))
11(in-package :ukkoclot/tg/keyboard-button-poll-type)
12
13(define-tg-type keyboard-button-poll-type
14 (type (or string null) nil)) ;(member "quiz" "regular") or null
diff --git a/src/tg/keyboard-button-request-chat.lisp b/src/tg/keyboard-button-request-chat.lisp
new file mode 100644
index 0000000..07f0d27
--- /dev/null
+++ b/src/tg/keyboard-button-request-chat.lisp
@@ -0,0 +1,32 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/keyboard-button-request-chat
4 (:use :c2cl :ukkoclot/tg/chat-administrator-rights :ukkoclot/tg/macros)
5 (:export
6 #:keyboard-button-request-chat
7 #:make-keyboard-button-request-chat
8 #:keyboard-button-request-chat-p
9 #:copy-keyboard-button-request-chat
10 #:keyboard-button-request-chat-request-id
11 #:keyboard-button-request-chat-chat-is-channel
12 #:keyboard-button-request-chat-chat-is-created
13 #:keyboard-button-request-chat-user-administrator-rights
14 #:keyboard-button-request-chat-bot-administrator-rights
15 #:keyboard-button-request-chat-bot-is-member
16 #:keyboard-button-request-chat-request-title
17 #:keyboard-button-request-chat-request-username
18 #:keyboard-button-request-chat-request-photo))
19(in-package :ukkoclot/tg/keyboard-button-request-chat)
20
21(define-tg-type keyboard-button-request-chat
22 (request-id integer)
23 (chat-is-channel boolean)
24 ;; TODO: (chat-is-forum ternary nil)
25 ;; TODO: (chat-has-username ternary nil)
26 (chat-is-created boolean nil)
27 (user-administrator-rights (or chat-administrator-rights null) nil)
28 (bot-administrator-rights (or chat-administrator-rights null) nil)
29 (bot-is-member boolean nil)
30 (request-title boolean nil)
31 (request-username boolean nil)
32 (request-photo boolean nil))
diff --git a/src/tg/keyboard-button-request-users.lisp b/src/tg/keyboard-button-request-users.lisp
new file mode 100644
index 0000000..82b9151
--- /dev/null
+++ b/src/tg/keyboard-button-request-users.lisp
@@ -0,0 +1,24 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/keyboard-button-request-users
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:keyboard-button-request-users
7 #:make-keyboard-button-request-users
8 #:keyboard-button-request-users-p
9 #:copy-keyboard-button-request-users
10 #:keyboard-button-request-users-request-id
11 #:keyboard-button-request-users-max-quantity
12 #:keyboard-button-request-users-request-name
13 #:keyboard-button-request-users-request-username
14 #:keyboard-button-request-users-request-photo))
15(in-package :ukkoclot/tg/keyboard-button-request-users)
16
17(define-tg-type keyboard-button-request-users
18 (request-id integer)
19 ;; TODO: (user-is-bot ternary nil)
20 ;; TODO: (user-is-premium ternary nil)
21 (max-quantity integer 1)
22 (request-name boolean nil)
23 (request-username boolean nil)
24 (request-photo boolean nil))
diff --git a/src/tg/keyboard-button.lisp b/src/tg/keyboard-button.lisp
new file mode 100644
index 0000000..79c87d6
--- /dev/null
+++ b/src/tg/keyboard-button.lisp
@@ -0,0 +1,32 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/keyboard-button
4 (:use
5 :c2cl
6 :ukkoclot/tg/keyboard-button-poll-type
7 :ukkoclot/tg/keyboard-button-request-chat
8 :ukkoclot/tg/keyboard-button-request-users
9 :ukkoclot/tg/macros
10 :ukkoclot/tg/web-app-info)
11 (:export
12 #:keyboard-button
13 #:make-keyboard-button
14 #:keyboard-button-p
15 #:copy-keyboard-button
16 #:keyboard-button-text
17 #:keyboard-button-request-users
18 #:keyboard-button-request-chat
19 #:keyboard-button-request-contact
20 #:keyboard-button-request-location
21 #:keyboard-button-request-poll
22 #:keyboard-button-web-app))
23(in-package :ukkoclot/tg/keyboard-button)
24
25(define-tg-type keyboard-button
26 (text string)
27 (request-users (or keyboard-button-request-users null) nil)
28 (request-chat (or keyboard-button-request-chat null) nil)
29 (request-contact boolean nil)
30 (request-location boolean nil)
31 (request-poll (or keyboard-button-poll-type null) nil)
32 (web-app (or web-app-info null) nil))
diff --git a/src/tg/link-preview-options.lisp b/src/tg/link-preview-options.lisp
new file mode 100644
index 0000000..7ed4859
--- /dev/null
+++ b/src/tg/link-preview-options.lisp
@@ -0,0 +1,22 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/link-preview-options
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:link-preview-options
7 #:make-link-preview-options
8 #:link-preview-options-p
9 #:copy-link-preview-options
10 #:link-preview-options-is-disabled
11 #:link-preview-options-url
12 #:link-preview-options-prefer-small-media
13 #:link-preview-options-prefer-large-media
14 #:link-preview-options-show-above-text))
15(in-package :ukkoclot/tg/link-preview-options)
16
17(define-tg-type link-preview-options
18 (is-disabled boolean nil)
19 (url (or string null) nil)
20 (prefer-small-media boolean nil)
21 (prefer-large-media boolean nil)
22 (show-above-text boolean nil))
diff --git a/src/tg/macros.lisp b/src/tg/macros.lisp
new file mode 100644
index 0000000..92afd6e
--- /dev/null
+++ b/src/tg/macros.lisp
@@ -0,0 +1,142 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/macros
4 (:use :c2cl)
5 (:import-from :ukkoclot/bot/impl :bot :do-call :parse-value)
6 (:import-from :ukkoclot/hash-tables :gethash-lazy)
7 (:import-from :ukkoclot/strings :lisp->snake-case)
8 (:local-nicknames
9 (:jzon :com.inuoe.jzon))
10 (:export :define-tg-method :define-tg-type))
11(in-package :ukkoclot/tg/macros)
12
13(eval-when (:compile-toplevel :load-toplevel :execute)
14 (defstruct (field (:constructor make-field%)) name type default skip-if-default)
15
16 (defparameter +unique+ (gensym))
17
18 (defun make-field (name type &optional (default +unique+) &key (skip-if-default (not (eq default +unique+))))
19 (let ((default (if (eq default +unique+)
20 (list 'error (format nil "No value given for ~A" name))
21 default)))
22 (make-field% :name name
23 :type type
24 :default default
25 :skip-if-default skip-if-default)))
26
27 (defun parse-field-specs (field-specs)
28 (loop for field-spec in field-specs
29 collect (apply #'make-field field-spec)))
30
31 (defun field-hash-key (field)
32 (string-downcase (lisp->snake-case (symbol-name (field-name field)))))
33
34 (defun field-accessor (struc-name field)
35 (intern (concatenate 'string (symbol-name struc-name) "-" (symbol-name (field-name field)))))
36
37 (defun field->coerced-field-spec (field struc-name obj-name)
38 `(list ,(string-downcase (lisp->snake-case (symbol-name (field-name field))))
39 (,(field-accessor struc-name field) ,obj-name)
40 ',(field-type field)))
41
42 (defun field->defun-spec (field)
43 (list (field-name field) (field-default field)))
44
45 (defun field->format-arg (field name struc)
46 `(',(field-name field) (,(field-accessor name field) ,struc)))
47
48 (defun field->ftype-spec (field)
49 (list (intern (symbol-name (field-name field)) :keyword) (field-type field)))
50
51 (defun field->gethash-spec (field hash-table-sym)
52 (let ((hash-key (field-hash-key field)))
53 (list 'gethash-lazy hash-key hash-table-sym (field-default field))))
54
55 (defun field->sethash-spec (field name struc hash-table-sym)
56 (let ((hash-key (field-hash-key field))
57 (skip-if-default (field-skip-if-default field))
58 (default (field-default field)))
59 (if skip-if-default
60 (let ((tmpsym (gensym "TMP")))
61 `(let ((,tmpsym (,(field-accessor name field) ,struc)))
62 (unless (equal ,tmpsym ,default)
63 (setf (gethash ,hash-key ,hash-table-sym) ,tmpsym))))
64 `(setf (gethash ,hash-key ,hash-table-sym) (,(field-accessor name field) ,struc)))))
65
66 (defun field->let-gethash-spec (field hash-table-sym)
67 `(,(field-name field)
68 (parse-value ',(field-type field) ,(field->gethash-spec field hash-table-sym))))
69
70 (defun field->make-spec (field)
71 (list (intern (symbol-name (field-name field)) :keyword)
72 (field-name field)))
73
74 (defun field->struct-spec (field)
75 (list (field-name field) (field-default field) :type (field-type field))))
76
77;; TODO: Automatically derive path from name
78;; TODO: Automatically derive mapfn from type
79(defmacro define-tg-method (
80 (name type path &optional (method :POST))
81 &body field-specs)
82 (let* ((fields (parse-field-specs field-specs))
83 (revfields (reverse fields))
84 (args (gensym "ARGS"))
85 (bot (gensym "BOT-")))
86 `(progn
87 (declaim (ftype (function (bot &key ,@(loop for field in fields
88 collect (field->ftype-spec field)))
89 ,type)
90 ,name))
91 (defun ,name (,bot &key ,@(loop for field in fields collect (field->defun-spec field)))
92 (let (,args)
93 ,@(loop for field in revfields
94 collecting
95 (if (field-skip-if-default field)
96 `(unless (equal ,(field-name field) ,(field-default field))
97 (setf ,args (acons ',(field-name field) ,(field-name field) ,args)))
98 `(setf ,args (acons ',(field-name field) ,(field-name field) ,args))))
99 (do-call ,bot ,method ,path ',type ,args))))))
100
101(defmacro define-tg-type (name &body field-specs)
102 (let* ((fields (parse-field-specs field-specs))
103 (revfields (reverse fields))
104 (make-name (intern (concatenate 'string "MAKE-" (symbol-name name))))
105 (printer (gensym (concatenate 'string "PRINT-" (symbol-name name))))
106 (hash (gensym "HASH-"))
107 (struc (gensym (symbol-name name)))
108 (stream (gensym "STREAM"))
109 (depth (gensym "DEPTH"))
110 (pprint-args (gensym "PPRINT-ARGS"))
111 (res (gensym "RES"))
112 (type (gensym "TYPE")))
113 `(progn
114 (defstruct (,name (:print-function ,printer))
115 ,@(loop for field in fields
116 collect (field->struct-spec field)))
117 (defun ,printer (,struc ,stream ,depth)
118 (declare (ignore ,depth))
119 (let (,pprint-args)
120 ,@(loop for field in revfields
121 collecting
122 (if (field-skip-if-default field)
123 `(let ((value (,(field-accessor name field) ,struc)))
124 (unless (equal value ,(field-default field))
125 (setf ,pprint-args (list* ',(field-name field) value ,pprint-args))))
126 `(setf ,pprint-args (list* ',(field-name field) (,(field-accessor name field) ,struc) ,pprint-args))))
127 (format ,stream "~A~<[~;~@{~_~1I~W = ~W~^, ~}~;]~:>" ',name ,pprint-args)))
128 (defmethod parse-value ((,type (eql ',name)) ,hash)
129 (let ,(loop for field in fields
130 collect (field->let-gethash-spec field hash))
131 (,make-name ,@(loop for field in fields
132 append (field->make-spec field)))))
133 (defmethod jzon:coerced-fields ((,struc ,name))
134 (let (,res)
135 ,@(loop for field in revfields
136 collecting
137 (if (field-skip-if-default field)
138 `(let ((value (,(field-accessor name field) ,struc)))
139 (unless (equal value ,(field-default field))
140 (setf ,res (cons ,(field->coerced-field-spec field name struc) ,res))))
141 `(setf ,res (cons ,(field->coerced-field-spec field name struc) ,res))))
142 ,res)))))
diff --git a/src/tg/message-entity-type.lisp b/src/tg/message-entity-type.lisp
new file mode 100644
index 0000000..f904509
--- /dev/null
+++ b/src/tg/message-entity-type.lisp
@@ -0,0 +1,47 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/message-entity-type
4 (:use :c2cl :ukkoclot/enum)
5 (:export
6 :message-entity-type
7 :mention
8 :hashtag
9 :cashtag
10 :bot-command
11 :url-entity
12 :email
13 :phone-number
14 :bold
15 :italic
16 :underline
17 :strikethrough
18 :spoiler
19 :blockquote
20 :expandable-blockquote
21 :code
22 :pre
23 :text-link
24 :text-mention
25 :custom-emoji))
26(in-package :ukkoclot/tg/message-entity-type)
27
28(define-enum message-entity-type
29 (mention "mention")
30 (hashtag "hashtag")
31 (cashtag "cashtag")
32 (bot-command "bot_command")
33 (url-entity "url")
34 (email "email")
35 (phone-number "phone_number")
36 (bold "bold")
37 (italic "italic")
38 (underline "underline")
39 (strikethrough "strikethrough")
40 (spoiler "spoiler")
41 (blockquote "blockquote")
42 (expandable-blockquote "expandable_blockquote")
43 (code "code")
44 (pre "pre")
45 (text-link "text_link")
46 (text-mention "text_mention")
47 (custom-emoji "custom_emoji"))
diff --git a/src/tg/message-entity.lisp b/src/tg/message-entity.lisp
new file mode 100644
index 0000000..c5be269
--- /dev/null
+++ b/src/tg/message-entity.lisp
@@ -0,0 +1,59 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/message-entity
4 (:use :c2cl :iterate :ukkoclot/tg/macros :ukkoclot/tg/message-entity-type :ukkoclot/tg/user)
5 (:export
6 #:message-entity
7 #:make-message-entity
8 #:message-entity-p
9 #:copy-message-entity
10 #:message-entity-type
11 #:message-entity-offset
12 #:message-entity-length
13 #:message-entity-url
14 #:message-entity-user
15 #:message-entity-language
16 #:message-entity-custom-emoji-id
17
18 #:message-entity-extract))
19(in-package :ukkoclot/tg/message-entity)
20
21(define-tg-type message-entity
22 (type message-entity-type)
23 (offset integer)
24 (length integer)
25 (url (or string null) nil)
26 (user (or user null) nil)
27 (language (or string null) nil)
28 (custom-emoji-id (or string null) nil))
29
30(unless (= char-code-limit #x110000)
31 (error "Some UTF-16 fuckery assumes that system chars are UTF-32"))
32
33(defun utf16-width (ch)
34 (if (< (char-code ch) #x10000)
35 1
36 2))
37
38(defun message-entity-extract (entity text)
39 (with-slots (length offset) entity
40 (if (= length 0)
41 ""
42 (let* ((start (iterate
43 (with curr-idx16 = 0)
44 (for ch in-string text with-index curr-idx32)
45 (for curr-width = (utf16-width ch))
46 (when (or (= curr-idx16 offset)
47 (> (+ curr-idx16 curr-width) offset))
48 (return curr-idx32))
49 (setq curr-idx16 (+ curr-idx16 curr-width))
50 (finally (return (length text)))))
51 (end (iterate
52 (with curr-len16 = 0)
53 (for ch in-string text from start with-index curr-idx32)
54 (for curr-width = (utf16-width ch))
55 (when (>= curr-len16 length)
56 (return curr-idx32))
57 (setq curr-len16 (+ curr-len16 curr-width))
58 (finally (return (length text))))))
59 (subseq text start end)))))
diff --git a/src/tg/message-reaction-updated.lisp b/src/tg/message-reaction-updated.lisp
new file mode 100644
index 0000000..f91a8f1
--- /dev/null
+++ b/src/tg/message-reaction-updated.lisp
@@ -0,0 +1,31 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/message-reaction-updated
4 (:use
5 :c2cl
6 :ukkoclot/tg/chat
7 :ukkoclot/tg/macros
8 :ukkoclot/tg/reaction-type
9 :ukkoclot/tg/user)
10 (:export
11 #:message-reaction-updated
12 #:make-message-reaction-updated
13 #:message-reaction-updated-p
14 #:copy-message-reaction-updated
15 #:message-reaction-updated-chat
16 #:message-reaction-updated-message-id
17 #:message-reaction-updated-user
18 #:message-reaction-updated-actor-chat
19 #:message-reaction-updated-date
20 #:message-reaction-updated-old-reaction
21 #:message-reaction-updated-new-reaction))
22(in-package :ukkoclot/tg/message-reaction-updated)
23
24(define-tg-type message-reaction-updated
25 (chat chat)
26 (message-id integer)
27 (user (or user null) nil)
28 (actor-chat (or chat null) nil)
29 (date integer)
30 (old-reaction (array reaction-type))
31 (new-reaction (array reaction-type)))
diff --git a/src/tg/message.lisp b/src/tg/message.lisp
new file mode 100644
index 0000000..18eb5c4
--- /dev/null
+++ b/src/tg/message.lisp
@@ -0,0 +1,172 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/message
4 (:use
5 :c2cl
6 :ukkoclot/tg/animation
7 :ukkoclot/tg/chat
8 :ukkoclot/tg/macros
9 :ukkoclot/tg/message-entity
10 :ukkoclot/tg/photo-size
11 :ukkoclot/tg/user)
12 (:export
13 #:message-chat-id
14 #:message-thread-id
15 #:message-id
16
17 #:message
18 #:make-message
19 #:message-p
20 #:copy-message
21 #:message-message-id
22 #:message-message-thread-id
23 #:message-from
24 #:message-sender-boost-count
25 #:message-sender-business-bot
26 #:message-date
27 #:message-business-connection-id
28 #:message-chat
29 #:message-is-topic-message
30 #:message-is-automatic-forward
31 #:message-reply-to-message
32 #:message-reply-to-checklist-task-id
33 #:message-via-bot
34 #:message-edit-date
35 #:message-has-protected-content
36 #:message-is-from-offline
37 #:message-is-paid-post
38 #:message-media-group-id
39 #:message-author-signature
40 #:message-paid-star-count
41 #:message-text
42 #:message-entities
43 #:message-effect-id
44 #:message-animation
45 #:message-photo
46 #:message-caption
47 #:message-show-caption-above-media
48 #:message-has-media-spoiler
49 #:message-new-chat-members
50 #:message-new-chat-title
51 #:message-new-chat-photo
52 #:message-delete-chat-photo
53 #:message-group-chat-created
54 #:message-supergroup-chat-created
55 #:message-channel-chat-created
56 #:message-migrate-to-chat-id
57 #:message-migrate-from-chat-id
58 #:message-pinned-message
59 #:message-connected-website))
60(in-package :ukkoclot/tg/message)
61
62;; If this is a MaybeInaccessibleMessage date will be 0 if this is inaccessible
63(define-tg-type message
64 (message-id integer)
65 (message-thread-id (or integer null) nil)
66 ;; (direct-messages-topic (or direct-messages-topic null) nil)
67 (from (or user null) nil)
68 ;; (sender-chat (or chat null) nil)
69 (sender-boost-count (or integer null) nil)
70 (sender-business-bot (or user null) nil)
71 (date integer)
72 (business-connection-id (or string null) nil)
73 (chat chat nil)
74 ;; (forward-origin (or message-origin null) nil)
75 (is-topic-message boolean nil)
76 (is-automatic-forward boolean nil)
77 (reply-to-message (or message null) nil)
78 ;; (external-reply (or external-reply-info null) nil)
79 ;; (quote (or text-quote null) nil)
80 ;; (reply-to-story (or story null) nil)
81 (reply-to-checklist-task-id (or integer null) nil)
82 (via-bot (or user null) nil)
83 (edit-date (or integer null) nil)
84 (has-protected-content boolean nil)
85 (is-from-offline boolean nil)
86 (is-paid-post boolean nil)
87 (media-group-id (or string null) nil)
88 (author-signature (or string null) nil)
89 (paid-star-count (or string null) nil)
90 (text (or string null) nil)
91 (entities (or (array message-entity) null) nil)
92 ;; (link-preview-options (or link-preview-options null) nil)
93 ;; (suggested-post-info (or suggested-post-info null) nil)
94 (effect-id (or string null) nil)
95 (animation (or animation null) nil)
96 ;; (audio (or audio null) nil)
97 ;; (document (or document null) nil)
98 ;; (paid-media (or paid-media-info null) nil)
99 (photo (or (array photo-size) null) nil)
100 ;; (sticker (or sticker null) nil)
101 ;; (story (or story null) nil)
102 ;; (video (or video null) nil)
103 ;; (video-note (or video-note null) nil)
104 ;; (voice (or voice null) nil)
105 (caption (or string null) nil)
106 ;; (caption-entities (or (array message-entity) null) nil)
107 (show-caption-above-media boolean nil)
108 (has-media-spoiler boolean nil)
109 ;; (contact (or contact null) nil)
110 ;; (dice (or dice null) nil)
111 ;; (game (or game null) nil)
112 ;; (poll (or poll null) nil)
113 ;; (venue (or venue null) nil)
114 ;; (location (or location null) nil)
115 (new-chat-members (or (array user) null) nil)
116 ;; (left-chat-member (or user null) nil)
117 (new-chat-title (or string null) nil)
118 (new-chat-photo (or (array photo-size) null) nil)
119 (delete-chat-photo boolean nil)
120 (group-chat-created boolean nil)
121 (supergroup-chat-created boolean nil)
122 (channel-chat-created boolean nil)
123 ;; (message-auto-delete-timer-changed (orp message-auto-delete-timer-changed null) nil)
124 (migrate-to-chat-id (or integer null) nil)
125 (migrate-from-chat-id (or integer null) nil)
126 (pinned-message (or message null) nil)
127 ;; (invoice (or invoice null) nil)
128 ;; (successful-payment (or successful-payment null) nil)
129 ;; (refunded-payment (or refunded-payment null) nil)
130 ;; (users-shared (or users-shared null) nil)
131 ;; (chat-shared (or chat-shared null) nil)
132 ;; (gift (or gift-info null) nil)
133 ;; (unique-gift (or unique-gift-info null) nil)
134 (connected-website (or string null) nil)
135 ;; (write-access-allowed (or write-access-allowed null) nil)
136 ;; (passport-data (or passport-data null) nil)
137 ;; (proximity-alert-triggered (or proximity-alert-triggered null) nil)
138 ;; (boost-added (or chat-boost-added null) nil)
139 ;; (chat-background-set (or chat-background null) nil)
140 ;; (checklist-tasks-added (or checklist-tasks-added null) nil)
141 ;; (direct-message-price-changed (or direct-message-price-changed null) nil)
142 ;; (forum-topic-created (or forum-topic-created null) nil)
143 ;; (forum-topic-edited (or forum-topic-edited null) nil)
144 ;; (forum-topic-closed (or forum-topic-closed null) nil)
145 ;; (forum-topic-reopened (or forum-topic-reopened null) nil)
146 ;; (general-forum-topic-hidden (or general-forum-topic-hidden null) nil)
147 ;; (general-forum-topic-unhidden (or general-forum-topic-unhidden null) nil)
148 ;; (giveaway-created (or giveaway-created null) nil)
149 ;; (giveaway-winners (or giveaway-winners null) nil)
150 ;; (giveaway-completed (or giveaway-completed null) nil)
151 ;; (paid-message-price-changed (or paid-message-price-changed null) nil)
152 ;; (suggested-post-approved (or suggested-post-approved null) nil)
153 ;; (suggested-post-approval-failed (or suggested-post-approval-failed null) nil)
154 ;; (suggested-post-declined (or suggested-post-declined null) nil)
155 ;; (suggested-post-paid (or suggested-post-paid null) nil)
156 ;; (suggested-post-refunded (or suggested-post-refunded null) nil)
157 ;; (video-chat-scheduled (or video-chat-scheduled null) nil)
158 ;; (video-chat-started (or video-chat-started null) nil)
159 ;; (video-chat-ended (or video-chat-ended null) nil)
160 ;; (video-chat-participants-invited (or video-chat-participants-invited null) nil)
161 ;; (web-app-data (or web-app-data null) nil)
162 ;; (reply-markup (or inline-keyboard-markup null) nil)
163 )
164
165(defun message-id (msg)
166 (message-message-id msg))
167
168(defun message-chat-id (msg)
169 (chat-id (message-chat msg)))
170
171(defun message-thread-id (msg)
172 (message-message-thread-id msg))
diff --git a/src/tg/parse-mode.lisp b/src/tg/parse-mode.lisp
new file mode 100644
index 0000000..57ef2af
--- /dev/null
+++ b/src/tg/parse-mode.lisp
@@ -0,0 +1,11 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/parse-mode
4 (:use :c2cl :ukkoclot/enum)
5 (:export :html :markdown-legacy :markdown :parse-mode))
6(in-package :ukkoclot/tg/parse-mode)
7
8(define-enum parse-mode
9 (markdown-legacy "Markdown")
10 (markdown "MarkdownV2")
11 (html "HTML"))
diff --git a/src/tg/photo-size.lisp b/src/tg/photo-size.lisp
new file mode 100644
index 0000000..32b586c
--- /dev/null
+++ b/src/tg/photo-size.lisp
@@ -0,0 +1,22 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/photo-size
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:photo-size
7 #:make-photo-size
8 #:photo-size-p
9 #:copy-photo-size
10 #:photo-size-file-id
11 #:photo-size-file-unique-id
12 #:photo-size-width
13 #:photo-size-height
14 #:photo-size-file-size))
15(in-package :ukkoclot/tg/photo-size)
16
17(define-tg-type photo-size
18 (file-id string)
19 (file-unique-id string)
20 (width integer)
21 (height integer)
22 (file-size (or integer null) nil))
diff --git a/src/tg/reaction-type-custom-emoji.lisp b/src/tg/reaction-type-custom-emoji.lisp
new file mode 100644
index 0000000..9191f1e
--- /dev/null
+++ b/src/tg/reaction-type-custom-emoji.lisp
@@ -0,0 +1,20 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/reaction-type-custom-emoji
4 (:use :c2cl :ukkoclot/enum :ukkoclot/tg/macros)
5 (:export
6 #:custom-emoji-type
7 #:reaction-type-custom-emoji-type
8 #:reaction-type-custom-emoji
9 #:make-reaction-type-custom-emoji
10 #:reaction-type-custom-emoji-p
11 #:copy-reaction-type-custom-emoji
12 #:reaction-type-custom-emoji-custom-emoji-id))
13(in-package :ukkoclot/tg/reaction-type-custom-emoji)
14
15(define-enum reaction-type-custom-emoji-type
16 (custom-emoji-type "custom_emoji"))
17
18(define-tg-type reaction-type-custom-emoji
19 (type reaction-type-custom-emoji-type)
20 (custom-emoji-id string))
diff --git a/src/tg/reaction-type-emoji.lisp b/src/tg/reaction-type-emoji.lisp
new file mode 100644
index 0000000..bf4920a
--- /dev/null
+++ b/src/tg/reaction-type-emoji.lisp
@@ -0,0 +1,20 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/reaction-type-emoji
4 (:use :c2cl :ukkoclot/enum :ukkoclot/tg/macros)
5 (:export
6 #:reaction-type-emoji-type
7 #:emoji-type
8 #:reaction-type-emoji
9 #:make-reaction-type-emoji
10 #:reaction-type-emoji-p
11 #:copy-reaction-type-emoji
12 #:reaction-type-emoji-emoji))
13(in-package :ukkoclot/tg/reaction-type-emoji)
14
15(define-enum reaction-type-emoji-type
16 (emoji-type "emoji"))
17
18(define-tg-type reaction-type-emoji
19 (type reaction-type-emoji-type)
20 (emoji string))
diff --git a/src/tg/reaction-type-paid.lisp b/src/tg/reaction-type-paid.lisp
new file mode 100644
index 0000000..f5b1bfd
--- /dev/null
+++ b/src/tg/reaction-type-paid.lisp
@@ -0,0 +1,18 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/reaction-type-paid
4 (:use :c2cl :ukkoclot/enum :ukkoclot/tg/macros)
5 (:export
6 #:reaction-type-paid-type
7 #:paid-type
8 #:reaction-type-paid
9 #:make-reaction-type-paid
10 #:reaction-type-paid-p
11 #:copy-reaction-type-paid))
12(in-package :ukkoclot/tg/reaction-type-paid)
13
14(define-enum reaction-type-paid-type
15 (paid-type "paid"))
16
17(define-tg-type reaction-type-paid
18 (type reaction-type-paid-type))
diff --git a/src/tg/reaction-type.lisp b/src/tg/reaction-type.lisp
new file mode 100644
index 0000000..35bf4cd
--- /dev/null
+++ b/src/tg/reaction-type.lisp
@@ -0,0 +1,14 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/reaction-type
4 (:use
5 :c2cl
6 :ukkoclot/tg/macros
7 :ukkoclot/tg/reaction-type-custom-emoji
8 :ukkoclot/tg/reaction-type-emoji
9 :ukkoclot/tg/reaction-type-paid)
10 (:export :reaction-type))
11(in-package :ukkoclot/tg/reaction-type)
12
13(deftype reaction-type ()
14 '(or reaction-type-emoji reaction-type-custom-emoji reaction-type-paid))
diff --git a/src/tg/reply-keyboard-markup.lisp b/src/tg/reply-keyboard-markup.lisp
new file mode 100644
index 0000000..2674c10
--- /dev/null
+++ b/src/tg/reply-keyboard-markup.lisp
@@ -0,0 +1,24 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/reply-keyboard-markup
4 (:use :c2cl :ukkoclot/tg/keyboard-button :ukkoclot/tg/macros)
5 (:export
6 #:reply-keyboard-markup
7 #:make-reply-keyboard-markup
8 #:reply-keyboard-markup-p
9 #:copy-reply-keyboard-markup
10 #:reply-keyboard-markup-keyboard
11 #:reply-keyboard-markup-is-persistent
12 #:reply-keyboard-markup-resize-keyboard
13 #:reply-keyboard-markup-one-time-keyboard
14 #:reply-keyboard-markup-input-field-placeholder
15 #:reply-keyboard-markup-selective))
16(in-package :ukkoclot/tg/reply-keyboard-markup)
17
18(define-tg-type reply-keyboard-markup
19 (keyboard (array (array keyboard-button)))
20 (is-persistent boolean nil)
21 (resize-keyboard boolean nil)
22 (one-time-keyboard boolean nil)
23 (input-field-placeholder (or string null) nil)
24 (selective boolean nil))
diff --git a/src/tg/reply-keyboard-remove.lisp b/src/tg/reply-keyboard-remove.lisp
new file mode 100644
index 0000000..908e46d
--- /dev/null
+++ b/src/tg/reply-keyboard-remove.lisp
@@ -0,0 +1,16 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/reply-keyboard-remove
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:reply-keyboard-remove
7 #:make-reply-keyboard-remove
8 #:reply-keyboard-remove-p
9 #:copy-reply-keyboard-remove
10 #:reply-keyboard-remove-remove-keyboard
11 #:reply-keyboard-remove-selective))
12(in-package :ukkoclot/tg/reply-keyboard-remove)
13
14(define-tg-type reply-keyboard-remove
15 (remove-keyboard boolean t :skip-if-default nil)
16 (selective boolean nil))
diff --git a/src/tg/reply-parameters.lisp b/src/tg/reply-parameters.lisp
new file mode 100644
index 0000000..e41d837
--- /dev/null
+++ b/src/tg/reply-parameters.lisp
@@ -0,0 +1,29 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/reply-parameters
4 (:use :c2cl :ukkoclot/tg/macros :ukkoclot/tg/message-entity)
5 (:export
6 #:reply-parameters
7 #:make-reply-parameters
8 #:reply-parameters-p
9 #:copy-reply-parameters
10 #:reply-parameters-message-id
11 #:reply-parameters-chat-id
12 #:reply-parameters-allow-sending-without-reply
13 #:reply-parameters-quote
14 #:reply-parameters-quote-parse-mode
15 #:reply-parameters-quote-entities
16 #:reply-parameters-quote-position
17 #:reply-parameters-checklist-task-id))
18(in-package :ukkoclot/tg/reply-parameters)
19
20(define-tg-type reply-parameters
21 (message-id integer)
22 (chat-id (or integer string null) nil)
23 ;; TODO: This should be a ternary true, false, default
24 (allow-sending-without-reply boolean nil)
25 (quote (or string null) nil)
26 (quote-parse-mode (or string null) nil)
27 (quote-entities (or (array message-entity) null) nil)
28 (quote-position (or integer null) nil)
29 (checklist-task-id (or integer null) nil))
diff --git a/src/tg/suggested-post-parameters.lisp b/src/tg/suggested-post-parameters.lisp
new file mode 100644
index 0000000..525272a
--- /dev/null
+++ b/src/tg/suggested-post-parameters.lisp
@@ -0,0 +1,16 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/suggested-post-parameters
4 (:use :c2cl :ukkoclot/tg/macros :ukkoclot/tg/suggested-post-price)
5 (:export
6 #:suggested-post-parameters
7 #:make-suggested-post-parameters
8 #:suggested-post-parameters-p
9 #:copy-suggested-post-parameters
10 #:suggested-post-parameters-price
11 #:suggested-post-parameters-send-date))
12(in-package :ukkoclot/tg/suggested-post-parameters)
13
14(define-tg-type suggested-post-parameters
15 (price (or suggested-post-price null) nil)
16 (send-date (or integer null) nil))
diff --git a/src/tg/suggested-post-price.lisp b/src/tg/suggested-post-price.lisp
new file mode 100644
index 0000000..9012e75
--- /dev/null
+++ b/src/tg/suggested-post-price.lisp
@@ -0,0 +1,16 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/suggested-post-price
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:suggested-post-price
7 #:make-suggested-post-price
8 #:suggested-post-price-p
9 #:copy-suggested-post-price
10 #:suggested-post-price-currency
11 #:suggested-post-price-amount))
12(in-package :ukkoclot/tg/suggested-post-price)
13
14(define-tg-type suggested-post-price
15 (currency string) ;(member "XTR" "TON")
16 (amount integer))
diff --git a/src/tg/update.lisp b/src/tg/update.lisp
new file mode 100644
index 0000000..1f0a463
--- /dev/null
+++ b/src/tg/update.lisp
@@ -0,0 +1,52 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/update
4 (:use
5 :c2cl
6 :ukkoclot/tg/macros
7 :ukkoclot/tg/business-connection
8 :ukkoclot/tg/callback-query
9 :ukkoclot/tg/message
10 :ukkoclot/tg/message-reaction-updated)
11 (:export
12 #:update
13 #:make-update
14 #:update-p
15 #:copy-update
16 #:update-update-id
17 #:update-message
18 #:update-edited-message
19 #:update-channel-post
20 #:update-edited-channel-post
21 #:update-business-connection
22 #:update-business-message
23 #:update-edited-business-message
24 #:update-message-reaction
25 #:update-callback-query))
26(in-package :ukkoclot/tg/update)
27
28(define-tg-type update
29 (update-id integer)
30 (message (or message null) nil)
31 (edited-message (or message null) nil)
32 (channel-post (or message null) nil)
33 (edited-channel-post (or message null) nil)
34 (business-connection (or business-connection null) nil)
35 (business-message (or message null) nil)
36 (edited-business-message (or message null) nil)
37 ;; (deleted-business-messages (or business-messages-deleted null) nil)
38 (message-reaction (or message-reaction-updated null) nil)
39 ;; (message-reaction-count (or message-reaction-count-updated null) nil)
40 ;; (inline-query (or inline-query null) nil)
41 ;; (chosen-inline-result (or chosen-inline-result null) nil)
42 (callback-query (or callback-query null) nil)
43 ;; (shipping-query (or shipping-query null) nil)
44 ;; (pre-checkout-query (or pre-checkout-query null) nil)
45 ;; (poll (or poll null) nil)
46 ;; (poll-answer (or poll-answer null) nil)
47 ;; (my-chat-member (or chat-member-updated null) nil)
48 ;; (chat-member (or chat-member-updated null) nil)
49 ;; (chat-join-request (or chat-join-request null) nil)
50 ;; (chat-boost (or chat-boost-updated null) nil)
51 ;; (removed-chat-boost (or chat-boost-removed) nil)
52 )
diff --git a/src/tg/user.lisp b/src/tg/user.lisp
new file mode 100644
index 0000000..c5b5b4d
--- /dev/null
+++ b/src/tg/user.lisp
@@ -0,0 +1,59 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/user
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:import-from :ukkoclot/strings :escape-xml)
6 (:export
7 #:user
8 #:make-user
9 #:user-p
10 #:copy-user
11 #:user-id
12 #:user-is-bot
13 #:user-first-name
14 #:user-last-name
15 #:user-username
16 #:user-language-code
17 #:user-is-premium
18 #:user-added-to-attachment-menu
19 #:user-can-join-groups
20 #:user-can-read-all-group-messages
21 #:user-supports-inline-queries
22 #:user-can-connect-to-business
23
24 #:user-format-name))
25(in-package :ukkoclot/tg/user)
26
27(define-tg-type user
28 (id integer)
29 (is-bot boolean)
30 (first-name string)
31 (last-name (or string null) nil)
32 (username (or string null) nil)
33 (language-code (or string null) nil)
34 (is-premium boolean nil)
35 (added-to-attachment-menu boolean nil)
36 (can-join-groups boolean nil)
37 (can-read-all-group-messages boolean nil)
38 (supports-inline-queries boolean nil)
39 (can-connect-to-business boolean nil))
40
41(defun user-format-name% (user out)
42 (format out "<a href=\"tg://user?id=~A\"><i>" (user-id user))
43 (escape-xml (user-first-name user) out)
44 (when (user-last-name user)
45 (write-char #\Space out)
46 (escape-xml (user-last-name user) out))
47 (write-string "</i>" out)
48
49 (when (user-username user)
50 (write-string " @" out)
51 (escape-xml (user-username user) out))
52
53 (format out "</a> [<code>~A</code>]" (user-id user)))
54
55(defun user-format-name (user &optional out)
56 (if out
57 (user-format-name% user out)
58 (with-output-to-string (stream)
59 (user-format-name% user stream))))
diff --git a/src/tg/web-app-info.lisp b/src/tg/web-app-info.lisp
new file mode 100644
index 0000000..8e96df2
--- /dev/null
+++ b/src/tg/web-app-info.lisp
@@ -0,0 +1,14 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg/web-app-info
4 (:use :c2cl :ukkoclot/tg/macros)
5 (:export
6 #:web-app-info
7 #:make-web-app-info
8 #:web-app-info-p
9 #:copy-web-app-info
10 #:web-app-info-url))
11(in-package :ukkoclot/tg/web-app-info)
12
13(define-tg-type web-app-info
14 (url string))