diff --git a/src/App/Controller/ClashxController.php b/src/App/Controller/ClashxController.php
new file mode 100644
index 0000000..f4c66b7
--- /dev/null
+++ b/src/App/Controller/ClashxController.php
@@ -0,0 +1,32 @@
+request->getQueryParameter('data') ?? '';
+ $handlers = [
+ 'domains' => fn(string $row) => 'DOMAIN-SUFFIX,' . $row,
+ 'ip4' => fn(string $row) => 'IP-CIDR,' . $row . '/32',
+ 'ip6' => fn(string $row) => 'IP-CIDR6,' . $row . '/128',
+ 'cidr4' => fn(string $row) => 'IP-CIDR,' . $row,
+ 'cidr6' => fn(string $row) => 'IP-CIDR6,' . $row,
+ ];
+ return implode($this::DELIMITER, array_map($handlers[$data] ?? fn(string $row) => $row, $response));
+ }
+}
diff --git a/src/App/Controller/IpsetController.php b/src/App/Controller/IpsetController.php
new file mode 100644
index 0000000..1487719
--- /dev/null
+++ b/src/App/Controller/IpsetController.php
@@ -0,0 +1,19 @@
+request->getQueryParameter('data') ?? '';
+ return implode(
+ $this::DELIMITER,
+ array_map(fn(string $row) => 'ipset=/' . $row . '/vpn_' . $data, $response)
+ );
+ }
+}
diff --git a/src/App/Controller/KvasController.php b/src/App/Controller/KvasController.php
new file mode 100644
index 0000000..8bd608c
--- /dev/null
+++ b/src/App/Controller/KvasController.php
@@ -0,0 +1,26 @@
+request->getQueryParameter('data') ?? '';
+ $handlers = [
+ 'domains' => fn(string $row) => '*' . $row,
+ 'ip4' => fn(string $row) => $row . '/32',
+ 'ip6' => fn(string $row) => $row . '/128',
+ 'cidr4' => fn(string $row) => $row,
+ 'cidr6' => fn(string $row) => $row,
+ ];
+ return implode($this::DELIMITER, array_map($handlers[$data] ?? fn(string $row) => $row, $response));
+ }
+}
diff --git a/src/App/Controller/MikrotikController.php b/src/App/Controller/MikrotikController.php
index 4bcebee..ecd6423 100644
--- a/src/App/Controller/MikrotikController.php
+++ b/src/App/Controller/MikrotikController.php
@@ -14,7 +14,7 @@ class MikrotikController extends AbstractIPListController {
$sites = SiteFactory::normalizeArray($this->request->getQueryParameters()['site'] ?? []);
$data = $this->request->getQueryParameter('data') ?? '';
if ($data == '') {
- return "# Error: The 'data' GET parameter is required in the URL to access this page, but it cannot have the value 'All'";
+ return "# Error: The 'data' GET parameter is required in the URL to access this page";
}
$response = [];
diff --git a/src/App/Controller/NfsetController.php b/src/App/Controller/NfsetController.php
new file mode 100644
index 0000000..7bd10c5
--- /dev/null
+++ b/src/App/Controller/NfsetController.php
@@ -0,0 +1,26 @@
+request->getQueryParameter('data') ?? '';
+
+ $prefix = 'nftset=/';
+ $suffix = '#inet#fw4#vpn_';
+ $handlers = [
+ 'domains' => fn(string $row) => $prefix . $row . '/4' . $suffix . $data,
+ 'ip4' => fn(string $row) => $prefix . $row . '/4' . $suffix . $data,
+ 'ip6' => fn(string $row) => $prefix . $row . '/6' . $suffix . $data,
+ 'cidr4' => fn(string $row) => $prefix . $row . '/4' . $suffix . $data,
+ 'cidr6' => fn(string $row) => $prefix . $row . '/6' . $suffix . $data,
+ ];
+ return implode($this::DELIMITER, array_map($handlers[$data] ?? fn(string $row) => $row, $response));
+ }
+}
diff --git a/src/App/Controller/TextController.php b/src/App/Controller/TextController.php
index b6d9fbb..5c0ee15 100644
--- a/src/App/Controller/TextController.php
+++ b/src/App/Controller/TextController.php
@@ -15,7 +15,7 @@ class TextController extends AbstractIPListController {
$sites = SiteFactory::normalizeArray($this->request->getQueryParameters()['site'] ?? []);
$data = $this->request->getQueryParameter('data') ?? '';
if ($data == '') {
- return "# Error: The 'data' GET parameter is required in the URL to access this page, but it cannot have the value 'All'";
+ return "# Error: The 'data' GET parameter is required in the URL to access this page";
}
$response = [];
@@ -29,9 +29,16 @@ class TextController extends AbstractIPListController {
}
}
- return implode(
- $this::DELIMITER,
+ return $this->render(
SiteFactory::normalizeArray($response, in_array($data, ['ipv4', 'ipv6', 'cidr4', 'cidr6']))
);
}
+
+ /**
+ * @param array $response
+ * @return string
+ */
+ protected function render(array $response): string {
+ return implode($this::DELIMITER, $response);
+ }
}
diff --git a/src/App/Service/IPListService.php b/src/App/Service/IPListService.php
index 357d4d5..bc2cd45 100644
--- a/src/App/Service/IPListService.php
+++ b/src/App/Service/IPListService.php
@@ -60,6 +60,10 @@ class IPListService {
* @return void
*/
private function loadConfig(string $name, object $config): void {
+ if (isset($this->sites[$name])) {
+ $this->logger->error(sprintf('Site "%s" already exists', $name));
+ return;
+ }
$this->sites[$name] = SiteFactory::create($name, $config);
}
}
diff --git a/src/App/Template/IndexTemplate.php b/src/App/Template/IndexTemplate.php
index 1894980..d42f3df 100644
--- a/src/App/Template/IndexTemplate.php
+++ b/src/App/Template/IndexTemplate.php
@@ -619,10 +619,14 @@ use OpenCCK\App\Controller\TextController;
Format: