Repository: favonia/cloudflare-ddns
Pull request #631 (2023-11-04 18:01:51)

fix(updater): triage all monitor messages based on success/failure

sonarcloud[bot]: SonarCloud Quality Gate failed.&nbsp; &nbsp; [![Quality Gate failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonarcloud.io/dashboard?id=favonia_cloudflare-ddns&pullRequest=631)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [1 Code Smell](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631) No Coverage information  
[![3.2%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/5-16px.png '3.2%')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list) [3.2% Duplication](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list)



![idea](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/light_bulb-16px.png 'idea') Catch issues before they fail your Quality Gate with our IDE extension ![sonarlint](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/sonarlint-16px.png 'sonarlint') [SonarLint](https://www.sonarsource.com/products/sonarlint/features/connected-mode/?referrer=sonarcloud-welcome)
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/favonia/cloudflare-ddns/pull/631?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=favonia) Report
> Merging [#631](https://app.codecov.io/gh/favonia/cloudflare-ddns/pull/631?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=favonia) (7805b3f) into [main](https://app.codecov.io/gh/favonia/cloudflare-ddns/commit/1d51ef182800c7e7ac1ddeb30ed18026aa4631d0?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=favonia) (1d51ef1) will **decrease** coverage by `0.12%`.
> The diff coverage is `91.66%`.

```diff
@@            Coverage Diff             @@
##             main     #631      +/-   ##
==========================================
- Coverage   88.45%   88.33%   -0.12%     
==========================================
  Files          45       45              
  Lines        2330     2341      +11     
==========================================
+ Hits         2061     2068       +7     
- Misses        259      262       +3     
- Partials       10       11       +1     
```

| [Flag](https://app.codecov.io/gh/favonia/cloudflare-ddns/pull/631/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=favonia) | Coverage Δ | |
|---|---|---|
| [unittests](https://app.codecov.io/gh/favonia/cloudflare-ddns/pull/631/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=favonia) | `88.33% <91.66%> (-0.12%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=favonia#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Files](https://app.codecov.io/gh/favonia/cloudflare-ddns/pull/631?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=favonia) | Coverage Δ | |
|---|---|---|
| [internal/updater/updater.go](https://app.codecov.io/gh/favonia/cloudflare-ddns/pull/631?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=favonia#diff-aW50ZXJuYWwvdXBkYXRlci91cGRhdGVyLmdv) | `96.33% <91.66%> (-3.67%)` | :arrow_down: |

:mega: Codecov offers a browser extension for seamless coverage viewing on GitHub. Try it in [Chrome](https://chrome.google.com/webstore/detail/codecov/gedikamndpbemklijjkncpnolildpbgo) or [Firefox](https://addons.mozilla.org/en-US/firefox/addon/codecov/) today!

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=favonia_cloudflare-ddns&pullRequest=631)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=favonia_cloudflare-ddns&pullRequest=631)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=favonia_cloudflare-ddns&pullRequest=631)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=favonia_cloudflare-ddns&pullRequest=631)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=favonia_cloudflare-ddns&pullRequest=631)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=favonia_cloudflare-ddns&pullRequest=631&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=favonia_cloudflare-ddns&pullRequest=631&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/go.mod b/go.mod
index 20bed45..fa4db93 100644
--- a/go.mod
+++ b/go.mod
@@ -19,9 +19,9 @@ require (
 	github.com/goccy/go-json v0.10.2 // indirect
 	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	golang.org/x/sync v0.3.0 // indirect
-	golang.org/x/text v0.13.0 // indirect
-	golang.org/x/time v0.3.0 // indirect
+	golang.org/x/sync v0.5.0 // indirect
+	golang.org/x/text v0.14.0 // indirect
+	golang.org/x/time v0.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	kernel.org/pub/linux/libs/security/libcap/psx v1.2.69 // indirect
 )
diff --git a/go.sum b/go.sum
index aeae396..68a6eb2 100644
--- a/go.sum
+++ b/go.sum
@@ -43,14 +43,14 @@ go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
 go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
 golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
 golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
+golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
-golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
+golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
diff --git a/internal/config/network_probe.go b/internal/config/network_probe.go
index 87f3dec..9a3c50f 100644
--- a/internal/config/network_probe.go
+++ b/internal/config/network_probe.go
@@ -11,7 +11,7 @@ import (
 
 // ProbeURL quickly checks whether one can send a HEAD request to the url.
 func ProbeURL(ctx context.Context, url string) bool {
-	ctx, cancel := context.WithDeadline(ctx, time.Now().Add(time.Second))
+	ctx, cancel := context.WithTimeout(ctx, time.Second)
 	defer cancel()
 
 	req, err := http.NewRequestWithContext(ctx, http.MethodHead, url, nil)
diff --git a/internal/updater/updater.go b/internal/updater/updater.go
index 5ede394..002d5a4 100644
--- a/internal/updater/updater.go
+++ b/internal/updater/updater.go
@@ -4,6 +4,7 @@ package updater
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"net/netip"
 	"strings"
@@ -15,6 +16,25 @@ import (
 	"github.com/favonia/cloudflare-ddns/internal/setter"
 )
 
+// ShouldDisplayHints determines whether help messages should be displayed.
+// The help messages are to help beginners detect possible misconfiguration.
+// These messages should be displayed at most once, and thus the value of this map
+// will be changed to false after displaying the help messages.
+//
+//nolint:gochecknoglobals
+var ShouldDisplayHints = map[string]bool{
+	"detect-ip4-fail": true,
+	"detect-ip6-fail": true,
+	"update-timeout":  true,
+}
+
+func getHintIDForDetection(ipNet ipnet.Type) string {
+	return map[ipnet.Type]string{
+		ipnet.IP4: "detect-ip4-fail",
+		ipnet.IP6: "detect-ip6-fail",
+	}[ipNet]
+}
+
 func getProxied(ppfmt pp.PP, c *config.Config, domain domain.Domain) bool {
 	if proxied, ok := c.Proxied[domain]; ok {
 		return proxied
@@ -27,32 +47,43 @@ func getProxied(ppfmt pp.PP, c *config.Config, domain domain.Domain) bool {
 	return false
 }
 
+var errSettingTimeout = errors.New("setting timeout")
+
 // setIP extracts relevant settings from the configuration and calls [setter.Setter.Set] with timeout.
 // ip must be non-zero.
 func setIP(ctx context.Context, ppfmt pp.PP,
 	c *config.Config, s setter.Setter, ipNet ipnet.Type, ip netip.Addr,
-) (bool, string) {
+) (bool, []string) {
 	allOk := true
-	var msgs []string
+
+	// [msgs[false]] collects all the error messages and [msgs[true]] collects all the success messages.
+	msgs := map[bool][]string{}
 
 	for _, domain := range c.Domains[ipNet] {
-		ctx, cancel := context.WithTimeout(ctx, c.UpdateTimeout)
+		ctx, cancel := context.WithTimeoutCause(ctx, c.UpdateTimeout, errSettingTimeout)
 		defer cancel()
 
 		ok, msg := s.Set(ctx, ppfmt, domain, ipNet, ip, c.TTL, getProxied(ppfmt, c, domain))
 		allOk = allOk && ok
 		if msg != "" {
-			msgs = append(msgs, msg)
+			msgs[ok] = append(msgs[ok], msg)
+		}
+
+		if !ok && ShouldDisplayHints["update-timeout"] && errors.Is(context.Cause(ctx), errSettingTimeout) {
+			ppfmt.Infof(pp.EmojiConfig, "If your network is working but with high latency, consider increasing the value of UPDATE_TIMEOUT") //nolint:lll
+			ShouldDisplayHints["update-timeout"] = false
 		}
 	}
 
-	return allOk, strings.Join(msgs, "\n")
+	return allOk, msgs[allOk]
 }
 
 // clearIP extracts relevant settings from the configuration and calls [setter.Setter.Clear] with a deadline.
-func clearIP(ctx context.Context, ppfmt pp.PP, c *config.Config, s setter.Setter, ipNet ipnet.Type) (bool, string) {
+func clearIP(ctx context.Context, ppfmt pp.PP, c *config.Config, s setter.Setter, ipNet ipnet.Type) (bool, []string) {
 	allOk := true
-	var msgs []string
+
+	// [msgs[false]] collects all the error messages and [msgs[true]] collects all the success messages.
+	msgs := map[bool][]string{}
 
 	for _, domain := range c.Domains[ipNet] {
 		ctx, cancel := context.WithTimeout(ctx, c.UpdateTimeout)
@@ -61,38 +92,28 @@ func clearIP(ctx context.Context, ppfmt pp.PP, c *config.Config, s setter.Setter
 		ok, msg := s.Clear(ctx, ppfmt, domain, ipNet)
 		allOk = allOk && ok
 		if msg != "" {
-			msgs = append(msgs, msg)
+			msgs[ok] = append(msgs[ok], msg)
 		}
 	}
 
-	return allOk, strings.Join(msgs, "\n")
-}
-
-// ShouldDisplayHelpMessages determines whether help messages should be displayed.
-// The help messages are to help beginners detect possible misconfiguration.
-// These messages should be displayed at most once, and thus the value of this map
-// will be changed to false after displaying the help messages.
-//
-//nolint:gochecknoglobals
-var ShouldDisplayHelpMessages = map[ipnet.Type]bool{
-	ipnet.IP4: true,
-	ipnet.IP6: true,
+	return allOk, msgs[allOk]
 }
 
 func detectIP(ctx context.Context, ppfmt pp.PP,
 	c *config.Config, ipNet ipnet.Type, use1001 bool,
-) (netip.Addr, bool, string) {
+) (netip.Addr, bool, []string) {
 	ctx, cancel := context.WithTimeout(ctx, c.DetectionTimeout)
 	defer cancel()
 
-	msg := ""
+	var msgs []string
 	ip, ok := c.Provider[ipNet].GetIP(ctx, ppfmt, ipNet, use1001)
 	if ok {
 		ppfmt.Infof(pp.EmojiInternet, "Detected the %s address: %v", ipNet.Describe(), ip)
 	} else {
-		msg = fmt.Sprintf("Failed to detect the %s address", ipNet.Describe())
+		msg := fmt.Sprintf("Failed to detect the %s address", ipNet.Describe())
+		msgs = append(msgs, msg)
 		ppfmt.Errorf(pp.EmojiError, "%s", msg)
-		if ShouldDisplayHelpMessages[ipNet] {
+		if ShouldDisplayHints[getHintIDForDetection(ipNet)] {
 			switch ipNet {
 			case ipnet.IP6:
 				ppfmt.Infof(pp.EmojiConfig, "If you are using Docker or Kubernetes, IPv6 often requires additional setups")     //nolint:lll
@@ -103,8 +124,8 @@ func detectIP(ctx context.Context, ppfmt pp.PP,
 			}
 		}
 	}
-	ShouldDisplayHelpMessages[ipNet] = false
-	return ip, ok, msg
+	ShouldDisplayHints[getHintIDForDetection(ipNet)] = false
+	return ip, ok, msgs
 }
 
 // UpdateIPs detect IP addresses and update DNS records of managed domains.
@@ -117,9 +138,7 @@ func UpdateIPs(ctx context.Context, ppfmt pp.PP, c *config.Config, s setter.Sett
 	for _, ipNet := range [...]ipnet.Type{ipnet.IP4, ipnet.IP6} {
 		if c.Provider[ipNet] != nil {
 			ip, ok, msg := detectIP(ctx, ppfmt, c, ipNet, c.Use1001)
-			if len(msg) != 0 {
-				msgs[ok] = append(msgs[ok], msg)
-			}
+			msgs[ok] = append(msgs[ok], msg...)
 			if !ok {
 				// We can't detect the new IP address. It's probably better to leave existing IP addresses alone.
 				allOk = false
@@ -127,9 +146,7 @@ func UpdateIPs(ctx context.Context, ppfmt pp.PP, c *config.Config, s setter.Sett
 			}
 
 			ok, msg = setIP(ctx, ppfmt, c, s, ipNet, ip)
-			if len(msg) != 0 {
-				msgs[ok] = append(msgs[ok], msg)
-			}
+			msgs[ok] = append(msgs[ok], msg...)
 			allOk = allOk && ok
 		}
 	}
@@ -146,17 +163,17 @@ func UpdateIPs(ctx context.Context, ppfmt pp.PP, c *config.Config, s setter.Sett
 // ClearIPs removes all DNS records of managed domains.
 func ClearIPs(ctx context.Context, ppfmt pp.PP, c *config.Config, s setter.Setter) (bool, string) {
 	allOk := true
-	var msgs []string
+
+	// [msgs[false]] collects all the error messages and [msgs[true]] collects all the success messages.
+	msgs := map[bool][]string{}
 
 	for _, ipNet := range [...]ipnet.Type{ipnet.IP4, ipnet.IP6} {
 		if c.Provider[ipNet] != nil {
 			ok, msg := clearIP(ctx, ppfmt, c, s, ipNet)
 			allOk = allOk && ok
-			if msg != "" {
-				msgs = append(msgs, msg)
-			}
+			msgs[ok] = append(msgs[ok], msg...)
 		}
 	}
 
-	return allOk, strings.Join(msgs, "\n")
+	return allOk, strings.Join(msgs[allOk], "\n")
 }


Test patch:
diff --git a/internal/updater/updater_test.go b/internal/updater/updater_test.go
index 9b40691..cf371b9 100644
--- a/internal/updater/updater_test.go
+++ b/internal/updater/updater_test.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"net/netip"
 	"testing"
+	"time"
 
 	"github.com/stretchr/testify/require"
 	"go.uber.org/mock/gomock"
@@ -17,6 +18,13 @@ import (
 	"github.com/favonia/cloudflare-ddns/internal/updater"
 )
 
+//nolint:gochecknoglobals
+var allHints = map[string]bool{
+	"detect-ip4-fail": true,
+	"detect-ip6-fail": true,
+	"update-timeout":  true,
+}
+
 //nolint:funlen,paralleltest // updater.IPv6MessageDisplayed is a global variable
 func TestUpdateIPs(t *testing.T) {
 	domain4 := domain.FQDN("ip4.hello")
@@ -51,117 +59,108 @@ func TestUpdateIPs(t *testing.T) {
 	proxiedBoth := mockproxied{domain4: true, domain6: true}
 
 	for name, tc := range map[string]struct {
-		ttl                       api.TTL
-		proxied                   mockproxied
-		ok                        bool
-		msg                       string
-		ShouldDisplayHelpMessages map[ipnet.Type]bool
-		prepareMockPP             func(m *mocks.MockPP)
-		prepareMockProvider       mockproviders
-		prepareMockSetter         func(ppfmt pp.PP, m *mocks.MockSetter)
+		proxied             mockproxied
+		ok                  bool
+		msg                 string
+		ShouldDisplayHints  map[string]bool
+		prepareMockPP       func(m *mocks.MockPP)
+		prepareMockProvider mockproviders
+		prepareMockSetter   func(ppfmt pp.PP, m *mocks.MockSetter)
 	}{
 		"none": {
-			api.TTLAuto, proxiedBoth, true, ``, map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true}, nil, mockproviders{}, nil,
+			proxiedBoth, true, ``, allHints, nil, mockproviders{}, nil,
 		},
 		"ip4only": {
-			api.TTLAuto,
 			proxiedNone,
 			true,
 			"",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			pp4only,
 			mockproviders{ipnet.IP4: provider4},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTL(1), false).Return(true, "")
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).Return(true, "")
 			},
 		},
 		"ip4only/setfail": {
-			api.TTLAuto,
 			proxiedBoth,
 			false,
 			"error",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			pp4only,
 			mockproviders{ipnet.IP4: provider4},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTL(1), true).Return(false, "error") //nolint:lll
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, true).Return(false, "error") //nolint:lll
 			},
 		},
 		"ip6only": {
-			api.TTLAuto,
 			proxiedNone,
 			true,
 			"ok",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			pp6only,
 			mockproviders{ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTL(1), false).Return(true, "ok")
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).Return(true, "ok")
 			},
 		},
 		"ip6only/setfail": {
-			api.TTLAuto,
 			proxiedBoth,
 			false,
 			"bad",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			pp6only,
 			mockproviders{ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTL(1), true).Return(false, "bad")
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, true).Return(false, "bad") //nolint:lll
 			},
 		},
 		"both": {
-			api.TTLAuto,
 			proxiedNone,
 			true,
 			"",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			ppBoth,
 			mockproviders{ipnet.IP4: provider4, ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
 				gomock.InOrder(
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTL(1), false).Return(true, ""),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTL(1), false).Return(true, ""),
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).Return(true, ""),
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).Return(true, ""),
 				)
 			},
 		},
 		"both/setfail1": {
-			api.TTLAuto,
 			proxiedBoth,
 			false,
 			"hey!",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			ppBoth,
 			mockproviders{ipnet.IP4: provider4, ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
 				gomock.InOrder(
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTL(1), true).Return(false, "hey!"), //nolint:lll
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTL(1), true).Return(true, ""),
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, true).Return(false, "hey!"), //nolint:lll
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, true).Return(true, ""),
 				)
 			},
 		},
 		"both/setfail2": {
-			api.TTLAuto,
 			proxiedNone,
 			false,
 			"wrong",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			ppBoth,
 			mockproviders{ipnet.IP4: provider4, ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
 				gomock.InOrder(
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTL(1), false).Return(true, ""),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTL(1), false).Return(false, "wrong"), //nolint:lll
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).Return(true, ""),
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).Return(false, "wrong"), //nolint:lll
 				)
 			},
 		},
 		"ip4fails": {
-			api.TTLAuto,
 			proxiedBoth,
 			false,
 			"Failed to detect the IPv4 address",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Errorf(pp.EmojiError, "%s", "Failed to detect the IPv4 address"),
@@ -176,15 +175,14 @@ func TestUpdateIPs(t *testing.T) {
 				ipnet.IP6: provider6,
 			},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTL(1), true).Return(true, "looking good") //nolint:lll
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, true).Return(true, "looking good") //nolint:lll
 			},
 		},
 		"ip6fails": {
-			api.TTLAuto,
 			proxiedNone,
 			false,
 			"Failed to detect the IPv6 address",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Infof(pp.EmojiInternet, "Detected the %s address: %v", "IPv4", ip4),
@@ -201,15 +199,14 @@ func TestUpdateIPs(t *testing.T) {
 				},
 			},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTL(1), false).Return(true, "good") //nolint:lll
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).Return(true, "good") //nolint:lll
 			},
 		},
 		"ip6fails/again": {
-			api.TTLAuto,
 			proxiedBoth,
 			false,
 			"Failed to detect the IPv6 address",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: false},
+			map[string]bool{"detect-ip4-fail": true, "detect-ip6-fail": false, "update-timeout": true},
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Infof(pp.EmojiInternet, "Detected the %s address: %v", "IPv4", ip4),
@@ -223,15 +220,14 @@ func TestUpdateIPs(t *testing.T) {
 				},
 			},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTL(1), true).Return(true, "")
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, true).Return(true, "")
 			},
 		},
 		"bothfail": {
-			api.TTLAuto,
 			proxiedNone,
 			false,
 			"Failed to detect the IPv4 address\nFailed to detect the IPv6 address",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Errorf(pp.EmojiError, "%s", "Failed to detect the IPv4 address"),
@@ -253,11 +249,10 @@ func TestUpdateIPs(t *testing.T) {
 			nil,
 		},
 		"ip4only-proxied-nil": {
-			api.TTLAuto,
 			mockproxied{},
 			true,
 			"response",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Infof(pp.EmojiInternet, "Detected the %s address: %v", "IPv4", ip4),
@@ -269,7 +264,32 @@ func TestUpdateIPs(t *testing.T) {
 			},
 			mockproviders{ipnet.IP4: provider4},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTL(1), false).Return(true, "response") //nolint:lll
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).Return(true, "response") //nolint:lll
+			},
+		},
+		"slow-setting": {
+			proxiedNone,
+			false,
+			"response",
+			allHints,
+			func(m *mocks.MockPP) {
+				gomock.InOrder(
+					m.EXPECT().Infof(pp.EmojiInternet, "Detected the %s address: %v", "IPv4", ip4),
+					m.EXPECT().Infof(pp.EmojiConfig, "If your network is working but with high latency, consider increasing the value of UPDATE_TIMEOUT"), //nolint:lll
+				)
+			},
+			mockproviders{
+				ipnet.IP4: func(ppfmt pp.PP, m *mocks.MockProvider) {
+					m.EXPECT().GetIP(gomock.Any(), ppfmt, ipnet.IP4, true).Return(ip4, true)
+				},
+			},
+			func(ppfmt pp.PP, m *mocks.MockSetter) {
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+					DoAndReturn(
+						func(_ context.Context, _ pp.PP, _ domain.Domain, _ ipnet.Type, _ netip.Addr, _ api.TTL, _ bool) (bool, string) { //nolint:lll
+							time.Sleep(2 * time.Second)
+							return false, "response"
+						})
 			},
 		},
 	} {
@@ -279,15 +299,18 @@ func TestUpdateIPs(t *testing.T) {
 			ctx := context.Background()
 			conf := config.Default()
 			conf.Domains = domains
-			conf.TTL = tc.ttl
+			conf.TTL = api.TTLAuto
 			conf.Proxied = tc.proxied
 			conf.Use1001 = true
+			conf.UpdateTimeout = time.Second
 			mockPP := mocks.NewMockPP(mockCtrl)
 			if tc.prepareMockPP != nil {
 				tc.prepareMockPP(mockPP)
 			}
+			for k := range updater.ShouldDisplayHints {
+				updater.ShouldDisplayHints[k] = tc.ShouldDisplayHints[k]
+			}
 			for _, ipnet := range [...]ipnet.Type{ipnet.IP4, ipnet.IP6} {
-				updater.ShouldDisplayHelpMessages[ipnet] = tc.ShouldDisplayHelpMessages[ipnet]
 				if tc.prepareMockProvider[ipnet] == nil {
 					conf.Provider[ipnet] = nil
 					continue
@@ -322,31 +345,28 @@ func TestClearIPs(t *testing.T) {
 	proxiedNone := mockproxied{domain4: false, domain6: false}
 
 	for name, tc := range map[string]struct {
-		ttl                       api.TTL
-		proxied                   mockproxied
-		ok                        bool
-		msg                       string
-		ShouldDisplayHelpMessages map[ipnet.Type]bool
-		prepareMockPP             func(m *mocks.MockPP)
-		prepareMockProvider       mockproviders
-		prepareMockSetter         func(ppfmt pp.PP, m *mocks.MockSetter)
+		proxied             mockproxied
+		ok                  bool
+		msg                 string
+		ShouldDisplayHints  map[string]bool
+		prepareMockPP       func(m *mocks.MockPP)
+		prepareMockProvider mockproviders
+		prepareMockSetter   func(ppfmt pp.PP, m *mocks.MockSetter)
 	}{
 		"none": {
-			api.TTLAuto,
 			proxiedNone,
 			true,
 			``,
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			nil,
 			mockproviders{},
 			nil,
 		},
 		"ip4only": {
-			api.TTLAuto,
 			proxiedNone,
 			true,
 			"hello",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			nil,
 			mockproviders{ipnet.IP4: true},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
@@ -354,11 +374,10 @@ func TestClearIPs(t *testing.T) {
 			},
 		},
 		"ip4only/setfail": {
-			api.TTLAuto,
 			proxiedNone,
 			false,
 			"err",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			nil,
 			mockproviders{ipnet.IP4: true},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
@@ -366,11 +385,10 @@ func TestClearIPs(t *testing.T) {
 			},
 		},
 		"ip6only": {
-			api.TTLAuto,
 			proxiedNone,
 			true,
 			"",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			nil,
 			mockproviders{ipnet.IP6: true},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
@@ -378,11 +396,10 @@ func TestClearIPs(t *testing.T) {
 			},
 		},
 		"ip6only/setfail": {
-			api.TTLAuto,
 			proxiedNone,
 			false,
 			"test",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			nil,
 			mockproviders{ipnet.IP6: true},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
@@ -390,11 +407,10 @@ func TestClearIPs(t *testing.T) {
 			},
 		},
 		"both": {
-			api.TTLAuto,
 			proxiedNone,
 			true,
 			"both\nneither",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			allHints,
 			nil,
 			mockproviders{ipnet.IP4: true, ipnet.IP6: true},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
@@ -405,11 +421,10 @@ func TestClearIPs(t *testing.T) {
 			},
 		},
 		"both/setfail1": {
-			api.TTLAuto,
 			proxiedNone,
 			false,
-			"999",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			"",
+			allHints,
 			nil,
 			mockproviders{ipnet.IP4: true, ipnet.IP6: true},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
@@ -420,11 +435,10 @@ func TestClearIPs(t *testing.T) {
 			},
 		},
 		"both/setfail2": {
-			api.TTLAuto,
 			proxiedNone,
 			false,
-			"1\n2",
-			map[ipnet.Type]bool{ipnet.IP4: true, ipnet.IP6: true},
+			"2",
+			allHints,
 			nil,
 			mockproviders{ipnet.IP4: true, ipnet.IP6: true},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
@@ -441,14 +455,16 @@ func TestClearIPs(t *testing.T) {
 			ctx := context.Background()
 			conf := config.Default()
 			conf.Domains = domains
-			conf.TTL = tc.ttl
+			conf.TTL = api.TTLAuto
 			conf.Proxied = tc.proxied
 			mockPP := mocks.NewMockPP(mockCtrl)
 			if tc.prepareMockPP != nil {
 				tc.prepareMockPP(mockPP)
 			}
+			for k := range updater.ShouldDisplayHints {
+				updater.ShouldDisplayHints[k] = tc.ShouldDisplayHints[k]
+			}
 			for _, ipnet := range [...]ipnet.Type{ipnet.IP4, ipnet.IP6} {
-				updater.ShouldDisplayHelpMessages[ipnet] = tc.ShouldDisplayHelpMessages[ipnet]
 				if !tc.prepareMockProvider[ipnet] {
 					conf.Provider[ipnet] = nil
 					continue