fix(alerting): Resolve Telegram issue with bad payload when condition has " in it
				
					
				
			This commit is contained in:
		| @ -2,6 +2,7 @@ package telegram | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| @ -36,7 +37,7 @@ func (provider *AlertProvider) IsValid() bool { | |||||||
|  |  | ||||||
| // Send an alert using the provider | // Send an alert using the provider | ||||||
| func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error { | func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error { | ||||||
| 	buffer := bytes.NewBuffer([]byte(provider.buildRequestBody(endpoint, alert, result, resolved))) | 	buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved)) | ||||||
| 	apiURL := provider.APIURL | 	apiURL := provider.APIURL | ||||||
| 	if apiURL == "" { | 	if apiURL == "" { | ||||||
| 		apiURL = defaultAPIURL | 		apiURL = defaultAPIURL | ||||||
| @ -58,13 +59,19 @@ func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type Body struct { | ||||||
|  | 	ChatID    string `json:"chat_id"` | ||||||
|  | 	Text      string `json:"text"` | ||||||
|  | 	ParseMode string `json:"parse_mode"` | ||||||
|  | } | ||||||
|  |  | ||||||
| // buildRequestBody builds the request body for the provider | // buildRequestBody builds the request body for the provider | ||||||
| func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) string { | func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte { | ||||||
| 	var message, results string | 	var message, results string | ||||||
| 	if resolved { | 	if resolved { | ||||||
| 		message = fmt.Sprintf("An alert for *%s* has been resolved:\\n—\\n    _healthcheck passing successfully %d time(s) in a row_\\n—  ", endpoint.DisplayName(), alert.FailureThreshold) | 		message = fmt.Sprintf("An alert for *%s* has been resolved:\n—\n    _healthcheck passing successfully %d time(s) in a row_\n—  ", endpoint.DisplayName(), alert.FailureThreshold) | ||||||
| 	} else { | 	} else { | ||||||
| 		message = fmt.Sprintf("An alert for *%s* has been triggered:\\n—\\n    _healthcheck failed %d time(s) in a row_\\n—  ", endpoint.DisplayName(), alert.FailureThreshold) | 		message = fmt.Sprintf("An alert for *%s* has been triggered:\n—\n    _healthcheck failed %d time(s) in a row_\n—  ", endpoint.DisplayName(), alert.FailureThreshold) | ||||||
| 	} | 	} | ||||||
| 	for _, conditionResult := range result.ConditionResults { | 	for _, conditionResult := range result.ConditionResults { | ||||||
| 		var prefix string | 		var prefix string | ||||||
| @ -73,15 +80,20 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert * | |||||||
| 		} else { | 		} else { | ||||||
| 			prefix = "❌" | 			prefix = "❌" | ||||||
| 		} | 		} | ||||||
| 		results += fmt.Sprintf("%s - `%s`\\n", prefix, conditionResult.Condition) | 		results += fmt.Sprintf("%s - `%s`\n", prefix, conditionResult.Condition) | ||||||
| 	} | 	} | ||||||
| 	var text string | 	var text string | ||||||
| 	if len(alert.GetDescription()) > 0 { | 	if len(alert.GetDescription()) > 0 { | ||||||
| 		text = fmt.Sprintf("⛑ *Gatus* \\n%s \\n*Description* \\n_%s_  \\n\\n*Condition results*\\n%s", message, alert.GetDescription(), results) | 		text = fmt.Sprintf("⛑ *Gatus* \n%s \n*Description* \n_%s_  \n\n*Condition results*\n%s", message, alert.GetDescription(), results) | ||||||
| 	} else { | 	} else { | ||||||
| 		text = fmt.Sprintf("⛑ *Gatus* \\n%s \\n*Condition results*\\n%s", message, results) | 		text = fmt.Sprintf("⛑ *Gatus* \n%s \n*Condition results*\n%s", message, results) | ||||||
| 	} | 	} | ||||||
| 	return fmt.Sprintf(`{"chat_id": "%s", "text": "%s", "parse_mode": "MARKDOWN"}`, provider.ID, text) | 	body, _ := json.Marshal(Body{ | ||||||
|  | 		ChatID:    provider.ID, | ||||||
|  | 		Text:      text, | ||||||
|  | 		ParseMode: "MARKDOWN", | ||||||
|  | 	}) | ||||||
|  | 	return body | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetDefaultAlert returns the provider's default alert configuration | // GetDefaultAlert returns the provider's default alert configuration | ||||||
|  | |||||||
| @ -124,14 +124,14 @@ func TestAlertProvider_buildRequestBody(t *testing.T) { | |||||||
| 			Provider:     AlertProvider{ID: "123"}, | 			Provider:     AlertProvider{ID: "123"}, | ||||||
| 			Alert:        alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, | 			Alert:        alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, | ||||||
| 			Resolved:     false, | 			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\"}", | 			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\"}", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			Name:         "resolved", | 			Name:         "resolved", | ||||||
| 			Provider:     AlertProvider{ID: "123"}, | 			Provider:     AlertProvider{ID: "123"}, | ||||||
| 			Alert:        alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, | 			Alert:        alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, | ||||||
| 			Resolved:     true, | 			Resolved:     true, | ||||||
| 			ExpectedBody: "{\"chat_id\": \"123\", \"text\": \"⛑ *Gatus* \\nAn alert for *endpoint-name* has been resolved:\\n—\\n    _healthcheck passing successfully 3 time(s) in a row_\\n—   \\n*Description* \\n_description-2_  \\n\\n*Condition results*\\n✅ - `[CONNECTED] == true`\\n✅ - `[STATUS] == 200`\\n\", \"parse_mode\": \"MARKDOWN\"}", | 			ExpectedBody: "{\"chat_id\":\"123\",\"text\":\"⛑ *Gatus* \\nAn alert for *endpoint-name* has been resolved:\\n—\\n    _healthcheck passing successfully 3 time(s) in a row_\\n—   \\n*Description* \\n_description-2_  \\n\\n*Condition results*\\n✅ - `[CONNECTED] == true`\\n✅ - `[STATUS] == 200`\\n\",\"parse_mode\":\"MARKDOWN\"}", | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	for _, scenario := range scenarios { | 	for _, scenario := range scenarios { | ||||||
| @ -147,11 +147,11 @@ func TestAlertProvider_buildRequestBody(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 				scenario.Resolved, | 				scenario.Resolved, | ||||||
| 			) | 			) | ||||||
| 			if body != scenario.ExpectedBody { | 			if string(body) != scenario.ExpectedBody { | ||||||
| 				t.Errorf("expected %s, got %s", scenario.ExpectedBody, body) | 				t.Errorf("expected:\n%s\ngot:\n%s", scenario.ExpectedBody, body) | ||||||
| 			} | 			} | ||||||
| 			out := make(map[string]interface{}) | 			out := make(map[string]interface{}) | ||||||
| 			if err := json.Unmarshal([]byte(body), &out); err != nil { | 			if err := json.Unmarshal(body, &out); err != nil { | ||||||
| 				t.Error("expected body to be valid JSON, got error:", err.Error()) | 				t.Error("expected body to be valid JSON, got error:", err.Error()) | ||||||
| 			} | 			} | ||||||
| 		}) | 		}) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user