diff --git a/modules/pihole/bootstrap.php b/modules/pihole/bootstrap.php index e5792a9..4351194 100644 --- a/modules/pihole/bootstrap.php +++ b/modules/pihole/bootstrap.php @@ -26,24 +26,76 @@ $mm->registerFunction($moduleName, 'instances', function () use ($moduleName): a $verifyTls = !isset($settings['verify_tls']) || $settings['verify_tls'] === '1' || $settings['verify_tls'] === 1 || $settings['verify_tls'] === true; $instances = []; - foreach (['primary', 'secondary'] as $key) { - $urlKey = $key . '_url'; - $tokenKey = $key . '_token'; - $nameKey = $key . '_name'; - $url = trim((string)($settings[$urlKey] ?? '')); - if ($url === '') { - continue; + + $rawJson = trim((string)($settings['instances_json'] ?? '')); + if ($rawJson !== '') { + $decoded = json_decode($rawJson, true); + if (is_array($decoded)) { + foreach ($decoded as $row) { + if (!is_array($row)) { + continue; + } + $id = trim((string)($row['id'] ?? '')); + $url = trim((string)($row['url'] ?? '')); + if ($id === '' || $url === '') { + continue; + } + $instances[$id] = [ + 'id' => $id, + 'name' => trim((string)($row['name'] ?? '')) ?: $id, + 'url' => rtrim($url, '/'), + 'token' => trim((string)($row['token'] ?? '')), + 'api_path' => $apiPath, + 'timeout' => $timeout, + 'verify_tls' => $verifyTls, + 'is_primary' => !empty($row['is_primary']), + ]; + } + } + } + + if (empty($instances)) { + foreach (['primary', 'secondary'] as $key) { + $urlKey = $key . '_url'; + $tokenKey = $key . '_token'; + $nameKey = $key . '_name'; + $url = trim((string)($settings[$urlKey] ?? '')); + if ($url === '') { + continue; + } + $instances[$key] = [ + 'id' => $key, + 'name' => trim((string)($settings[$nameKey] ?? '')) ?: ($key === 'primary' ? 'Primaer' : 'Sekundaer'), + 'url' => rtrim($url, '/'), + 'token' => trim((string)($settings[$tokenKey] ?? '')), + 'api_path' => $apiPath, + 'timeout' => $timeout, + 'verify_tls' => $verifyTls, + 'is_primary' => $key === 'primary', + ]; + } + } + + $primaryId = trim((string)($settings['primary_id'] ?? '')); + if ($primaryId !== '' && isset($instances[$primaryId])) { + foreach ($instances as $id => &$row) { + $row['is_primary'] = ($id === $primaryId); + } + unset($row); + } else { + $hasPrimary = false; + foreach ($instances as $row) { + if (!empty($row['is_primary'])) { + $hasPrimary = true; + break; + } + } + if (!$hasPrimary && $instances) { + $firstKey = array_key_first($instances); + if ($firstKey !== null) { + $instances[$firstKey]['is_primary'] = true; + } } - $instances[$key] = [ - 'id' => $key, - 'name' => trim((string)($settings[$nameKey] ?? '')) ?: ($key === 'primary' ? 'Primaer' : 'Sekundaer'), - 'url' => rtrim($url, '/'), - 'token' => trim((string)($settings[$tokenKey] ?? '')), - 'api_path' => $apiPath, - 'timeout' => $timeout, - 'verify_tls' => $verifyTls, - 'is_primary' => $key === 'primary', - ]; } return $instances; diff --git a/modules/pihole/module.json b/modules/pihole/module.json index 31ef237..c8d5ef2 100644 --- a/modules/pihole/module.json +++ b/modules/pihole/module.json @@ -21,12 +21,14 @@ }, "setup": { "fields": [ - { "name": "primary_name", "label": "Primaer-Name", "type": "text", "required": false, "help": "Anzeige-Name (z.B. Pi-hole Main)" }, - { "name": "primary_url", "label": "Primaer-URL", "type": "text", "required": true, "help": "Basis-URL der Instanz, z.B. http://pi-hole.local" }, - { "name": "primary_token", "label": "Primaer-API Token", "type": "password", "required": false, "help": "Token aus dem Pi-hole Admin (API Token)." }, - { "name": "secondary_name", "label": "Sekundaer-Name", "type": "text", "required": false, "help": "Anzeige-Name (z.B. Pi-hole Backup)" }, - { "name": "secondary_url", "label": "Sekundaer-URL", "type": "text", "required": false, "help": "Basis-URL der zweiten Instanz" }, - { "name": "secondary_token", "label": "Sekundaer-API Token", "type": "password", "required": false }, + { "name": "instances_json", "label": "Instanzen (JSON)", "type": "textarea", "required": false, "help": "Mehrere Instanzen als JSON-Array. Beispiel: [{\"id\":\"pihole-main\",\"name\":\"Pi-hole Main\",\"url\":\"http://pi-hole.local\",\"token\":\"TOKEN\",\"is_primary\":true},{\"id\":\"pihole-backup\",\"name\":\"Pi-hole Backup\",\"url\":\"http://pi-hole-2.local\",\"token\":\"TOKEN2\"}]" }, + { "name": "primary_id", "label": "Primaer-ID (optional)", "type": "text", "required": false, "help": "Wenn gesetzt, wird diese Instanz als Primaer fuer Listen-Updates genutzt." }, + { "name": "primary_name", "label": "Primaer-Name (Legacy)", "type": "text", "required": false, "help": "Anzeige-Name (z.B. Pi-hole Main)" }, + { "name": "primary_url", "label": "Primaer-URL (Legacy)", "type": "text", "required": false, "help": "Basis-URL der Instanz, z.B. http://pi-hole.local" }, + { "name": "primary_token", "label": "Primaer-API Token (Legacy)", "type": "password", "required": false, "help": "Token aus dem Pi-hole Admin (API Token)." }, + { "name": "secondary_name", "label": "Sekundaer-Name (Legacy)", "type": "text", "required": false, "help": "Anzeige-Name (z.B. Pi-hole Backup)" }, + { "name": "secondary_url", "label": "Sekundaer-URL (Legacy)", "type": "text", "required": false, "help": "Basis-URL der zweiten Instanz" }, + { "name": "secondary_token", "label": "Sekundaer-API Token (Legacy)", "type": "password", "required": false }, { "name": "api_path", "label": "API Pfad", "type": "text", "required": false, "help": "Standard: /admin/api.php" }, { "name": "api_timeout_sec", "label": "API Timeout (Sek.)", "type": "number", "required": false, "help": "Standard 8" }, { "name": "verify_tls", "label": "TLS Verifikation aktiv", "type": "checkbox", "required": false, "help": "Deaktivieren nur wenn das Zertifikat unsicher ist." }, diff --git a/modules/pihole/pages/api.php b/modules/pihole/pages/api.php index 0191056..addb72d 100644 --- a/modules/pihole/pages/api.php +++ b/modules/pihole/pages/api.php @@ -97,10 +97,26 @@ $apiRequest = function (array $instance, array $params) use ($normalizeApiPath): return ['ok' => true, 'data' => $data, 'http_code' => $httpCode, 'url' => $full]; }; -$pickInstances = function (string $target) use ($instances): array { +$resolvePrimaryId = function () use ($instances): ?string { + foreach ($instances as $id => $row) { + if (!empty($row['is_primary'])) { + return $id; + } + } + $first = array_key_first($instances); + return $first !== null ? (string)$first : null; +}; + +$pickInstances = function (string $target) use ($instances, $resolvePrimaryId): array { if ($target === 'all') { return $instances; } + if ($target === 'primary') { + $primaryId = $resolvePrimaryId(); + if ($primaryId !== null && isset($instances[$primaryId])) { + return [$primaryId => $instances[$primaryId]]; + } + } if (isset($instances[$target])) { return [$target => $instances[$target]]; }