summaryrefslogtreecommitdiff
path: root/src/tg-types/message-entity.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tg-types/message-entity.lisp')
-rw-r--r--src/tg-types/message-entity.lisp61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/tg-types/message-entity.lisp b/src/tg-types/message-entity.lisp
new file mode 100644
index 0000000..fcabcce
--- /dev/null
+++ b/src/tg-types/message-entity.lisp
@@ -0,0 +1,61 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/tg-types/message-entity
4 (:use :c2cl :iterate :ukkoclot/tg-types/macros :ukkoclot/tg-types/parsers :ukkoclot/tg-types/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 hash->message-entity
19 message-entity-extract
20 parse-message-entity-array))
21(in-package :ukkoclot/tg-types/message-entity)
22
23(define-tg-type message-entity
24 (type keyword nil :parser tg-string->keyword)
25 (offset integer)
26 (length integer)
27 (url (or string null) nil)
28 (user (or user null) nil)
29 (language (or string null) nil)
30 (custom-emoji-id (or string null) nil))
31
32(unless (= char-code-limit #x110000)
33 (error "Some UTF-16 fuckery assumes that system chars are UTF-32"))
34
35(defun utf16-width (ch)
36 (if (< (char-code ch) #x10000)
37 1
38 2))
39
40(defun message-entity-extract (entity text)
41 (with-slots (length offset) entity
42 (if (= length 0)
43 ""
44 (let* ((start (iterate
45 (with curr-idx16 = 0)
46 (for ch in-string text with-index curr-idx32)
47 (for curr-width = (utf16-width ch))
48 (when (or (= curr-idx16 offset)
49 (> (+ curr-idx16 curr-width) offset))
50 (return curr-idx32))
51 (setq curr-idx16 (+ curr-idx16 curr-width))
52 (finally (return (length text)))))
53 (end (iterate
54 (with curr-len16 = 0)
55 (for ch in-string text from start with-index curr-idx32)
56 (for curr-width = (utf16-width ch))
57 (when (>= curr-len16 length)
58 (return curr-idx32))
59 (setq curr-len16 (+ curr-len16 curr-width))
60 (finally (return (length text))))))
61 (subseq text start end)))))