diff --git a/README.md b/README.md
index 5d2a436e..8004653d 100644
--- a/README.md
+++ b/README.md
@@ -279,7 +279,7 @@ This allows you to monitor anything you want, even when what you want to check l
For instance:
- You can create your own agent that lives in a private network and pushes the status of your services to a publicly-exposed Gatus instance
-- You can monitor services that are not supported by Gatus
+- You can monitor services that are not supported by Gatus
- You can implement your own monitoring system while using Gatus as the dashboard
| Parameter | Description | Default |
@@ -1185,14 +1185,18 @@ Here's an example of what the notifications look like:
#### Configuring Telegram alerts
-| Parameter | Description | Default |
-|:----------------------------------|:-------------------------------------------------------------------------------------------|:---------------------------|
-| `alerting.telegram` | Configuration for alerts of type `telegram` | `{}` |
-| `alerting.telegram.token` | Telegram Bot Token | Required `""` |
-| `alerting.telegram.id` | Telegram User ID | Required `""` |
-| `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 |
+| Parameter | Description | Default |
+|:--------------------------------------|:-------------------------------------------------------------------------------------------|:---------------------------|
+| `alerting.telegram` | Configuration for alerts of type `telegram` | `{}` |
+| `alerting.telegram.token` | Telegram Bot Token | Required `""` |
+| `alerting.telegram.id` | Telegram User ID | Required `""` |
+| `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 |
+| `alerting.telegram.overrides` | List of overrides that may be prioritized over the default configuration | `[]` |
+| `alerting.telegram.overrides[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` |
+| `alerting.telegram.overrides[].token` | Telegram Bot Token for override default value | `""` |
+| `alerting.telegram.overrides[].id` | Telegram User ID for override default value | `""` |
```yaml
alerting:
diff --git a/alerting/provider/telegram/telegram.go b/alerting/provider/telegram/telegram.go
index f5950a17..ecfd700b 100644
--- a/alerting/provider/telegram/telegram.go
+++ b/alerting/provider/telegram/telegram.go
@@ -25,6 +25,16 @@ type AlertProvider struct {
// DefaultAlert is the default alert configuration to use for endpoints with an alert of the appropriate type
DefaultAlert *alert.Alert `yaml:"default-alert,omitempty"`
+
+ // Overrides is a list of Overrid that may be prioritized over the default configuration
+ Overrides []*Override `yaml:"overrides,omitempty"`
+}
+
+// Override is a configuration that may be prioritized over the default configuration
+type Override struct {
+ group string `yaml:"group"`
+ token string `yaml:"token"`
+ id string `yaml:"id"`
}
// IsValid returns whether the provider's configuration is valid
@@ -32,6 +42,18 @@ func (provider *AlertProvider) IsValid() bool {
if provider.ClientConfig == nil {
provider.ClientConfig = client.GetDefaultConfig()
}
+
+ registerGroups := make(map[string]bool)
+ for _, override := range provider.Overrides {
+ if len(override.group) == 0 {
+ return false
+ }
+ if _, ok := registerGroups[override.group]; ok {
+ return false
+ }
+ registerGroups[override.group] = true
+ }
+
return len(provider.Token) > 0 && len(provider.ID) > 0
}
@@ -42,7 +64,7 @@ func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, r
if apiURL == "" {
apiURL = defaultAPIURL
}
- request, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/bot%s/sendMessage", apiURL, provider.Token), buffer)
+ request, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/bot%s/sendMessage", apiURL, provider.getTokenForGroup(ep.Group)), buffer)
if err != nil {
return err
}
@@ -59,6 +81,15 @@ func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, r
return err
}
+func (provider *AlertProvider) getTokenForGroup(group string) string {
+ for _, override := range provider.Overrides {
+ if override.group == group && len(override.token) > 0 {
+ return override.token
+ }
+ }
+ return provider.Token
+}
+
type Body struct {
ChatID string `json:"chat_id"`
Text string `json:"text"`
@@ -93,13 +124,22 @@ func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *al
text = fmt.Sprintf("⛑ *Gatus* \n%s%s", message, formattedConditionResults)
}
bodyAsJSON, _ := json.Marshal(Body{
- ChatID: provider.ID,
+ ChatID: provider.getIDForGroup(ep.Group),
Text: text,
ParseMode: "MARKDOWN",
})
return bodyAsJSON
}
+func (provider *AlertProvider) getIDForGroup(group string) string {
+ for _, override := range provider.Overrides {
+ if override.group == group && len(override.id) > 0 {
+ return override.id
+ }
+ }
+ return provider.ID
+}
+
// GetDefaultAlert returns the provider's default alert configuration
func (provider *AlertProvider) GetDefaultAlert() *alert.Alert {
return provider.DefaultAlert
diff --git a/alerting/provider/telegram/telegram_test.go b/alerting/provider/telegram/telegram_test.go
index 6c9b9109..c1f201cb 100644
--- a/alerting/provider/telegram/telegram_test.go
+++ b/alerting/provider/telegram/telegram_test.go
@@ -11,7 +11,7 @@ import (
"github.com/TwiN/gatus/v5/test"
)
-func TestAlertProvider_IsValid(t *testing.T) {
+func TestAlertDefaultProvider_IsValid(t *testing.T) {
t.Run("invalid-provider", func(t *testing.T) {
invalidProvider := AlertProvider{Token: "", ID: ""}
if invalidProvider.IsValid() {
@@ -32,6 +32,69 @@ func TestAlertProvider_IsValid(t *testing.T) {
})
}
+func TestAlertProvider_IsValidWithOverrides(t *testing.T) {
+ t.Run("invalid-provider-override-nonexist-group", func(t *testing.T) {
+ invalidProvider := AlertProvider{Token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11", ID: "12345678", Overrides: []*Override{{token: "token", id: "id"}}}
+ if invalidProvider.IsValid() {
+ t.Error("provider shouldn't have been valid")
+ }
+ })
+ t.Run("invalid-provider-override-duplicate-group", func(t *testing.T) {
+ invalidProvider := AlertProvider{Token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11", ID: "12345678", Overrides: []*Override{{group: "group1", token: "token", id: "id"}, {group: "group1", id: "id2"}}}
+ if invalidProvider.IsValid() {
+ t.Error("provider shouldn't have been valid")
+ }
+ })
+ t.Run("valid-provider", func(t *testing.T) {
+ validProvider := AlertProvider{Token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11", ID: "12345678", Overrides: []*Override{{group: "group", token: "token", id: "id"}}}
+ if validProvider.ClientConfig != nil {
+ t.Error("provider client config should have been nil prior to IsValid() being executed")
+ }
+ if !validProvider.IsValid() {
+ t.Error("provider should've been valid")
+ }
+ if validProvider.ClientConfig == nil {
+ t.Error("provider client config should have been set after IsValid() was executed")
+ }
+ })
+}
+
+func TestAlertProvider_getTokenAndIDForGroup(t *testing.T) {
+ t.Run("get-token-with-override", func(t *testing.T) {
+ provider := AlertProvider{Token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11", ID: "12345678", Overrides: []*Override{{group: "group", token: "overrideToken", id: "overrideID"}}}
+ token := provider.getTokenForGroup("group")
+ if token != "overrideToken" {
+ t.Error("token should have been 'overrideToken'")
+ }
+ id := provider.getIDForGroup("group")
+ if id != "overrideID" {
+ t.Error("id should have been 'overrideID'")
+ }
+ })
+ t.Run("get-default-token-with-overridden-id", func(t *testing.T) {
+ provider := AlertProvider{Token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11", ID: "12345678", Overrides: []*Override{{group: "group", id: "overrideID"}}}
+ token := provider.getTokenForGroup("group")
+ if token != provider.Token {
+ t.Error("token should have been the default token")
+ }
+ id := provider.getIDForGroup("group")
+ if id != "overrideID" {
+ t.Error("id should have been 'overrideID'")
+ }
+ })
+ t.Run("get-default-token-with-overridden-token", func(t *testing.T) {
+ provider := AlertProvider{Token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11", ID: "12345678", Overrides: []*Override{{group: "group", token: "overrideToken"}}}
+ token := provider.getTokenForGroup("group")
+ if token != "overrideToken" {
+ t.Error("token should have been 'overrideToken'")
+ }
+ id := provider.getIDForGroup("group")
+ if id != provider.ID {
+ t.Error("id should have been the default id")
+ }
+ })
+}
+
func TestAlertProvider_Send(t *testing.T) {
defer client.InjectHTTPClient(nil)
firstDescription := "description-1"