Skip to content

Commit 9e15025

Browse files
authored
Merge pull request #1140 from cappyzawa/feat/telegram-proxy-support
Add proxy support to Telegram notifier
2 parents 3f4e962 + e4160c5 commit 9e15025

File tree

6 files changed

+81
-37
lines changed

6 files changed

+81
-37
lines changed

docs/spec/v1beta3/providers.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,8 +554,7 @@ This can be a unique identifier (`-1234567890`) for the target chat,
554554
a unique identifier with the topic identifier (`-1234567890:1`) for the forum chat,
555555
or the username (`@username`) of the target channel.
556556

557-
This Provider type does not support the configuration of a [proxy URL](#https-proxy)
558-
or [certificate secret reference](#certificate-secret-reference).
557+
This Provider type does not support the configuration of a [certificate secret reference](#certificate-secret-reference).
559558

560559
###### Telegram example
561560

go.mod

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ require (
1414
github.com/PagerDuty/go-pagerduty v1.8.0
1515
github.com/cdevents/sdk-go v0.4.1
1616
github.com/chainguard-dev/git-urls v1.0.2
17-
github.com/containrrr/shoutrrr v0.8.0
1817
github.com/elazarl/goproxy v1.7.2
1918
github.com/fluxcd/cli-utils v0.36.0-flux.13
2019
github.com/fluxcd/notification-controller/api v1.6.0
@@ -99,7 +98,6 @@ require (
9998
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
10099
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
101100
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
102-
github.com/fatih/color v1.16.0 // indirect
103101
github.com/felixge/httpsnoop v1.0.4 // indirect
104102
github.com/fluxcd/pkg/apis/acl v0.7.0 // indirect
105103
github.com/fluxcd/pkg/apis/kustomize v1.10.0 // indirect
@@ -145,8 +143,6 @@ require (
145143
github.com/leodido/go-urn v1.4.0 // indirect
146144
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
147145
github.com/mailru/easyjson v0.9.0 // indirect
148-
github.com/mattn/go-colorable v0.1.13 // indirect
149-
github.com/mattn/go-isatty v0.0.20 // indirect
150146
github.com/mitchellh/go-homedir v1.1.0 // indirect
151147
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
152148
github.com/mitchellh/mapstructure v1.5.0 // indirect

go.sum

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ github.com/cloudevents/sdk-go/v2 v2.15.2/go.mod h1:lL7kSWAE/V8VI4Wh0jbL2v/jvqsm6
105105
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
106106
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
107107
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
108-
github.com/containrrr/shoutrrr v0.8.0 h1:mfG2ATzIS7NR2Ec6XL+xyoHzN97H8WPjir8aYzJUSec=
109-
github.com/containrrr/shoutrrr v0.8.0/go.mod h1:ioyQAyu1LJY6sILuNyKaQaw+9Ttik5QePU8atnAdO2o=
110108
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
111109
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
112110
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
@@ -211,7 +209,6 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
211209
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
212210
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
213211
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
214-
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
215212
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
216213
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
217214
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
@@ -295,8 +292,6 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe
295292
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
296293
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
297294
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
298-
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
299-
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
300295
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
301296
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
302297
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -330,7 +325,6 @@ github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4
330325
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
331326
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
332327
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
333-
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
334328
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
335329
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
336330
github.com/microsoft/azure-devops-go-api/azuredevops/v6 v6.0.1 h1:ACnM5CwgTH6OSQHErzZDrotEG0rffPdJxtF/WOWglAw=
@@ -514,9 +508,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
514508
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
515509
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
516510
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
517-
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
518511
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
519-
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
520512
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
521513
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
522514
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

internal/notifier/factory.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ func azureEventHubNotifierFunc(opts notifierOptions) (Interface, error) {
285285
}
286286

287287
func telegramNotifierFunc(opts notifierOptions) (Interface, error) {
288-
return NewTelegram(opts.Channel, opts.Token)
288+
return NewTelegram(opts.URL, opts.ProxyURL, opts.Channel, opts.Token)
289289
}
290290

291291
func larkNotifierFunc(opts notifierOptions) (Interface, error) {

internal/notifier/telegram.go

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,50 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"net/url"
78
"strings"
89

9-
"github.com/containrrr/shoutrrr"
1010
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
1111
)
1212

13+
const (
14+
defaultTelegramBaseURL = "https://api.telegram.org/bot%s"
15+
sendMessageMethodName = "sendMessage"
16+
)
17+
1318
type Telegram struct {
14-
Channel string
15-
Token string
16-
send func(url string, message string) error // this allows the send function to be overridden for testing
19+
URL string
20+
ProxyURL string
21+
Channel string
22+
Token string
23+
}
24+
25+
// TelegramPayload represents the payload sent to Telegram Bot API
26+
// Reference: https://core.telegram.org/bots/api#sendmessage
27+
type TelegramPayload struct {
28+
ChatID string `json:"chat_id"` // Unique identifier for the target chat
29+
Text string `json:"text"` // Text of the message to be sent
30+
ParseMode string `json:"parse_mode"` // Mode for parsing entities in the message text
1731
}
1832

19-
func NewTelegram(channel, token string) (*Telegram, error) {
33+
func NewTelegram(apiURL, proxyURL, channel, token string) (*Telegram, error) {
2034
if channel == "" {
2135
return nil, errors.New("empty Telegram channel")
2236
}
2337

38+
if token == "" {
39+
return nil, errors.New("empty Telegram token")
40+
}
41+
42+
// Note: Always ignore apiURL parameter for backward compatibility.
43+
// The address field was ignored until v1.6.0.
44+
apiURL = fmt.Sprintf(defaultTelegramBaseURL, token)
45+
2446
return &Telegram{
25-
Channel: channel,
26-
Token: token,
27-
send: shoutrrr.Send,
47+
URL: apiURL,
48+
ProxyURL: proxyURL,
49+
Channel: channel,
50+
Token: token,
2851
}, nil
2952
}
3053

@@ -46,9 +69,24 @@ func (t *Telegram) Post(ctx context.Context, event eventv1.Event) error {
4669
metadata = metadata + fmt.Sprintf("\\- *%s*: %s\n", escapeString(k), escapeString(v))
4770
}
4871
message := fmt.Sprintf("*%s*\n%s\n%s", escapeString(heading), escapeString(event.Message), metadata)
49-
url := fmt.Sprintf("telegram://%s@telegram?channels=%s&parseMode=markDownv2", t.Token, t.Channel)
50-
err := t.send(url, message)
51-
return err
72+
73+
payload := TelegramPayload{
74+
ChatID: t.Channel,
75+
Text: message,
76+
ParseMode: "MarkdownV2", // https://core.telegram.org/bots/api#markdownv2-style
77+
}
78+
79+
apiURL, err := url.JoinPath(t.URL, sendMessageMethodName)
80+
if err != nil {
81+
return fmt.Errorf("failed to construct API URL: %w", err)
82+
}
83+
84+
var opts []postOption
85+
if t.ProxyURL != "" {
86+
opts = append(opts, withProxy(t.ProxyURL))
87+
}
88+
89+
return postMessage(ctx, apiURL, payload, opts...)
5290
}
5391

5492
// The telegram API requires that some special characters are escaped

internal/notifier/telegram_test.go

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,21 @@ import (
3131

3232
func TestTelegram_Post(t *testing.T) {
3333
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
34+
require.Equal(t, http.MethodPost, r.Method)
35+
require.Equal(t, "/sendMessage", r.URL.Path)
36+
require.Equal(t, "application/json", r.Header.Get("Content-Type"))
37+
3438
b, err := io.ReadAll(r.Body)
3539
require.NoError(t, err)
3640

37-
var payload = WebexPayload{}
41+
var payload TelegramPayload
3842
err = json.Unmarshal(b, &payload)
3943
require.NoError(t, err)
40-
}))
41-
defer ts.Close()
42-
43-
telegram, err := NewTelegram("channel", "token")
44-
require.NoError(t, err)
4544

46-
telegram.send = func(url, message string) error {
47-
require.Equal(t, "telegram://token@telegram?channels=channel&parseMode=markDownv2", url)
45+
require.Equal(t, "channel", payload.ChatID)
46+
require.Equal(t, "MarkdownV2", payload.ParseMode)
4847

49-
lines := strings.Split(message, "\n")
48+
lines := strings.Split(payload.Text, "\n")
5049
require.Len(t, lines, 5)
5150
slices.Sort(lines[2:4])
5251
require.Equal(t, "*💫 gitrepository/webapp/gitops\\-system*", lines[0])
@@ -57,11 +56,31 @@ func TestTelegram_Post(t *testing.T) {
5756
"",
5857
}, lines[2:])
5958

60-
return nil
61-
}
59+
w.WriteHeader(http.StatusOK)
60+
}))
61+
defer ts.Close()
62+
63+
telegram, err := NewTelegram("", "", "channel", "token")
64+
require.NoError(t, err)
65+
66+
telegram.URL = ts.URL
6267

6368
ev := testEvent()
6469
ev.Metadata["kubernetes.io/somekey"] = "some.value"
6570
err = telegram.Post(context.TODO(), ev)
6671
require.NoError(t, err)
6772
}
73+
74+
func TestTelegram_NewTelegram_IgnoresAddress(t *testing.T) {
75+
telegram, err := NewTelegram("https://api.telegram.org", "", "channel", "token")
76+
require.NoError(t, err)
77+
require.Equal(t, "https://api.telegram.org/bottoken", telegram.URL)
78+
79+
telegram2, err := NewTelegram("https://custom.example.com", "", "channel", "token")
80+
require.NoError(t, err)
81+
require.Equal(t, "https://api.telegram.org/bottoken", telegram2.URL)
82+
83+
telegram3, err := NewTelegram("", "", "channel", "token")
84+
require.NoError(t, err)
85+
require.Equal(t, "https://api.telegram.org/bottoken", telegram3.URL)
86+
}

0 commit comments

Comments
 (0)