Initial commit - Dutchie dispensary scraper

This commit is contained in:
Kelly
2025-11-28 19:45:44 -07:00
commit 5757a8e9bd
23375 changed files with 3788799 additions and 0 deletions

263
backend/src/routes/proxies.ts Executable file
View File

@@ -0,0 +1,263 @@
import { Router } from 'express';
import { authMiddleware, requireRole } from '../auth/middleware';
import { pool } from '../db/migrate';
import { testProxy, addProxy, addProxiesFromList } from '../services/proxy';
import { createProxyTestJob, getProxyTestJob, getActiveProxyTestJob, cancelProxyTestJob } from '../services/proxyTestQueue';
const router = Router();
router.use(authMiddleware);
// Get all proxies
router.get('/', async (req, res) => {
try {
const result = await pool.query(`
SELECT id, host, port, protocol, active, is_anonymous,
last_tested_at, test_result, response_time_ms, created_at,
city, state, country, country_code, location_updated_at
FROM proxies
ORDER BY created_at DESC
`);
res.json({ proxies: result.rows });
} catch (error) {
console.error('Error fetching proxies:', error);
res.status(500).json({ error: 'Failed to fetch proxies' });
}
});
// Get active proxy test job (must be before /:id route)
router.get('/test-job', async (req, res) => {
try {
const job = await getActiveProxyTestJob();
res.json({ job });
} catch (error) {
console.error('Error fetching active job:', error);
res.status(500).json({ error: 'Failed to fetch active job' });
}
});
// Get proxy test job status (must be before /:id route)
router.get('/test-job/:jobId', async (req, res) => {
try {
const { jobId } = req.params;
const job = await getProxyTestJob(parseInt(jobId));
if (!job) {
return res.status(404).json({ error: 'Job not found' });
}
res.json({ job });
} catch (error) {
console.error('Error fetching job status:', error);
res.status(500).json({ error: 'Failed to fetch job status' });
}
});
// Get single proxy
router.get('/:id', async (req, res) => {
try {
const { id } = req.params;
const result = await pool.query(`
SELECT id, host, port, protocol, username, active, is_anonymous,
last_tested_at, test_result, response_time_ms, created_at
FROM proxies
WHERE id = $1
`, [id]);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'Proxy not found' });
}
res.json({ proxy: result.rows[0] });
} catch (error) {
console.error('Error fetching proxy:', error);
res.status(500).json({ error: 'Failed to fetch proxy' });
}
});
// Add single proxy
router.post('/', requireRole('superadmin', 'admin'), async (req, res) => {
try {
const { host, port, protocol, username, password } = req.body;
if (!host || !port || !protocol) {
return res.status(400).json({ error: 'Host, port, and protocol required' });
}
// Test and add proxy
const proxyId = await addProxy(host, port, protocol, username, password);
const result = await pool.query(`
SELECT * FROM proxies WHERE id = $1
`, [proxyId]);
res.status(201).json({ proxy: result.rows[0] });
} catch (error: any) {
console.error('Error adding proxy:', error);
res.status(400).json({ error: error.message || 'Failed to add proxy' });
}
});
// Add multiple proxies
router.post('/bulk', requireRole('superadmin', 'admin'), async (req, res) => {
try {
const { proxies } = req.body;
if (!proxies || !Array.isArray(proxies)) {
return res.status(400).json({ error: 'Proxies array required' });
}
const result = await addProxiesFromList(proxies);
res.status(201).json(result);
} catch (error) {
console.error('Error adding proxies:', error);
res.status(500).json({ error: 'Failed to add proxies' });
}
});
// Test single proxy
router.post('/:id/test', requireRole('superadmin', 'admin'), async (req, res) => {
try {
const { id } = req.params;
const proxyResult = await pool.query(`
SELECT host, port, protocol, username, password
FROM proxies
WHERE id = $1
`, [id]);
if (proxyResult.rows.length === 0) {
return res.status(404).json({ error: 'Proxy not found' });
}
const proxy = proxyResult.rows[0];
const testResult = await testProxy(
proxy.host,
proxy.port,
proxy.protocol,
proxy.username,
proxy.password
);
// Update proxy with test results
await pool.query(`
UPDATE proxies
SET last_tested_at = CURRENT_TIMESTAMP,
test_result = $1,
response_time_ms = $2,
is_anonymous = $3,
active = $4
WHERE id = $5
`, [
testResult.success ? 'success' : 'failed',
testResult.responseTimeMs,
testResult.isAnonymous,
testResult.success,
id
]);
res.json({ test_result: testResult });
} catch (error) {
console.error('Error testing proxy:', error);
res.status(500).json({ error: 'Failed to test proxy' });
}
});
// Start proxy test job
router.post('/test-all', requireRole('superadmin', 'admin'), async (req, res) => {
try {
const jobId = await createProxyTestJob();
res.json({ jobId, message: 'Proxy test job started' });
} catch (error) {
console.error('Error starting proxy test job:', error);
res.status(500).json({ error: 'Failed to start proxy test job' });
}
});
// Cancel proxy test job
router.post('/test-job/:jobId/cancel', requireRole('superadmin', 'admin'), async (req, res) => {
try {
const { jobId } = req.params;
const cancelled = await cancelProxyTestJob(parseInt(jobId));
if (!cancelled) {
return res.status(404).json({ error: 'Job not found or already completed' });
}
res.json({ message: 'Job cancelled successfully' });
} catch (error) {
console.error('Error cancelling job:', error);
res.status(500).json({ error: 'Failed to cancel job' });
}
});
// Update proxy
router.put('/:id', requireRole('superadmin', 'admin'), async (req, res) => {
try {
const { id } = req.params;
const { host, port, protocol, username, password, active } = req.body;
const result = await pool.query(`
UPDATE proxies
SET host = COALESCE($1, host),
port = COALESCE($2, port),
protocol = COALESCE($3, protocol),
username = COALESCE($4, username),
password = COALESCE($5, password),
active = COALESCE($6, active),
updated_at = CURRENT_TIMESTAMP
WHERE id = $7
RETURNING *
`, [host, port, protocol, username, password, active, id]);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'Proxy not found' });
}
res.json({ proxy: result.rows[0] });
} catch (error) {
console.error('Error updating proxy:', error);
res.status(500).json({ error: 'Failed to update proxy' });
}
});
// Delete proxy
router.delete('/:id', requireRole('superadmin'), async (req, res) => {
try {
const { id } = req.params;
const result = await pool.query(`
DELETE FROM proxies WHERE id = $1 RETURNING id
`, [id]);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'Proxy not found' });
}
res.json({ message: 'Proxy deleted successfully' });
} catch (error) {
console.error('Error deleting proxy:', error);
res.status(500).json({ error: 'Failed to delete proxy' });
}
});
// Update all proxy locations
router.post('/update-locations', requireRole('superadmin', 'admin'), async (req, res) => {
try {
const { updateAllProxyLocations } = await import('../services/geolocation');
// Run in background
updateAllProxyLocations().catch(err => {
console.error('❌ Location update failed:', err);
});
res.json({ message: 'Location update job started' });
} catch (error) {
console.error('Error starting location update:', error);
res.status(500).json({ error: 'Failed to start location update' });
}
});
export default router;