From 00419a4b4a1322417d681ff606d88abc6bedb72e Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 11 Jul 2025 20:55:42 +0300 Subject: [PATCH] feat(alerting): Support sending messages to Telegram topics in group (#928) * feat(alerting): Added the ability to send messages to Telegram topics in groups. * feat(alerting): Added the ability to send messages to Telegram topics in groups. fix tests * feat(alerting): Added the ability to send messages to Telegram topics in groups. Rename TopicId to TopicID * feat(alerting): Added the ability to send messages to Telegram topics in groups. Fixed description for alerting.telegram.topic-id in README.md --------- Co-authored-by: TwiN --- README.md | 2 ++ alerting/provider/telegram/telegram.go | 12 +++++++++--- alerting/provider/telegram/telegram_test.go | 7 +++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b538007f..7be1e170 100644 --- a/README.md +++ b/README.md @@ -1551,6 +1551,7 @@ Here's an example of what the notifications look like: | `alerting.telegram` | Configuration for alerts of type `telegram` | `{}` | | `alerting.telegram.token` | Telegram Bot Token | Required `""` | | `alerting.telegram.id` | Telegram User ID | Required `""` | +| `alerting.telegram.topic-id` | Telegram Topic ID in a group corresponds to `message_thread_id` in the Telegram API | `""` | | `alerting.telegram.api-url` | Telegram API URL | `https://api.telegram.org` | | `alerting.telegram.client` | Client configuration.
See [Client configuration](#client-configuration). | `{}` | | `alerting.telegram.default-alert` | Default alert configuration.
See [Setting a default alert](#setting-a-default-alert) | N/A | @@ -1563,6 +1564,7 @@ alerting: telegram: token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11" id: "0123456789" + topic-id: "7" endpoints: - name: website diff --git a/alerting/provider/telegram/telegram.go b/alerting/provider/telegram/telegram.go index b2624c7c..11a8d290 100644 --- a/alerting/provider/telegram/telegram.go +++ b/alerting/provider/telegram/telegram.go @@ -23,9 +23,10 @@ var ( ) type Config struct { - Token string `yaml:"token"` - ID string `yaml:"id"` - ApiUrl string `yaml:"api-url"` + Token string `yaml:"token"` + ID string `yaml:"id"` + TopicID string `yaml:"topic-id,omitempty"` + ApiUrl string `yaml:"api-url"` ClientConfig *client.Config `yaml:"client,omitempty"` } @@ -53,6 +54,9 @@ func (cfg *Config) Merge(override *Config) { if len(override.ID) > 0 { cfg.ID = override.ID } + if len(override.TopicID) > 0 { + cfg.TopicID = override.TopicID + } if len(override.ApiUrl) > 0 { cfg.ApiUrl = override.ApiUrl } @@ -117,6 +121,7 @@ type Body struct { ChatID string `json:"chat_id"` Text string `json:"text"` ParseMode string `json:"parse_mode"` + TopicID string `json:"message_thread_id,omitempty"` } // buildRequestBody builds the request body for the provider @@ -150,6 +155,7 @@ func (provider *AlertProvider) buildRequestBody(cfg *Config, ep *endpoint.Endpoi ChatID: cfg.ID, Text: text, ParseMode: "MARKDOWN", + TopicID: cfg.TopicID, }) return bodyAsJSON } diff --git a/alerting/provider/telegram/telegram_test.go b/alerting/provider/telegram/telegram_test.go index 2d4fd6ab..a680c9a8 100644 --- a/alerting/provider/telegram/telegram_test.go +++ b/alerting/provider/telegram/telegram_test.go @@ -154,6 +154,13 @@ func TestAlertProvider_buildRequestBody(t *testing.T) { Resolved: true, ExpectedBody: "{\"chat_id\":\"123\",\"text\":\"⛑ *Gatus* \\nAn alert for *endpoint-name* has been resolved:\\n—\\n _healthcheck passing successfully 5 time(s) in a row_\\n— \\n*Description* \\n_description-2_ \\n\",\"parse_mode\":\"MARKDOWN\"}", }, + { + Name: "send to topic", + Provider: AlertProvider{DefaultConfig: Config{ID: "123", TopicID: "7"}}, + Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, + Resolved: false, + ExpectedBody: "{\"chat_id\":\"123\",\"text\":\"⛑ *Gatus* \\nAn alert for *endpoint-name* has been triggered:\\n—\\n _healthcheck failed 3 time(s) in a row_\\n— \\n*Description* \\n_description-1_ \\n\\n*Condition results*\\n❌ - `[CONNECTED] == true`\\n❌ - `[STATUS] == 200`\\n\",\"parse_mode\":\"MARKDOWN\",\"message_thread_id\":\"7\"}", + }, } for _, scenario := range scenarios { t.Run(scenario.Name, func(t *testing.T) {