better message formatting
Some checks failed
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/bump_version Pipeline failed
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
Some checks failed
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/bump_version Pipeline failed
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -47,15 +48,15 @@ type sendMessagePayload struct {
|
||||
|
||||
func NewClient(logger mlogger.Logger, cfg *notconfig.TelegramConfig) (Client, error) {
|
||||
if cfg == nil {
|
||||
return nil, merrors.InvalidArgument("telegram configuration is not provided")
|
||||
return nil, merrors.InvalidArgument("telegram configuration is not provided", "config.notification.telegram")
|
||||
}
|
||||
token := strings.TrimSpace(os.Getenv(cfg.BotTokenEnv))
|
||||
if token == "" {
|
||||
return nil, merrors.InvalidArgument(fmt.Sprintf("telegram bot token env %s is empty", cfg.BotTokenEnv))
|
||||
return nil, merrors.InvalidArgument(fmt.Sprintf("telegram bot token env %s is empty", cfg.BotTokenEnv), cfg.BotTokenEnv)
|
||||
}
|
||||
chatID := strings.TrimSpace(os.Getenv(cfg.ChatIDEnv))
|
||||
if chatID == "" {
|
||||
return nil, merrors.InvalidArgument(fmt.Sprintf("telegram chat id env %s is empty", cfg.ChatIDEnv))
|
||||
return nil, merrors.InvalidArgument(fmt.Sprintf("telegram chat id env %s is empty", cfg.ChatIDEnv), cfg.ChatIDEnv)
|
||||
}
|
||||
|
||||
var threadID *int64
|
||||
@@ -64,7 +65,7 @@ func NewClient(logger mlogger.Logger, cfg *notconfig.TelegramConfig) (Client, er
|
||||
if raw != "" {
|
||||
val, err := strconv.ParseInt(raw, 10, 64)
|
||||
if err != nil {
|
||||
return nil, merrors.InvalidArgumentWrap(err, fmt.Sprintf("telegram thread id env %s is invalid", env))
|
||||
return nil, merrors.InvalidArgumentWrap(err, fmt.Sprintf("telegram thread id env %s is invalid", env), env)
|
||||
}
|
||||
threadID = &val
|
||||
}
|
||||
@@ -79,6 +80,10 @@ func NewClient(logger mlogger.Logger, cfg *notconfig.TelegramConfig) (Client, er
|
||||
if apiURL == "" {
|
||||
apiURL = defaultAPIURL
|
||||
}
|
||||
parseMode := strings.TrimSpace(cfg.ParseMode)
|
||||
if parseMode == "" {
|
||||
parseMode = "Markdown"
|
||||
}
|
||||
|
||||
return &client{
|
||||
logger: logger.Named("telegram"),
|
||||
@@ -89,15 +94,15 @@ func NewClient(logger mlogger.Logger, cfg *notconfig.TelegramConfig) (Client, er
|
||||
botToken: token,
|
||||
chatID: chatID,
|
||||
threadID: threadID,
|
||||
parseMode: strings.TrimSpace(cfg.ParseMode),
|
||||
parseMode: parseMode,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *client) SendDemoRequest(ctx context.Context, request *model.DemoRequest) error {
|
||||
if request == nil {
|
||||
return merrors.InvalidArgument("demo request payload is nil")
|
||||
return merrors.InvalidArgument("demo request payload is nil", "request")
|
||||
}
|
||||
message := buildMessage(request)
|
||||
message := buildMessage(request, c.parseMode)
|
||||
payload := sendMessagePayload{
|
||||
ChatID: c.chatID,
|
||||
Text: message,
|
||||
@@ -157,16 +162,89 @@ func (c *client) endpoint() string {
|
||||
return fmt.Sprintf("%s/bot%s/sendMessage", c.apiURL, c.botToken)
|
||||
}
|
||||
|
||||
func buildMessage(req *model.DemoRequest) string {
|
||||
func buildMessage(req *model.DemoRequest, parseMode string) string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("New demo request received\n")
|
||||
builder.WriteString(fmt.Sprintf("Name: %s\n", req.Name))
|
||||
builder.WriteString(fmt.Sprintf("Organization: %s\n", req.OrganizationName))
|
||||
builder.WriteString(fmt.Sprintf("Phone: %s\n", req.Phone))
|
||||
builder.WriteString(fmt.Sprintf("Work email: %s\n", req.WorkEmail))
|
||||
builder.WriteString(fmt.Sprintf("Payout volume: %s\n", req.PayoutVolume))
|
||||
if req.Comment != "" {
|
||||
builder.WriteString(fmt.Sprintf("Comment: %s\n", req.Comment))
|
||||
builder.WriteString("-----------------------------\n")
|
||||
|
||||
formatter := selectValueFormatter(parseMode)
|
||||
appendMessageField(&builder, "Name", req.Name, formatter)
|
||||
appendMessageField(&builder, "Organization", req.OrganizationName, formatter)
|
||||
appendMessageField(&builder, "Phone", req.Phone, formatter)
|
||||
appendMessageField(&builder, "Work email", req.WorkEmail, formatter)
|
||||
appendMessageField(&builder, "Payout volume", req.PayoutVolume, formatter)
|
||||
if strings.TrimSpace(req.Comment) != "" {
|
||||
appendMessageField(&builder, "Comment", req.Comment, 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("<b>%s</b>", 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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user