Skip to content

Commit ea07005

Browse files
authored
Merge branch 'main' into dependencies
2 parents 4f78dc5 + b0f60a1 commit ea07005

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,21 @@ The user-friendly interface allows for straightforward secure setup and manageme
2626
- [x] Supports multiple IP resolvers
2727
- [x] Deploy as Windows Service
2828
- [x] Available as Docker Container
29+
- [x] Custom update URL with check
2930

3031
## 🏷️ Supported providers
3132

3233
`Strato` `DDNSS` `Dynu` `Aliyun` `NoIP` `DD24` `INWX`
3334

3435
> **Note:** If your DynDNS provider is not listed open an issue and I will integrate it.
3536
37+
### Custom provider
38+
39+
Select the provider **Custom** from the provider list.
40+
Then enter the user-defined URL in the **URL** field.
41+
Use the placeholder `<ipv4>` at the point where the IPv4 address is to be inserted.
42+
In the **“Check”** field, enter a string that will be used for checking to ensure that the update server's response is successful.
43+
3644
## 📜 Installation guide
3745

3846
### 🐋 Deploy with Docker

pkg/ddns/providers/custom.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package providers
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"strings"
7+
)
8+
9+
type UpdateCustomRequest struct {
10+
Domain string `json:"URL"`
11+
Check string `json:"Check"`
12+
}
13+
14+
func UpdateCustom(request interface{}, ipAddr string) error {
15+
r, ok := request.(*UpdateCustomRequest)
16+
if !ok {
17+
return fmt.Errorf("invalid request type: %T", request)
18+
}
19+
if !strings.Contains(r.Domain, "<ipv4>") {
20+
return fmt.Errorf("no <ipv4> placeholder found in URL")
21+
}
22+
r.Domain = strings.Replace(r.Domain, "<ipv4>", ipAddr, -1)
23+
resp, err := SendHTTPRequest(http.MethodGet, r.Domain, nil)
24+
if err != nil {
25+
return err
26+
}
27+
if !strings.Contains(resp, r.Check) {
28+
return fmt.Errorf("check string '%s' not found in response", r.Check)
29+
}
30+
return nil
31+
}

pkg/ddns/update.go

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type provider struct {
1010
}
1111

1212
var updaters = map[string]provider{
13+
"Custom": {Updater: providers.UpdateCustom, Request: providers.UpdateCustomRequest{}},
1314
"Strato": {Updater: providers.UpdateStrato, Request: providers.UpdateStratoRequest{}},
1415
"DDNSS": {Updater: providers.UpdateDDNSS, Request: providers.UpdateDDNSSRequest{}},
1516
"Dynu": {Updater: providers.UpdateDynu, Request: providers.UpdateDynuRequest{}},

pkg/server/routes/web/static/js/index.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
// Utility function to encode text content
2+
function encodeTextContent(text) {
3+
const div = document.createElement('div');
4+
div.appendChild(document.createTextNode(text));
5+
return div.innerHTML;
6+
}
7+
18
// Append inputs to form create job
29
document.getElementById('add-provider-select').addEventListener('change', async (e) => {
310
try {
@@ -21,8 +28,9 @@ document.getElementById('add-provider-select').addEventListener('change', async
2128
document.querySelector('table tbody').addEventListener('click', function(event) {
2229
const row = event.target.closest('tr');
2330
if (!row) return;
24-
document.getElementById('edit-id').value = row.querySelector('td:nth-child(1)').textContent;
25-
document.getElementById('delete-button').href = `/api/job/delete?ID=${row.querySelector('td:nth-child(1)').textContent}`;
31+
const idText = row.querySelector('td:nth-child(1)').textContent;
32+
document.getElementById('edit-id').value = idText;
33+
document.getElementById('delete-button').href = `/api/job/delete?ID=${encodeTextContent(idText)}`;
2634
document.getElementById('edit-provider-select').value = row.querySelector('td:nth-child(2)').textContent;
2735
const params = JSON.parse(row.querySelector('td:nth-child(4)').getAttribute('json'));
2836
let html = '';

0 commit comments

Comments
 (0)