package telegram import ( "fmt" "html" "strings" ) type messageField struct { label string value string } type messageTemplate struct { title string fields []messageField } func (mt messageTemplate) Format(parseMode string) string { var builder strings.Builder builder.WriteString(mt.title) builder.WriteString("\n") builder.WriteString("-----------------------------\n") formatter := selectValueFormatter(parseMode) for _, field := range mt.fields { appendMessageField(&builder, field.label, field.value, formatter) } return builder.String() } type valueFormatter func(string) string func appendMessageField(builder *strings.Builder, label, value string, formatter valueFormatter) { value = strings.TrimSpace(value) if value == "" { value = "—" } else if formatter != nil { value = formatter(value) } fmt.Fprintf(builder, "• %s: %s\n", label, value) } func selectValueFormatter(parseMode string) valueFormatter { switch strings.ToLower(parseMode) { case "markdown": return func(value string) string { return fmt.Sprintf("*%s*", escapeMarkdown(value)) } case "markdownv2": return func(value string) string { return fmt.Sprintf("*%s*", escapeMarkdownV2(value)) } case "html": return func(value string) string { return fmt.Sprintf("%s", html.EscapeString(value)) } default: return nil } } var markdownEscaper = strings.NewReplacer( "*", "\\*", "_", "\\_", "[", "\\[", "]", "\\]", "(", "\\(", ")", "\\)", "`", "\\`", ) var markdownV2Escaper = strings.NewReplacer( "_", "\\_", "*", "\\*", "[", "\\[", "]", "\\]", "(", "\\(", ")", "\\)", "~", "\\~", "`", "\\`", ">", "\\>", "#", "\\#", "+", "\\+", "-", "\\-", "=", "\\=", "|", "\\|", "{", "\\{", "}", "\\}", ".", "\\.", "!", "\\!", ) func escapeMarkdown(value string) string { return markdownEscaper.Replace(value) } func escapeMarkdownV2(value string) string { return markdownV2Escaper.Replace(value) }