bot changes
This commit is contained in:
@@ -2,6 +2,7 @@ package screens
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"example.com/m/bot"
|
||||
@@ -26,6 +27,9 @@ type CreativeEditorFields struct {
|
||||
MediaType string // "photo", "video", "animation"
|
||||
MediaFileID string // File ID из Telegram
|
||||
|
||||
// Навигация (хлебные крошки)
|
||||
Navigation string
|
||||
|
||||
// Состояние для добавления кнопки
|
||||
WaitingForButtonText bool
|
||||
WaitingForButtonURL bool
|
||||
@@ -43,6 +47,13 @@ type CreativeEditorFields struct {
|
||||
|
||||
// GetCreativeText возвращает текст для превью креатива
|
||||
func (e *CreativeEditorFields) GetCreativeText() string {
|
||||
var result string
|
||||
|
||||
// Добавляем навигацию если она есть
|
||||
if e.Navigation != "" {
|
||||
result = fmt.Sprintf("<i>%s</i>\n\n", e.Navigation)
|
||||
}
|
||||
|
||||
if e.Text != nil && *e.Text != "" {
|
||||
// Проверяем что текст не является "визуально пустым" HTML
|
||||
// Например: "<a class=\"tg-link\"></a>" - пустая ссылка
|
||||
@@ -51,7 +62,7 @@ func (e *CreativeEditorFields) GetCreativeText() string {
|
||||
// Убираем пустые HTML-теги (простая проверка)
|
||||
if text == "<a class=\"tg-link\"></a>" || text == "" {
|
||||
log.Info().Str("text", *e.Text).Msg("GetCreativeText: text is visually empty, using default")
|
||||
return `<i>💭 Я твой креатив
|
||||
return result + `<i>💭 Я твой креатив
|
||||
|
||||
У меня пока нет текста, добавь его ниже.
|
||||
|
||||
@@ -59,10 +70,10 @@ func (e *CreativeEditorFields) GetCreativeText() string {
|
||||
}
|
||||
|
||||
log.Info().Str("text", *e.Text).Msg("GetCreativeText: returning creative text")
|
||||
return *e.Text
|
||||
return result + *e.Text
|
||||
}
|
||||
log.Info().Bool("text_is_nil", e.Text == nil).Msg("GetCreativeText: returning default text")
|
||||
return `<i>💭 Я твой креатив
|
||||
return result + `<i>💭 Я твой креатив
|
||||
|
||||
У меня пока нет текста, добавь его ниже.
|
||||
|
||||
@@ -361,54 +372,89 @@ func (e *CreativeEditorFields) GetFormattedText(message *echotron.Message) strin
|
||||
return message.Text
|
||||
}
|
||||
|
||||
type tagSpan struct {
|
||||
open string
|
||||
close string
|
||||
start int
|
||||
end int
|
||||
len int
|
||||
}
|
||||
|
||||
// Преобразуем текст в руны для правильной работы с UTF-8
|
||||
runes := []rune(message.Text)
|
||||
result := ""
|
||||
lastPos := 0
|
||||
|
||||
// Обрабатываем entities
|
||||
var spans []tagSpan
|
||||
for _, entity := range message.Entities {
|
||||
// Добавляем текст до entity
|
||||
if entity.Offset > lastPos {
|
||||
result += string(runes[lastPos:entity.Offset])
|
||||
// URL уже присутствует в сыром тексте, чтобы не дублировать - пропускаем entity.
|
||||
if entity.Type == "url" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Получаем текст entity
|
||||
entityText := string(runes[entity.Offset : entity.Offset+entity.Length])
|
||||
entityText := ""
|
||||
if entity.Offset+entity.Length <= len(runes) {
|
||||
entityText = string(runes[entity.Offset : entity.Offset+entity.Length])
|
||||
}
|
||||
|
||||
// Оборачиваем в соответствующие HTML-теги
|
||||
var openTag, closeTag string
|
||||
switch entity.Type {
|
||||
case "bold":
|
||||
result += "<b>" + entityText + "</b>"
|
||||
openTag, closeTag = "<b>", "</b>"
|
||||
case "italic":
|
||||
result += "<i>" + entityText + "</i>"
|
||||
openTag, closeTag = "<i>", "</i>"
|
||||
case "underline":
|
||||
result += "<u>" + entityText + "</u>"
|
||||
openTag, closeTag = "<u>", "</u>"
|
||||
case "strikethrough":
|
||||
result += "<s>" + entityText + "</s>"
|
||||
openTag, closeTag = "<s>", "</s>"
|
||||
case "code":
|
||||
result += "<code>" + entityText + "</code>"
|
||||
openTag, closeTag = "<code>", "</code>"
|
||||
case "pre":
|
||||
result += "<pre>" + entityText + "</pre>"
|
||||
openTag, closeTag = "<pre>", "</pre>"
|
||||
case "text_link":
|
||||
if entity.URL != "" {
|
||||
result += fmt.Sprintf("<a href=\"%s\">%s</a>", entity.URL, entityText)
|
||||
} else {
|
||||
result += entityText
|
||||
openTag = fmt.Sprintf("<a href=\"%s\">", entity.URL)
|
||||
closeTag = "</a>"
|
||||
}
|
||||
case "url":
|
||||
result += entityText
|
||||
default:
|
||||
result += entityText
|
||||
_ = entityText
|
||||
}
|
||||
|
||||
lastPos = entity.Offset + entity.Length
|
||||
if openTag != "" && closeTag != "" {
|
||||
spans = append(spans, tagSpan{
|
||||
open: openTag,
|
||||
close: closeTag,
|
||||
start: entity.Offset,
|
||||
end: entity.Offset + entity.Length,
|
||||
len: entity.Length,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Добавляем оставшийся текст
|
||||
if lastPos < len(runes) {
|
||||
result += string(runes[lastPos:])
|
||||
opens := make(map[int][]tagSpan)
|
||||
closes := make(map[int][]tagSpan)
|
||||
for _, span := range spans {
|
||||
opens[span.start] = append(opens[span.start], span)
|
||||
closes[span.end] = append(closes[span.end], span)
|
||||
}
|
||||
|
||||
return result
|
||||
// Пишем текст один раз, вставляя HTML-теги по позициям
|
||||
var result strings.Builder
|
||||
for i := 0; i <= len(runes); i++ {
|
||||
if closing, ok := closes[i]; ok {
|
||||
sort.Slice(closing, func(a, b int) bool { return closing[a].len < closing[b].len })
|
||||
for _, span := range closing {
|
||||
result.WriteString(span.close)
|
||||
}
|
||||
}
|
||||
if opening, ok := opens[i]; ok {
|
||||
sort.Slice(opening, func(a, b int) bool { return opening[a].len > opening[b].len })
|
||||
for _, span := range opening {
|
||||
result.WriteString(span.open)
|
||||
}
|
||||
}
|
||||
if i < len(runes) {
|
||||
result.WriteRune(runes[i])
|
||||
}
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user