mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
183 lines
4.4 KiB
TypeScript
183 lines
4.4 KiB
TypeScript
import { upsertOneproxyProxy } from "./db/oneproxy";
|
|
import { getSettings } from "./db/settings";
|
|
|
|
type OneProxyApiResponse = {
|
|
total: number;
|
|
count: number;
|
|
offset: number;
|
|
limit: number;
|
|
proxies: Array<{
|
|
id: number;
|
|
url: string;
|
|
protocol: string;
|
|
ip: string;
|
|
port: number;
|
|
country_code: string;
|
|
country_name: string;
|
|
latency_ms: number;
|
|
anonymity: string;
|
|
proxy_type: string;
|
|
can_access_google: boolean;
|
|
quality_score: number;
|
|
is_working: boolean;
|
|
validation_status: string;
|
|
last_validated: string;
|
|
}>;
|
|
};
|
|
|
|
const DEFAULT_API_URL = "https://1proxy-api.aitradepulse.com";
|
|
const DEFAULT_MAX_PROXIES = 500;
|
|
const DEFAULT_MIN_QUALITY = 50;
|
|
const DEFAULT_PAGE_SIZE = 100;
|
|
|
|
let lastSyncSuccess = false;
|
|
let lastSyncError: string | null = null;
|
|
let lastSyncAt: string | null = null;
|
|
let lastSyncCount = 0;
|
|
let consecutiveFailures = 0;
|
|
const MAX_CONSECUTIVE_FAILURES = 5;
|
|
|
|
export async function syncOneproxyProxies(options?: {
|
|
apiUrl?: string;
|
|
maxProxies?: number;
|
|
minQuality?: number;
|
|
}): Promise<{
|
|
success: boolean;
|
|
added: number;
|
|
updated: number;
|
|
failed: number;
|
|
total: number;
|
|
error: string | null;
|
|
}> {
|
|
const settings = await getSettings();
|
|
const enabled = process.env.ONEPROXY_ENABLED !== "false";
|
|
if (!enabled) {
|
|
return {
|
|
success: false,
|
|
added: 0,
|
|
updated: 0,
|
|
failed: 0,
|
|
total: 0,
|
|
error: "1proxy integration disabled",
|
|
};
|
|
}
|
|
|
|
const apiUrl = options?.apiUrl || process.env.ONEPROXY_API_URL || DEFAULT_API_URL;
|
|
const maxProxies =
|
|
(options?.maxProxies ?? parseInt(process.env.ONEPROXY_MAX_PROXIES || "", 10)) ||
|
|
DEFAULT_MAX_PROXIES;
|
|
const minQuality =
|
|
(options?.minQuality ?? parseInt(process.env.ONEPROXY_MIN_QUALITY_THRESHOLD || "", 10)) ||
|
|
DEFAULT_MIN_QUALITY;
|
|
|
|
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
return {
|
|
success: false,
|
|
added: 0,
|
|
updated: 0,
|
|
failed: 0,
|
|
total: 0,
|
|
error: `Circuit breaker: ${consecutiveFailures} consecutive failures. Reset required.`,
|
|
};
|
|
}
|
|
|
|
let added = 0;
|
|
let updated = 0;
|
|
let failed = 0;
|
|
let offset = 0;
|
|
|
|
try {
|
|
while (true) {
|
|
const url = `${apiUrl}/api/v1/proxies/advanced?limit=${DEFAULT_PAGE_SIZE}&offset=${offset}&min_quality=${minQuality}&is_working=true`;
|
|
const response = await fetch(url, {
|
|
signal: AbortSignal.timeout(30000),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`1proxy API returned ${response.status}`);
|
|
}
|
|
|
|
const data = (await response.json()) as OneProxyApiResponse;
|
|
if (!data.proxies || data.proxies.length === 0) break;
|
|
|
|
for (const proxy of data.proxies) {
|
|
if (added + updated >= maxProxies) break;
|
|
|
|
try {
|
|
const result = await upsertOneproxyProxy({
|
|
ip: proxy.ip,
|
|
port: proxy.port,
|
|
protocol: proxy.protocol,
|
|
countryCode: proxy.country_code,
|
|
anonymity: proxy.anonymity,
|
|
qualityScore: proxy.quality_score,
|
|
latencyMs: proxy.latency_ms,
|
|
googleAccess: proxy.can_access_google,
|
|
lastValidated: proxy.last_validated,
|
|
});
|
|
|
|
if (result.action === "created") added++;
|
|
else updated++;
|
|
} catch {
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
if (added + updated >= maxProxies) break;
|
|
if (data.proxies.length < DEFAULT_PAGE_SIZE) break;
|
|
|
|
offset += DEFAULT_PAGE_SIZE;
|
|
}
|
|
|
|
consecutiveFailures = 0;
|
|
lastSyncSuccess = true;
|
|
lastSyncError = null;
|
|
lastSyncAt = new Date().toISOString();
|
|
lastSyncCount = added + updated;
|
|
|
|
return {
|
|
success: true,
|
|
added,
|
|
updated,
|
|
failed,
|
|
total: added + updated,
|
|
error: null,
|
|
};
|
|
} catch (err) {
|
|
consecutiveFailures++;
|
|
lastSyncSuccess = false;
|
|
lastSyncError = err instanceof Error ? err.message : String(err);
|
|
lastSyncAt = new Date().toISOString();
|
|
|
|
return {
|
|
success: false,
|
|
added: 0,
|
|
updated: 0,
|
|
failed: 0,
|
|
total: 0,
|
|
error: lastSyncError,
|
|
};
|
|
}
|
|
}
|
|
|
|
export function getOneproxySyncStatus(): {
|
|
lastSyncSuccess: boolean;
|
|
lastSyncError: string | null;
|
|
lastSyncAt: string | null;
|
|
lastSyncCount: number;
|
|
consecutiveFailures: number;
|
|
} {
|
|
return {
|
|
lastSyncSuccess,
|
|
lastSyncError,
|
|
lastSyncAt,
|
|
lastSyncCount,
|
|
consecutiveFailures,
|
|
};
|
|
}
|
|
|
|
export function resetOneproxyCircuitBreaker(): void {
|
|
consecutiveFailures = 0;
|
|
lastSyncError = null;
|
|
}
|