upd / src /lib /helpers /urbanProxy.ts
cursorpro's picture
Upload 57 files
7a4c980 verified
const ACCOUNT_API = "https://api-pro.urban-vpn.com/rest/v1";
const STATS_API = "https://stats.urban-vpn.com/api/rest/v2";
const CLIENT_APP = "URBAN_VPN_BROWSER_EXTENSION";
const BROWSER = "CHROME";
interface UrbanProxyResult {
url: string;
protocol: string;
host: string;
port: number;
username?: string;
password?: string;
}
const PREFERRED_COUNTRIES = ["US", "GB", "CA", "DE", "FR", "NL", "ES", "IT", "JP", "KR", "SG", "AU"];
export async function fetchUrbanProxy(targetCountryCode = "RANDOM"): Promise<UrbanProxyResult | null> {
console.log(`[UrbanVPN] Fetching Urban VPN Proxy (Target: ${targetCountryCode})...`);
// 1. Register Anonymous
// console.log("[UrbanVPN] 1. Registering Anonymous User...");
const regUrl = `${ACCOUNT_API}/registrations/clientApps/${CLIENT_APP}/users/anonymous`;
const regHeaders = {
"content-type": "application/json",
"accept": "application/json, text/plain, */*",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
};
const regPayload = {
clientApp: {
name: CLIENT_APP,
browser: BROWSER
}
};
let regResp;
try {
regResp = await fetch(regUrl, {
method: "POST",
headers: regHeaders,
body: JSON.stringify(regPayload)
});
} catch (err) {
console.error("[UrbanVPN] Network error during registration:", err);
return null;
}
if (!regResp.ok) {
const text = await regResp.text();
console.error(`[UrbanVPN] Registration failed: ${regResp.status} ${regResp.statusText}`);
console.error(text);
return null;
}
const regData = await regResp.json();
const idToken = regData.id_token || regData.idToken || regData.value;
if (!idToken) {
console.error("[UrbanVPN] No ID token found in registration response.");
return null;
}
// 2. Get Security Token
// console.log("[UrbanVPN] 2. Getting Security Token...");
const secUrl = `${ACCOUNT_API}/security/tokens/accs`;
const secHeaders = {
...regHeaders,
"authorization": `Bearer ${idToken}`
};
const secPayload = {
type: "accs",
clientApp: {
name: CLIENT_APP
}
};
const secResp = await fetch(secUrl, {
method: "POST",
headers: secHeaders,
body: JSON.stringify(secPayload)
});
if (!secResp.ok) {
const text = await secResp.text();
console.error(`[UrbanVPN] Security Token request failed: ${secResp.status}`);
console.error(text);
return null;
}
const secData = await secResp.json();
let tokenString = "";
let credUsername = "";
const credPassword = "1";
if (secData.token && typeof secData.token === 'object' && secData.token.value) {
tokenString = secData.token.value;
credUsername = secData.token.value;
} else if (typeof secData.token === 'string') {
tokenString = secData.token;
credUsername = secData.token;
} else if (secData.value) {
tokenString = secData.value;
credUsername = secData.value;
}
if (!tokenString) {
console.error("[UrbanVPN] No security token found.");
return null;
}
// 3. Get Countries / Proxies
// console.log("[UrbanVPN] 3. Fetching Proxy List...");
const countriesUrl = `${STATS_API}/entrypoints/countries`;
const proxyHeaders = {
...regHeaders,
"authorization": `Bearer ${tokenString}`,
"X-Client-App": CLIENT_APP
};
// @ts-ignore: delete operator on string index signature
delete proxyHeaders["content-type"];
const countriesResp = await fetch(countriesUrl, {
headers: proxyHeaders
});
if (!countriesResp.ok) {
const text = await countriesResp.text();
console.error(`[UrbanVPN] Failed to fetch countries: ${countriesResp.status}`);
console.error(text);
return null;
}
const countriesData = await countriesResp.json();
if (!countriesData.countries || !countriesData.countries.elements) {
console.error("[UrbanVPN] Invalid countries data format.");
return null;
}
const countries = countriesData.countries.elements;
// Pick a country
let selectedCountryCode = targetCountryCode;
if (selectedCountryCode === "RANDOM") {
selectedCountryCode = PREFERRED_COUNTRIES[Math.floor(Math.random() * PREFERRED_COUNTRIES.length)];
}
// Find target country proxy
// deno-lint-ignore no-explicit-any
let targetCountry = countries.find((c: any) => c.code.iso2 === selectedCountryCode);
// Fallback if random choice not found
if (!targetCountry) {
targetCountry = countries[0];
console.log(`[UrbanVPN] Requested country ${selectedCountryCode} not found, falling back to ${targetCountry.code.iso2}`);
}
if (targetCountry) {
console.log(`[UrbanVPN] Selected Country: ${targetCountry.title} (${targetCountry.code.iso2})`);
let proxyHost = null;
let proxyPort = null;
let signature = null;
if (targetCountry.address && targetCountry.address.primary) {
proxyHost = targetCountry.address.primary.host;
proxyPort = targetCountry.address.primary.port;
}
else if (targetCountry.servers && targetCountry.servers.elements && targetCountry.servers.elements.length > 0) {
// Pick a RANDOM server from the list
const serverIndex = Math.floor(Math.random() * targetCountry.servers.elements.length);
const srv = targetCountry.servers.elements[serverIndex];
if (srv.address && srv.address.primary) {
proxyHost = srv.address.primary.host;
proxyPort = srv.address.primary.port || srv.address.primary.port_min;
signature = srv.signature;
}
}
if (signature) {
// console.log("[UrbanVPN] Found proxy signature, fetching Auth Proxy Token...");
const proxyTokenUrl = `${ACCOUNT_API}/security/tokens/accs-proxy`;
const proxyTokenPayload = {
type: "accs-proxy",
clientApp: { name: CLIENT_APP },
signature: signature
};
const proxyTokenHeaders = {
...regHeaders,
"authorization": `Bearer ${tokenString}`
};
const ptResp = await fetch(proxyTokenUrl, {
method: "POST",
headers: proxyTokenHeaders,
body: JSON.stringify(proxyTokenPayload)
});
if (ptResp.ok) {
const ptData = await ptResp.json();
if (ptData.value) {
credUsername = ptData.value;
} else if (ptData.token && ptData.token.value) {
credUsername = ptData.token.value;
}
} else {
console.error(`[UrbanVPN] Failed to get Proxy Auth Token: ${ptResp.status}`);
}
}
if (proxyHost) {
const proxyUrl = `http://${encodeURIComponent(credUsername)}:${encodeURIComponent(credPassword)}@${proxyHost}:${proxyPort}`;
console.log(`[UrbanVPN] Proxy found: ${proxyHost}:${proxyPort}`);
return {
url: proxyUrl,
protocol: 'http',
host: proxyHost,
port: proxyPort,
username: credUsername,
password: credPassword
};
}
}
console.error("[UrbanVPN] No proxy server details found.");
return null;
}