diff options
Diffstat (limited to 'src/tg')
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 | |||
| 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)) | ||