From ef457a1fda462dc79003f56c1614116272c52c21 Mon Sep 17 00:00:00 2001 From: Rekryt Date: Wed, 4 Sep 2024 16:42:20 +0300 Subject: [PATCH] feat: new output formats Dnsmasq nfset and ipset, ClashX, Keenetic KVAS --- src/App/Controller/ClashxController.php | 32 +++++++++++++++++++++++ src/App/Controller/IpsetController.php | 19 ++++++++++++++ src/App/Controller/KvasController.php | 26 ++++++++++++++++++ src/App/Controller/MikrotikController.php | 2 +- src/App/Controller/NfsetController.php | 26 ++++++++++++++++++ src/App/Controller/TextController.php | 13 ++++++--- src/App/Service/IPListService.php | 4 +++ src/App/Template/IndexTemplate.php | 8 ++++-- src/Domain/Factory/SiteFactory.php | 12 ++++----- 9 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 src/App/Controller/ClashxController.php create mode 100644 src/App/Controller/IpsetController.php create mode 100644 src/App/Controller/KvasController.php create mode 100644 src/App/Controller/NfsetController.php 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: