Repository: favonia/cloudflare-ddns (go)

Issue:
Sometimes the updater sends the message "OK" when failing
Following up on #615, I just had the following error in the docker logs:
```
🔔 Successfully pinged Uptime Kuma
⏰ Checking the IP addresses in about 5m0s . . .
😞 Failed to send HTTP(S) request to "https://1.1.1.1/cdn-cgi/trace": context deadline exceeded
😞 Failed to detect the IPv4 address
🔔 Successfully pinged Uptime Kuma
⏰ Checking the IP addresses in about 4m55s . . .
🌐 Detected the IPv4 address: 71.x.y.86
🤷 The A records of "ddns.domain.com" are already up to date
🔔 Successfully pinged Uptime Kuma
⏰ Checking the IP addresses in about 5m0s . . .
```
Which is totally fine (I rebooted my router, so the container was running, but it couldn't reach the internet for that one interval).
However this is what Uptime Kuma showed:
![image](https://github.com/favonia/cloudflare-ddns/assets/90044149/828f814c-b1b3-4577-84b5-fe4db2e7504a)
(So it sent an OK instead of the actual issue of "context deadline exceeded" (or request timed out, or whatever makes sense as error message))

Pull request description:
fix(monitor): a more powerful hack for quirks of Uptime Kuma
Close #648.

Patch:
diff --git a/cmd/ddns/ddns.go b/cmd/ddns/ddns.go
index 637f678..4625b9d 100644
--- a/cmd/ddns/ddns.go
+++ b/cmd/ddns/ddns.go
@@ -56,9 +56,9 @@ func initConfig(ctx context.Context, ppfmt pp.PP) (*config.Config, setter.Setter
 
 func stopUpdating(ctx context.Context, ppfmt pp.PP, c *config.Config, s setter.Setter) {
 	if c.DeleteOnStop {
-		resp := updater.DeleteIPs(ctx, ppfmt, c, s)
-		monitor.LogMessageAll(ctx, ppfmt, c.Monitors, resp)
-		notifier.SendMessageAll(ctx, ppfmt, c.Notifiers, resp)
+		msg := updater.DeleteIPs(ctx, ppfmt, c, s)
+		monitor.LogMessageAll(ctx, ppfmt, c.Monitors, msg)
+		notifier.SendMessageAll(ctx, ppfmt, c.Notifiers, msg)
 	}
 }
 
@@ -128,9 +128,9 @@ func realMain() int { //nolint:funlen
 		if first && !c.UpdateOnStart {
 			monitor.SuccessAll(ctx, ppfmt, c.Monitors, "Started (no action)")
 		} else {
-			resp := updater.UpdateIPs(ctxWithSignals, ppfmt, c, s)
-			monitor.PingMessageAll(ctx, ppfmt, c.Monitors, resp)
-			notifier.SendMessageAll(ctx, ppfmt, c.Notifiers, resp)
+			msg := updater.UpdateIPs(ctxWithSignals, ppfmt, c, s)
+			monitor.PingMessageAll(ctx, ppfmt, c.Monitors, msg)
+			notifier.SendMessageAll(ctx, ppfmt, c.Notifiers, msg)
 		}
 
 		// Check if cron was disabled
diff --git a/internal/monitor/uptimekuma.go b/internal/monitor/uptimekuma.go
index 51e5bef..c4fefe1 100644
--- a/internal/monitor/uptimekuma.go
+++ b/internal/monitor/uptimekuma.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"net/url"
 	"slices"
+	"strings"
 	"time"
 
 	"github.com/google/go-querystring/query"
@@ -81,7 +82,7 @@ func NewUptimeKuma(ppfmt pp.PP, rawURL string) (*UptimeKuma, bool) {
 
 			default: // problematic case
 				ppfmt.Warningf(pp.EmojiUserError,
-					`The Uptime Kuma URL (redacted) contains an unexpected query %s=... and it will not be used`,
+					`The Uptime Kuma URL (redacted) contains an unexpected query %s=... and it will be ignored`,
 					k)
 			}
 		}
@@ -165,7 +166,8 @@ func (h *UptimeKuma) Start(_ctx context.Context, _ppfmt pp.PP, _message string)
 
 // Failure pings the server with status=down.
 func (h *UptimeKuma) Failure(ctx context.Context, ppfmt pp.PP, message string) bool {
-	if len(message) == 0 {
+	message = strings.TrimSpace(message)
+	if message == "" {
 		// If we do not send a non-empty message to Uptime Kuma, it seems to
 		// either keep the previous message (even if it was for success) or
 		// assume the message is "OK". Either is bad.


Test patch:
diff --git a/internal/config/env_monitor_test.go b/internal/config/env_monitor_test.go
index 3d5ea28..e1d6ac5 100644
--- a/internal/config/env_monitor_test.go
+++ b/internal/config/env_monitor_test.go
@@ -169,7 +169,7 @@ func TestReadAndAppendUptimeKumaURL(t *testing.T) {
 			true,
 			func(m *mocks.MockPP) {
 				m.EXPECT().Warningf(pp.EmojiUserError,
-					`The Uptime Kuma URL (redacted) contains an unexpected query %s=... and it will not be used`,
+					`The Uptime Kuma URL (redacted) contains an unexpected query %s=... and it will be ignored`,
 					"hello")
 			},
 		},
diff --git a/internal/monitor/uptimekuma_test.go b/internal/monitor/uptimekuma_test.go
index e813d6e..fde3b1b 100644
--- a/internal/monitor/uptimekuma_test.go
+++ b/internal/monitor/uptimekuma_test.go
@@ -36,7 +36,7 @@ func TestNewUptimeKuma(t *testing.T) {
 		"unexpected": {
 			"https://user:pass@host/path?random=", true,
 			func(m *mocks.MockPP) {
-				m.EXPECT().Warningf(pp.EmojiUserError, "The Uptime Kuma URL (redacted) contains an unexpected query %s=... and it will not be used", "random") //nolint:lll
+				m.EXPECT().Warningf(pp.EmojiUserError, "The Uptime Kuma URL (redacted) contains an unexpected query %s=... and it will be ignored", "random") //nolint:lll
 			},
 		},
 		"ill-formed-query": {