fix long text in telegram
release / docker-image (push) Successful in 1m9s
release / goreleaser (push) Successful in 10m13s

This commit is contained in:
2026-02-12 20:36:37 +03:00
parent 868c90c896
commit 1905e7ab16
3 changed files with 63 additions and 41 deletions
+35 -17
View File
@@ -14,9 +14,9 @@ const (
maxCaptionLen = 1024
)
// formatMemory returns (mainText, captionText) formatted as HTML for Telegram.
// mainText is for sendMessage (up to 4096 chars), captionText for photo captions (up to 1024 chars).
func formatMemory(mem *search.Memory, publicURL string) (mainText, captionText string) {
// formatMemory returns the full message text formatted as HTML for Telegram.
// The text is NOT truncated — the caller is responsible for splitting if needed.
func formatMemory(mem *search.Memory, publicURL string) string {
var b strings.Builder
// Header: date and "ago" text
@@ -43,10 +43,7 @@ func formatMemory(mem *search.Memory, publicURL string) (mainText, captionText s
memoURL := fmt.Sprintf("%s/%s", publicURL, mem.Memo.Name)
b.WriteString("\n\n<a href=\"" + memoURL + "\">Оригинал</a>")
full := b.String()
mainText = truncateHTML(full, maxMessageLen)
captionText = truncateHTML(full, maxCaptionLen)
return mainText, captionText
return b.String()
}
// imageAttachments returns image attachments from the memo.
@@ -60,22 +57,43 @@ func imageAttachments(memo *memos.Memo) []memos.Attachment {
return images
}
// truncateHTML truncates text to maxLen, cutting at a word/line boundary and adding "...".
func truncateHTML(text string, maxLen int) string {
// splitText splits text into chunks of at most maxLen bytes,
// breaking at paragraph (\n\n), line (\n), or word boundaries.
func splitText(text string, maxLen int) []string {
if len(text) <= maxLen {
return text
return []string{text}
}
// Reserve space for "..."
cut := maxLen - 3
var parts []string
remaining := text
// Find last newline or space before cut point
idx := strings.LastIndexAny(text[:cut], "\n ")
if idx <= 0 {
idx = cut
for len(remaining) > maxLen {
chunk := remaining[:maxLen]
// Try to break at a paragraph boundary
idx := strings.LastIndex(chunk, "\n\n")
if idx <= 0 {
// Try a line boundary
idx = strings.LastIndex(chunk, "\n")
}
if idx <= 0 {
// Try a word boundary
idx = strings.LastIndexByte(chunk, ' ')
}
if idx <= 0 {
// Hard cut as last resort
idx = maxLen
}
parts = append(parts, remaining[:idx])
remaining = strings.TrimLeft(remaining[idx:], "\n ")
}
return text[:idx] + "..."
if remaining != "" {
parts = append(parts, remaining)
}
return parts
}
// escapeHTML escapes special HTML characters for Telegram HTML parse mode.