feat(telegram): support
<div class="think">block rendering as blockquote<br /><br />- Convert LLM<think>...</div>
tags to Telegram <blockquote> HTML
with 🧠 prefix for visual distinction
- Fix markdown blockquote (> lines) rendering: convert to <blockquote>
HTML instead of stripping the prefix
- Fix reasoning content not being sent: fallback to ReasoningContent
field when Reasoning is empty (supports DeepSeek and similar models)
```</think>
This commit is contained in:
parent
946af6b53d
commit
3a0af79f73
1 changed files with 76 additions and 1 deletions
|
|
@ -36,6 +36,7 @@ var (
|
||||||
reListItem = regexp.MustCompile(`^[-*]\s+`)
|
reListItem = regexp.MustCompile(`^[-*]\s+`)
|
||||||
reCodeBlock = regexp.MustCompile("```[\\w]*\\n?([\\s\\S]*?)```")
|
reCodeBlock = regexp.MustCompile("```[\\w]*\\n?([\\s\\S]*?)```")
|
||||||
reInlineCode = regexp.MustCompile("`([^`]+)`")
|
reInlineCode = regexp.MustCompile("`([^`]+)`")
|
||||||
|
reThinkBlock = regexp.MustCompile(`(?s)<think>(.*?)</think>`)
|
||||||
)
|
)
|
||||||
|
|
||||||
type TelegramChannel struct {
|
type TelegramChannel struct {
|
||||||
|
|
@ -615,6 +616,10 @@ func markdownToTelegramHTML(text string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert <think>...</think> blocks to blockquote before other processing
|
||||||
|
thinkBlocks := extractThinkBlocks(text)
|
||||||
|
text = thinkBlocks.text
|
||||||
|
|
||||||
codeBlocks := extractCodeBlocks(text)
|
codeBlocks := extractCodeBlocks(text)
|
||||||
text = codeBlocks.text
|
text = codeBlocks.text
|
||||||
|
|
||||||
|
|
@ -623,7 +628,8 @@ func markdownToTelegramHTML(text string) string {
|
||||||
|
|
||||||
text = reHeading.ReplaceAllString(text, "$1")
|
text = reHeading.ReplaceAllString(text, "$1")
|
||||||
|
|
||||||
text = reBlockquote.ReplaceAllString(text, "$1")
|
// Convert blockquote lines (> ...) to <blockquote> HTML
|
||||||
|
text = convertBlockquotes(text)
|
||||||
|
|
||||||
text = escapeHTML(text)
|
text = escapeHTML(text)
|
||||||
|
|
||||||
|
|
@ -659,6 +665,75 @@ func markdownToTelegramHTML(text string) string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore think blocks as <blockquote>
|
||||||
|
for i, content := range thinkBlocks.contents {
|
||||||
|
escaped := escapeHTML(strings.TrimSpace(content))
|
||||||
|
text = strings.ReplaceAll(
|
||||||
|
text,
|
||||||
|
fmt.Sprintf("\x00TK%d\x00", i),
|
||||||
|
fmt.Sprintf("<blockquote>🧠 %s</blockquote>", escaped),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
// thinkBlockMatch holds extracted <think> blocks.
|
||||||
|
type thinkBlockMatch struct {
|
||||||
|
text string
|
||||||
|
contents []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractThinkBlocks extracts <think>...</think> blocks and replaces them with placeholders.
|
||||||
|
func extractThinkBlocks(text string) thinkBlockMatch {
|
||||||
|
matches := reThinkBlock.FindAllStringSubmatch(text, -1)
|
||||||
|
|
||||||
|
contents := make([]string, 0, len(matches))
|
||||||
|
for _, match := range matches {
|
||||||
|
contents = append(contents, match[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
text = reThinkBlock.ReplaceAllStringFunc(text, func(m string) string {
|
||||||
|
placeholder := fmt.Sprintf("\x00TK%d\x00", i)
|
||||||
|
i++
|
||||||
|
return placeholder
|
||||||
|
})
|
||||||
|
|
||||||
|
return thinkBlockMatch{text: text, contents: contents}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertBlockquotes groups consecutive `> ...` lines into <blockquote> blocks.
|
||||||
|
func convertBlockquotes(text string) string {
|
||||||
|
lines := strings.Split(text, "\n")
|
||||||
|
var result []string
|
||||||
|
inBlockquote := false
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
if reBlockquote.MatchString(line) {
|
||||||
|
content := reBlockquote.ReplaceAllString(line, "$1")
|
||||||
|
if !inBlockquote {
|
||||||
|
result = append(result, "\x00BQ_START\x00"+content)
|
||||||
|
inBlockquote = true
|
||||||
|
} else {
|
||||||
|
result = append(result, content)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if inBlockquote {
|
||||||
|
result = append(result, "\x00BQ_END\x00")
|
||||||
|
inBlockquote = false
|
||||||
|
}
|
||||||
|
result = append(result, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if inBlockquote {
|
||||||
|
result = append(result, "\x00BQ_END\x00")
|
||||||
|
}
|
||||||
|
|
||||||
|
text = strings.Join(result, "\n")
|
||||||
|
text = strings.ReplaceAll(text, "\x00BQ_START\x00", "<blockquote>")
|
||||||
|
text = strings.ReplaceAll(text, "\n\x00BQ_END\x00", "</blockquote>")
|
||||||
|
text = strings.ReplaceAll(text, "\x00BQ_END\x00", "</blockquote>")
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue