chat_sdk-telegram 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d2616114e163dc4eb34bb79b9b008cde53832f9483957e2511bbbd3596c34e3
4
- data.tar.gz: 3b35d0c60617dc93afa0b706b70e80f21d5672a4a00e0f7d0db374f49c6318c4
3
+ metadata.gz: f873b2a03fd234639c59a872229bcd2942abc6169b1c970023ceaa16cb239062
4
+ data.tar.gz: 9e41b3269dc1116e2bc7169b146770337e8f9bbb6020b85f7f36c575828cf678
5
5
  SHA512:
6
- metadata.gz: d45e83949b108b320fa21661d0bff2549ab7c4db6a386c3bc03c24e503b5299aebb06b0bed88e10254a7fba6b1770ec1bd8ad866171f24996bd202586951e85b
7
- data.tar.gz: fb63c59d2e3a750530ff211f392b35b3003b5afa8e7bb7f7c277149bebc6d32ca4cc69f85c473428be9419359b1162a6d7ed7843472343069cbeef503b6255f7
6
+ metadata.gz: 331146db0c5788c64ce2c7da1a097ff0ae54d2ad946d471be832fdb8123439db92feb7e3db213c023bed0f61cc3121822e6cf26560fc1ec6bd8962ec0082fbe3
7
+ data.tar.gz: 9843eee8e48fab1a345487035beac68a014bc558e343346dc1cfe6a170f7799b9170f9cff2e10d9bc8fdb738c4cc73fa118731558508baf8970509e54aeea3e2
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatSDK
4
+ module Telegram
5
+ class FormatConverter < ChatSDK::Format::Converter
6
+ SPECIAL_CHARS = %w[_ * [ ] ( ) ~ \\ ` > # + - = | { } . !].freeze
7
+
8
+ # Telegram MarkdownV2 → standard Markdown
9
+ def to_markdown(platform_text)
10
+ text = platform_text.to_s
11
+ return "" if text.empty?
12
+
13
+ # Convert Telegram user links: [text](tg://user?id=123) → @123
14
+ text = text.gsub(/\[([^\]]*)\]\(tg:\/\/user\?id=(\d+)\)/, '@\2')
15
+
16
+ # Strip underline markers: __text__ → text
17
+ # Use a loop to handle nested cases
18
+ text = text.gsub(/(?<!_)__(?!_)(.+?)(?<!_)__(?!_)/m, '\1')
19
+
20
+ # Strip spoiler markers: ||text|| → text
21
+ text = text.gsub(/\|\|(.+?)\|\|/m, '\1')
22
+
23
+ # Unescape all backslash-escaped characters
24
+ text.gsub(/\\(.)/, '\1')
25
+ end
26
+
27
+ # Standard Markdown → Telegram MarkdownV2
28
+ def from_markdown(markdown)
29
+ text = markdown.to_s
30
+ return "" if text.empty?
31
+
32
+ parts = split_code_blocks(text)
33
+ parts.map.with_index { |part, i| i.odd? ? part : escape_special_chars(part) }.join
34
+ end
35
+
36
+ private
37
+
38
+ # Escape Telegram MarkdownV2 special chars outside of markdown syntax.
39
+ # Preserves bold (**), italic (*), strikethrough (~~), links, etc.
40
+ def escape_special_chars(text)
41
+ result = +""
42
+ i = 0
43
+ chars = text.chars
44
+
45
+ while i < chars.length
46
+ char = chars[i]
47
+
48
+ # Bold: **text** — pass through
49
+ if char == "*" && chars[i + 1] == "*"
50
+ close = text.index("**", i + 2)
51
+ if close
52
+ inner = text[(i + 2)...close]
53
+ result << "**#{escape_special_chars(inner)}**"
54
+ i = close + 2
55
+ next
56
+ end
57
+ end
58
+
59
+ # Italic: *text* (single asterisk, not preceded/followed by another *)
60
+ if char == "*" && chars[i + 1] != "*"
61
+ close = find_single_asterisk_close(chars, i + 1)
62
+ if close
63
+ inner = chars[(i + 1)...close].join
64
+ result << "*#{escape_special_chars(inner)}*"
65
+ i = close + 1
66
+ next
67
+ end
68
+ end
69
+
70
+ # Strikethrough: ~~text~~
71
+ if char == "~" && chars[i + 1] == "~"
72
+ close = text.index("~~", i + 2)
73
+ if close
74
+ inner = text[(i + 2)...close]
75
+ result << "~~#{escape_special_chars(inner)}~~"
76
+ i = close + 2
77
+ next
78
+ end
79
+ end
80
+
81
+ # Links: [text](url) — pass through
82
+ if char == "["
83
+ link_match = text[i..].match(/\A\[([^\]]*)\]\(([^)]*)\)/)
84
+ if link_match
85
+ result << link_match[0]
86
+ i += link_match[0].length
87
+ next
88
+ end
89
+ end
90
+
91
+ # Escape special characters
92
+ result << if SPECIAL_CHARS.include?(char)
93
+ "\\#{char}"
94
+ else
95
+ char
96
+ end
97
+
98
+ i += 1
99
+ end
100
+
101
+ result
102
+ end
103
+
104
+ # Find closing single * that isn't part of **
105
+ def find_single_asterisk_close(chars, start)
106
+ i = start
107
+ while i < chars.length
108
+ if chars[i] == "*" && chars[i + 1] != "*" && (i == start || chars[i - 1] != "*")
109
+ return i
110
+ end
111
+ i += 1
112
+ end
113
+ nil
114
+ end
115
+ end
116
+ end
117
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chat_sdk-telegram
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Quentin Rousseau
@@ -48,6 +48,7 @@ files:
48
48
  - lib/chat_sdk/telegram/adapter.rb
49
49
  - lib/chat_sdk/telegram/api_client.rb
50
50
  - lib/chat_sdk/telegram/event_parser.rb
51
+ - lib/chat_sdk/telegram/format_converter.rb
51
52
  - lib/chat_sdk/telegram/keyboard_renderer.rb
52
53
  homepage: https://github.com/rootlyhq/chat-sdk
53
54
  licenses: