1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-03-11 14:39:28 +02:00

feat(telegram): ability to choose msg format, mdv2escape (#4036)

this allows to choose parse mode between `HTML` and `Markdownv2`, and
adds a new template function, `mdv2escape`, to escape the characters
according to telegram docs:
https://core.telegram.org/bots/api#formatting-options


closes #4021
This commit is contained in:
Carlos Alexandro Becker 2023-05-27 00:17:02 -03:00 committed by GitHub
parent 3bb9a9a5b3
commit e0dabc1cb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 17 deletions

View File

@ -11,7 +11,11 @@ import (
"github.com/goreleaser/goreleaser/pkg/context"
)
const defaultMessageTemplate = `{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}`
const (
defaultMessageTemplate = `{{ .ProjectName }} {{ mdv2escape .Tag }} is out! Check it out at {{ mdv2escape .ReleaseURL }}`
parseModeHTML = "HTML"
parseModeMarkdown = "MarkdownV2"
)
type Pipe struct{}
@ -26,23 +30,19 @@ func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Announce.Telegram.MessageTemplate == "" {
ctx.Config.Announce.Telegram.MessageTemplate = defaultMessageTemplate
}
switch ctx.Config.Announce.Telegram.ParseMode {
case parseModeHTML, parseModeMarkdown:
break
default:
ctx.Config.Announce.Telegram.ParseMode = parseModeMarkdown
}
return nil
}
func (Pipe) Announce(ctx *context.Context) error {
tpl := tmpl.New(ctx)
msg, err := tpl.Apply(ctx.Config.Announce.Telegram.MessageTemplate)
msg, chatID, err := getMessageDetails(ctx)
if err != nil {
return fmt.Errorf("telegram: %w", err)
}
chatIDStr, err := tpl.Apply(ctx.Config.Announce.Telegram.ChatID)
if err != nil {
return fmt.Errorf("telegram: %w", err)
}
chatID, err := strconv.ParseInt(chatIDStr, 10, 64)
if err != nil {
return fmt.Errorf("telegram: %w", err)
return err
}
var cfg Config
@ -65,3 +65,20 @@ func (Pipe) Announce(ctx *context.Context) error {
log.Debug("message sent")
return nil
}
func getMessageDetails(ctx *context.Context) (string, int64, error) {
msg, err := tmpl.New(ctx).Apply(ctx.Config.Announce.Telegram.MessageTemplate)
if err != nil {
return "", 0, fmt.Errorf("telegram: %w", err)
}
chatIDStr, err := tmpl.New(ctx).Apply(ctx.Config.Announce.Telegram.ChatID)
if err != nil {
return "", 0, fmt.Errorf("telegram: %w", err)
}
chatID, err := strconv.ParseInt(chatIDStr, 10, 64)
if err != nil {
return "", 0, fmt.Errorf("telegram: %w", err)
}
return msg, chatID, nil
}

View File

@ -14,9 +14,24 @@ func TestStringer(t *testing.T) {
}
func TestDefault(t *testing.T) {
ctx := testctx.New()
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, ctx.Config.Announce.Telegram.MessageTemplate, defaultMessageTemplate)
t.Run("empty", func(t *testing.T) {
ctx := testctx.New()
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, ctx.Config.Announce.Telegram.MessageTemplate, defaultMessageTemplate)
require.Equal(t, ctx.Config.Announce.Telegram.ParseMode, parseModeMarkdown)
})
t.Run("markdownv2 parsemode", func(t *testing.T) {
ctx := testctx.New()
ctx.Config.Announce.Telegram.ParseMode = parseModeMarkdown
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, ctx.Config.Announce.Telegram.ParseMode, parseModeMarkdown)
})
t.Run("html parsemode", func(t *testing.T) {
ctx := testctx.New()
ctx.Config.Announce.Telegram.ParseMode = parseModeHTML
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, ctx.Config.Announce.Telegram.ParseMode, parseModeHTML)
})
}
func TestAnnounceInvalidTemplate(t *testing.T) {
@ -84,3 +99,23 @@ func TestSkip(t *testing.T) {
require.False(t, Pipe{}.Skip(ctx))
})
}
func TestGetMessageDetails(t *testing.T) {
t.Run("default message template", func(t *testing.T) {
ctx := testctx.NewWithCfg(
config.Project{
ProjectName: "foo",
Announce: config.Announce{
Telegram: config.Telegram{
ChatID: "1230212",
},
},
},
testctx.WithCurrentTag("v1.0.0"),
)
require.NoError(t, Pipe{}.Default(ctx))
msg, _, err := getMessageDetails(ctx)
require.NoError(t, err)
require.Equal(t, "foo v1\\.0\\.0 is out! Check it out at ", msg)
})
}

View File

@ -232,6 +232,7 @@ func (t *Template) Apply(s string) (string, error) {
"incpatch": incPatch,
"filter": filter(false),
"reverseFilter": filter(true),
"mdv2escape": mdv2Escape,
}).
Parse(s)
if err != nil {
@ -322,3 +323,26 @@ func filter(reverse bool) func(content, exp string) string {
return strings.Join(lines, "\n")
}
}
func mdv2Escape(s string) string {
return strings.NewReplacer(
"_", "\\_",
"*", "\\*",
"[", "\\[",
"]", "\\]",
"(", "\\(",
")", "\\)",
"~", "\\~",
"`", "\\`",
">", "\\>",
"#", "\\#",
"+", "\\+",
"-", "\\-",
"=", "\\=",
"|", "\\|",
"{", "\\{",
"}", "\\}",
".", "\\.",
"!", "\\!",
).Replace(s)
}

View File

@ -410,3 +410,10 @@ func TestBool(t *testing.T) {
}
})
}
func TestMdv2Escape(t *testing.T) {
require.Equal(
t,
"aaa\\_\\*\\[\\]\\(\\)\\~\\`\\>\\#\\+\\-\\=\\|\\{\\}\\.\\!",
mdv2Escape("aaa_*[]()~`>#+-=|{}.!"))
}

View File

@ -1145,6 +1145,7 @@ type Telegram struct {
Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
MessageTemplate string `yaml:"message_template,omitempty" json:"message_template,omitempty"`
ChatID string `yaml:"chat_id,omitempty" json:"chat_id,omitempty" jsonschema:"oneof_type=string;integer"`
ParseMode string `yaml:"parse_mode,omitempty" json:"parse_mode,omitempty" jsonschema:"enum=MarkdownV2,enum=HTML,default=MarkdownV2"`
}
type OpenCollective struct {

View File

@ -25,9 +25,17 @@ announce:
# Message template to use while publishing.
#
# Default: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
# Default: '{{ .ProjectName }} {{ mdv2escape .Tag }} is out! Check it out at {{ mdv2escape .ReleaseURL }}'
# Templates: allowed
message_template: 'Awesome project {{.Tag}} is out!'
# Parse mode.
#
# Valid options are MarkdownV2 and HTML.
#
# Default: MarkdownV2
# Since: v1.19
parse_mode: HTML
```
You can format your message using `MarkdownV2`, for reference, see the
@ -35,3 +43,5 @@ You can format your message using `MarkdownV2`, for reference, see the
!!! tip
Learn more about the [name template engine](/customization/templates/).
In the specific case of `MarkdownV2`, you'll probably need the `mdv2escape`
function.

View File

@ -143,6 +143,7 @@ Usage |Description
`filter "text" "regex"` |keeps only the lines matching the given regex, analogous to `grep -E`. Since v1.6.
`reverseFilter "text" "regex"`|keeps only the lines **not** matching the given regex, analogous to `grep -vE`. Since v1.6.
`title "foo"` |"titlenize" the string using english as language. See [Title](https://pkg.go.dev/golang.org/x/text/cases#Title). Since v1.14.
`mdv2escape "foo"` |escape characteres according to MarkdownV2, especially useful in the Telegram integration. Since v1.19.
With all those fields, you may be able to compose the name of your artifacts
pretty much the way you want: