diff --git a/backend/server.js b/backend/server.js
index 1d046f0..de209f9 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -942,6 +942,172 @@ app.post('/api/simple-filters', async (req, res) => {
}
});
+// --- Auto URL Routes ---
+
+// Get auto URLs from S3
+app.get('/api/auto-urls', async (req, res) => {
+ const params = {
+ Bucket: BUCKET_NAME,
+ Key: 'bgp_data/auto_url/urls.txt',
+ };
+
+ try {
+ const data = await s3.getObject(params).promise();
+ const fileContent = data.Body.toString('utf-8');
+ const urls = fileContent.split('\n').filter(line => line).map(line => {
+ const parts = line.trim().split(/\s*\|\s*/);
+ const url = parts[0] || '';
+ const community = parts[1] || '';
+ return { url, community };
+ });
+ res.json(urls);
+ } catch (error) {
+ if (error.code === 'NoSuchKey') {
+ res.json([]); // Return empty array if file does not exist
+ } else {
+ console.error(error);
+ res.status(500).send('Error reading auto URLs from S3');
+ }
+ }
+});
+
+// Update auto URLs in S3
+app.post('/api/auto-urls', async (req, res) => {
+ const { urls } = req.body;
+ const fileContent = urls.map(u => `${u.url} | ${u.community}`).join('\n');
+
+ const params = {
+ Bucket: BUCKET_NAME,
+ Key: 'bgp_data/auto_url/urls.txt',
+ Body: fileContent,
+ ContentType: 'text/plain',
+ };
+
+ try {
+ await s3.putObject(params).promise();
+ res.send('Auto URLs updated successfully');
+ } catch (error) {
+ console.error(error);
+ res.status(500).send('Error writing auto URLs to S3');
+ }
+});
+
+// Process auto URLs and update IPs
+app.post('/api/auto-urls/process', async (req, res) => {
+ const https = require('https');
+ const http = require('http');
+
+ try {
+ // Get current auto URLs
+ const urlsParams = {
+ Bucket: BUCKET_NAME,
+ Key: 'bgp_data/auto_url/urls.txt',
+ };
+
+ let urls = [];
+ try {
+ const urlsData = await s3.getObject(urlsParams).promise();
+ const urlsContent = urlsData.Body.toString('utf-8');
+ urls = urlsContent.split('\n').filter(line => line).map(line => {
+ const parts = line.trim().split(/\s*\|\s*/);
+ return { url: parts[0] || '', community: parts[1] || '' };
+ });
+ } catch (error) {
+ if (error.code !== 'NoSuchKey') {
+ throw error;
+ }
+ }
+
+ if (urls.length === 0) {
+ return res.status(400).send('No URLs to process');
+ }
+
+ // Get current IPs
+ const ipsParams = {
+ Bucket: BUCKET_NAME,
+ Key: 'bgp_data/ips.txt',
+ };
+
+ let currentIps = [];
+ try {
+ const ipsData = await s3.getObject(ipsParams).promise();
+ const ipsContent = ipsData.Body.toString('utf-8');
+ currentIps = ipsContent.split('\n').filter(line => line).map(line => {
+ const parts = line.trim().split(/\s+/);
+ return { ipRange: parts[0] || '', community: parts[1] || '' };
+ });
+ } catch (error) {
+ if (error.code !== 'NoSuchKey') {
+ throw error;
+ }
+ }
+
+ // Process each URL
+ const newIps = [];
+ for (const urlData of urls) {
+ try {
+ const url = urlData.url.trim();
+ const community = urlData.community.trim();
+
+ if (!url || !community) continue;
+
+ // Download content from URL
+ const content = await new Promise((resolve, reject) => {
+ const protocol = url.startsWith('https:') ? https : http;
+ const req = protocol.get(url, (res) => {
+ let data = '';
+ res.on('data', (chunk) => data += chunk);
+ res.on('end', () => resolve(data));
+ });
+ req.on('error', reject);
+ req.setTimeout(10000, () => req.destroy());
+ });
+
+ // Parse IPs from content
+ const lines = content.split('\n');
+ for (const line of lines) {
+ const ip = line.trim();
+ if (ip && (ip.includes('.') || ip.includes(':'))) {
+ newIps.push({ ipRange: ip, community });
+ }
+ }
+
+ } catch (error) {
+ console.error(`Error processing URL ${urlData.url}:`, error);
+ }
+ }
+
+ // Merge with existing IPs (avoid duplicates)
+ const existingIpRanges = new Set(currentIps.map(ip => ip.ipRange));
+ const uniqueNewIps = newIps.filter(ip => !existingIpRanges.has(ip.ipRange));
+
+ const allIps = [...currentIps, ...uniqueNewIps];
+
+ // Save updated IPs
+ const updatedIpsContent = allIps.map(ip => `${ip.ipRange} ${ip.community}`).join('\n');
+ const updateParams = {
+ Bucket: BUCKET_NAME,
+ Key: 'bgp_data/ips.txt',
+ Body: updatedIpsContent,
+ ContentType: 'text/plain',
+ };
+
+ await s3.putObject(updateParams).promise();
+
+ res.json({
+ success: true,
+ message: `Обработано ${urls.length} URL, добавлено ${uniqueNewIps.length} новых IP-адресов`,
+ processedUrls: urls.length,
+ newIpsCount: uniqueNewIps.length,
+ totalIpsCount: allIps.length
+ });
+
+ } catch (error) {
+ console.error('Error processing auto URLs:', error);
+ res.status(500).send('Error processing auto URLs');
+ }
+});
+
// The "catchall" handler: for any request that doesn't
// match one above, send back React's index.html file.
app.get('*', (req, res) => {
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 84ff028..d523323 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -17,7 +17,8 @@ import {
IconAlertTriangle,
IconAlertCircle,
IconServer,
- IconFilter
+ IconFilter,
+ IconDownload
} from '@tabler/icons-react';
import DataManager from './DataManager';
import ServerManager from './ServerManager';
@@ -25,6 +26,7 @@ import FilterManager from './FilterManager';
import DomainsNewManager from './DomainsNewManager';
import IPRangesManager from './IPRangesManager';
import ASNsNewManager from './ASNsNewManager';
+import AutoUrlManager from './AutoUrlManager';
import './App.css';
import axios from 'axios';
import {
@@ -56,6 +58,7 @@ function MainLayout() {
{ id: 'domains-new', title: 'Домены New', icon: IconWorld, path: '/domains-new' },
{ id: 'ip-ranges', title: 'IP-диапазоны', icon: IconNetwork, path: '/ip-ranges' },
{ id: 'asns', title: 'AS', icon: IconNetwork, path: '/asns' },
+ { id: 'auto-urls', title: 'Авто URL', icon: IconDownload, path: '/auto-urls' },
{ id: 'servers', title: 'Серверы', icon: IconServer, path: '/servers' },
{ id: 'filters', title: 'Фильтры', icon: IconFilter, path: '/filters' },
{ id: 'files', title: 'Файлы', icon: IconFileText, path: '/files' },
@@ -103,6 +106,7 @@ function MainLayout() {
Нет добавленных URL-адресов
+ +| URL | +Community | +Действия | +
|---|---|---|
| + updateUrl(index, 'url', e.target.value)} + disabled={saving || processing} + /> + | ++ updateUrl(index, 'community', e.target.value)} + disabled={saving || processing} + /> + | ++ + | +
Файл сохраняется в формате:
+
+{`https://test.com/ips.txt | 555
+https://example.com/blacklist.txt | 666`}
+
+