UNPKG

@0xtld/tair-node

Version:

A Node.js package for Tair functionality with configuration, core, and helper modules.

211 lines (172 loc) 6.09 kB
import axios, { AxiosInstance, AxiosResponse } from 'axios'; import { UrbanProxyElement } from '../types'; import { HttpsProxyAgent } from 'https-proxy-agent'; class UrbanProxyConfig { static clientAppName = 'URBAN_VPN_BROWSER_EXTENSION'; static headers = { 'accept': '*/*', 'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8,vi;q=0.7,cs;q=0.6,th;q=0.5', 'authorization': 'Bearer wBgfw5JK1K24wpo01S5wSbtNi5MEIMjI', 'cache-control': 'no-cache', 'content-type': 'application/json', 'origin': 'chrome-extension://eppiocemhmnlbhjplcgkofciiegomcon', 'pragma': 'no-cache', 'priority': 'u=1, i', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'none', 'sec-fetch-storage-access': 'active', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36', }; static urls = { accessToken: 'https://api-pro.falais.com/rest/v1/security/tokens/accs', getProxy: 'https://api-pro.falais.com/rest/v1/security/tokens/accs-proxy', getProxyList: 'https://stats.falais.com/api/rest/v2/entrypoints/countries', }; } class UrbanProxy { private proxyList: UrbanProxyElement[] = []; private proxy: UrbanProxyElement | null = null; private accessToken: string | null = null; private session: AxiosInstance; constructor() { this.session = axios.create({ headers: UrbanProxyConfig.headers, }); this.session.interceptors.response.use( (response) => response, async (error) => { if (error.response) { this.reset(); } return Promise.reject(error); } ) } private async getAccessToken(): Promise<string | null> { const response = await this.session.post(UrbanProxyConfig.urls.accessToken, { type: 'accs', clientApp: { name: UrbanProxyConfig.clientAppName, }, }); if (response.status === 200) { this.accessToken = response.data.value; return this.accessToken; } return null; } private async handleBeforeRequest(): Promise<void> { if (!this.accessToken) { await this.getAccessToken(); } } private isExpired(proxy: UrbanProxyElement): boolean { return proxy.expiration_time! < Date.now(); } private async handleAfterResponse(response: AxiosResponse): Promise<void> { if (response.status === 401) { await this.refreshSession(); } else if (response.status !== 200) { console.error(`Error: ${response.status} - ${response.data}`); this.reset(); } } private reset(): void { this.proxy = null; this.proxyList = []; this.accessToken = null; } private async refreshSession(): Promise<void> { this.session = axios.create({ headers: UrbanProxyConfig.headers, }); await this.getAccessToken(); } private async authProxy(proxy: UrbanProxyElement): Promise<UrbanProxyElement> { await this.handleBeforeRequest(); const headers = { ...UrbanProxyConfig.headers, authorization: `Bearer ${this.accessToken}`, 'x-client-app': UrbanProxyConfig.clientAppName, }; const body = { type: 'accs-proxy', clientApp: { name: UrbanProxyConfig.clientAppName, }, signature: proxy.signature, }; const response = await this.session.post(UrbanProxyConfig.urls.getProxy, body, { headers }); if (response.status !== 200) { await this.handleAfterResponse(response); throw new Error(`Auth proxy failed -> ${response.status} : ${response.data}`); } const resp = response.data; proxy.username = resp.value; proxy.creation_time = resp.creationTime; proxy.expiration_time = resp.expirationTime; proxy.auth_str = `http://${proxy.username}:${proxy.password}@${proxy.host}:${proxy.port}`; this.proxyList = this.proxyList.filter((p) => p !== proxy); this.proxyList.push(proxy); return proxy; } public async getProxy(proxy: UrbanProxyElement | null = null): Promise<UrbanProxyElement> { if (this.proxyList.length === 0) { await this.getProxyList(); } if (proxy && !this.isExpired(proxy)) { return proxy; } const element = this.proxyList[Math.floor(Math.random() * this.proxyList.length)]; if (!element) { throw new Error('Proxy not found'); } if (element.expiration_time && element.expiration_time > Date.now()) { return element; } return this.authProxy(element); } public async getProxyList(): Promise<UrbanProxyElement[]> { await this.handleBeforeRequest(); const headers = { ...UrbanProxyConfig.headers, authorization: `Bearer ${this.accessToken}`, 'x-client-app': UrbanProxyConfig.clientAppName, }; const response = await this.session.get(UrbanProxyConfig.urls.getProxyList, { headers }); if (response.status !== 200) { await this.handleAfterResponse(response); throw new Error(`Get proxy list failed -> ${response.status} : ${response.data}`); } const resp = response.data; for (const country of resp.countries.elements) { const servers = country.servers.elements || []; for (const element of servers) { this.proxyList.push({ ...element, host: element.address.primary.host, port: element.address.primary.port, ip: element.address.primary.ip, password: element.password || '1', }); } } console.log(`Proxy list available: ${this.proxyList.length}`); return this.proxyList; } public getHttpsAgent(proxy: UrbanProxyElement): HttpsProxyAgent<string> { return new HttpsProxyAgent(proxy .auth_str); } public async getIp(proxy: UrbanProxyElement): Promise<string> { const agent = this.getHttpsAgent(proxy); const response = await axios.get('https://ifconfig.co/json', { httpsAgent: agent, timeout: 10000, }); return response.data; } } export { UrbanProxy, UrbanProxyElement, UrbanProxyConfig }; export default UrbanProxy;