Files
notify/tools.go
2025-11-29 14:45:32 +03:00

113 lines
2.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package notify
import (
"html"
"regexp"
"strings"
"github.com/mattn/go-runewidth"
)
// Проверка, что строка — число (целое или с точкой, +,-, пробелы)
var numberRe = regexp.MustCompile(`^[+-]?[\d\s_]*\.?\d+$`)
// Выравнивание текста по центру с учётом визуальной ширины
func centerPad(s string, width int) string {
w := runewidth.StringWidth(s)
if w >= width {
return s
}
left := (width - w) / 2
right := width - w - left
return strings.Repeat(" ", left) + s + strings.Repeat(" ", right)
}
// Выравнивание текста по левому краю с учётом ширины
func padRightVisual(s string, width int) string {
w := runewidth.StringWidth(s)
if w >= width {
return s
}
return s + strings.Repeat(" ", width-w)
}
// Выравнивание текста по правому краю с учётом ширины
func padLeftVisual(s string, width int) string {
w := runewidth.StringWidth(s)
if w >= width {
return s
}
return strings.Repeat(" ", width-w) + s
}
// BuildTelegramBoxTable строит ASCII-таблицу с рамками для Telegram HTML <pre>
func BuildTelegramTable(rows [][]string) string {
if len(rows) == 0 {
return ""
}
// Экранируем HTML-символы
for i := range rows {
for j := range rows[i] {
rows[i][j] = html.EscapeString(rows[i][j])
}
}
// Определяем визуальную ширину колонок
colWidths := make([]int, len(rows[0]))
for _, row := range rows {
for i, col := range row {
w := runewidth.StringWidth(col)
if w > colWidths[i] {
colWidths[i] = w
}
}
}
// Функция для линий-разделителей
buildSep := func() string {
var s strings.Builder
s.WriteString("+")
for _, w := range colWidths {
s.WriteString(strings.Repeat("-", w+2))
s.WriteString("+")
}
return s.String()
}
var b strings.Builder
b.WriteString(buildSep() + "\n")
for ri, row := range rows {
b.WriteString("|")
for i, col := range row {
w := colWidths[i]
var cell string
switch {
case ri == 0:
// Заголовок — по центру
cell = centerPad(col, w)
case numberRe.MatchString(col):
// Число — по правому краю
cell = padLeftVisual(col, w)
default:
// Текст — по левому краю
cell = padRightVisual(col, w)
}
b.WriteString(" " + cell + " |")
}
b.WriteString("\n")
// Разделитель после заголовка
if ri == 0 {
b.WriteString(buildSep() + "\n")
}
}
b.WriteString(buildSep() + "\n")
return b.String()
}