NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name universal proxy parser // @namespace dimaslanjaka:universal-parser-proxy // @version 1.3 // @description parse proxy from site page // @author dimaslanjaka // @supportURL https://github.com/dimaslanjaka/php-proxy-hunter/issues // @homepageURL https://dimaslanjaka.github.io/ // @contributionURL https://github.com/dimaslanjaka/php-proxy-hunter // @license MIT // @match *://hidemy.name/*/proxy-list/* // @match *://hidemy.io/*/proxy-list/* // @match *://hide.mn/*/proxy-list/* // @match *://hidemyna.me/*/proxy-list/* // @match *://hidemyname.io/*/proxy-list/* // @match *://*.sslproxies.org/* // @match *://*.socks-proxy.net/* // @match *://*.us-proxy.org/* // @match *://www.proxydocker.com/* // @match *://spys.one/* // @match *://proxypremium.top/* // @match *://proxyscrape.com/* // @match *://squidproxyserver.com/* // @match *://geonode.com/free-proxy-list // @match *://aliveproxy.com/* // @match *://free-proxy-list.net/* // @match *://free-proxy.cz/* // @match *://www.blackhatworld.com/* // @match *://www.cool-proxy.net/* // @match *://www.cybersyndrome.net/* // @match *://www.echolink.org/* // @match *://www.gatherproxy.com/* // @match *://www.idcloak.com/* // @match *://www.ip-adress.com/* // @match *://www.mrhinkydink.com/* // @match *://www.samair.ru/* // @match *://www.ultraproxies.com/* // @match *://www.us-proxy.org/* // @match *://www.xroxy.com/* // @match *://advanced.name/* // @match *://api.openproxylist.xyz/* // @match *://api.proxyscrape.com/* // @match *://apiproxyfree.com/* // @match *://cyber-hub.pw/* // @match *://free-proxy-list.com/* // @match *://hidemy.name/* // @match *://list.proxylistplus.com/* // @match *://openproxy.space/* // @match *://pastebin.com/* // @match *://premiumproxy.net/* // @match *://premproxy.com/* // @match *://proxy-daily.com/* // @match *://proxy-list.org/* // @match *://proxylist.geonode.com/* // @match *://proxyservers.pro/* // @match *://raw.githubusercontent.com/* // @match *://smallseotools.com/* // @match *://spys.me/* // @match *://vpnoverview.com/* // @match *://www.freeproxy.world/* // @match *://www.netzwelt.de/* // @match *://www.proxy-list.download/* // @match *://www.proxydocker.com/* // @match *://www.proxynova.com/* // @match *://www.proxyscan.io/* // @match *://proxydb.net/* // @match *://proxyhub.me/* // @match *://www.ditatompel.com/* // @match *://iptotal.io/* // @match *://www.lumiproxy.com/* // @match *://free.proxy-sale.com/* // @match *://freeproxylist.cc/* // @match *://proxy-tools.com/* // @match *://fineproxy.org/* // @match *://proxy-spider.com/* // @match *://vakhov.github.io/fresh-proxy-list* // @match *://www.kxdaili.com/* // @match *://www.kuaidaili.com/* // @match *://www.ip3366.net/* // @match *://www.my-proxy.com/* // @match *://www.89ip.cn/* // @match *://api.proxy-checker.net/* // @match *://libernet.uo1.net/* // @match *://proxyelite.info/* // @require https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js // @downloadURL https://raw.githack.com/dimaslanjaka/php-proxy-hunter/master/userscripts/universal.user.js // @updateURL https://raw.githack.com/dimaslanjaka/php-proxy-hunter/master/userscripts/universal.meta.js // ==/UserScript== (function () { 'use strict'; const md5 = function (text) { // eslint-disable-next-line no-undef return CryptoJS.MD5(text).toString(); }; const isMD5Format = function (str) { // Regular expression to check if a string is a valid MD5 hash const md5Regex = /^[a-f0-9]{32}$/i; return md5Regex.test(str); }; /** * Split a string into chunks of lines. * @param {string} input - The input string to split. * @param {number} linesPerChunk - Maximum number of lines per chunk. * @returns {string[]} An array of chunks, where each chunk is a string with up to `linesPerChunk` lines. */ const splitStringByLines = function (input, linesPerChunk) { // Split the input string by lines const lines = input.split('\n'); // Initialize an array to hold chunks of lines const chunks = []; // Loop through lines and group into chunks for (let i = 0; i < lines.length; i += linesPerChunk) { // Slice the array to get the chunk of lines const chunk = lines.slice(i, i + linesPerChunk); // Join the chunk back into a single string and push it to the array chunks.push(chunk.join('\n')); } return chunks; }; /** * Upload and check proxy. * @param {string} dataToSend - The proxy data to send. */ var addProxyFun = function (dataToSend) { if (!dataToSend) return; if (typeof dataToSend !== 'string') dataToSend = JSON.stringify(dataToSend, null, 2); /** * Check if the data has already been sent by looking at local storage. * @param {string|Object} data - The data to check. * @returns {boolean} True if the data has already been sent. */ var hasDataBeenSent = function (data) { if (typeof data !== 'string') data = md5(JSON.stringify(data)); if (!isMD5Format(data)) data = md5(data); var sentData = localStorage.getItem('sentData'); var result = sentData && sentData.includes(data); console.log(data, 'is same', result); return result; }; /** * Mark data as sent by saving it in local storage. * @param {string|Object} data - The data to be marked as sent. */ var markDataAsSent = function (data) { // skip null data if (!data) return; // Check if data has already been sent if (!hasDataBeenSent(data)) { if (typeof data !== 'string') { data = md5(JSON.stringify(data)); // Convert object data to MD5 hash } if (!isMD5Format(data)) { data = md5(data); // Ensure data is in MD5 format } try { var sentData = localStorage.getItem('sentData') || ''; sentData += data + '\n'; // Append the entire data localStorage.setItem('sentData', sentData); } catch (_e) { console.log('RESET LOCAL STORAGE DATA'); // reset local storage localStorage.setItem('sentData', data); } } }; if (hasDataBeenSent(dataToSend)) return; var services = [ // php proxy hunter 'http://localhost/proxyAdd.php', 'http://localhost/proxyCheckerParallel.php', 'https://sh.webmanajemen.com/proxyAdd.php', 'https://sh.webmanajemen.com/proxyCheckerParallel.php', // python proxy hunter 'https://sh.webmanajemen.com:8443/proxy/check', 'https://localhost:4000/proxy/check', 'https://localhost:7000/proxy/check', 'https://localhost:8000/proxy/check' ]; /** * Perform fetch with a delay. * @param {string} url - The URL to which the fetch request is made. * @param {string} dataToSend - The data to be sent in the POST request. * @returns {Promise} - Returns a promise that resolves after the fetch completes. */ var fetchWithDelay = function (url, dataToSend) { return new Promise(function (resolve, reject) { setTimeout(function () { fetch(url, { signal: AbortSignal.timeout(5000), method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Greasemonkey-Script': '1' }, body: dataToSend }) .then(function (response) { if (!response.ok) { // Log all response headers var headers = []; response.headers.forEach(function (value, name) { headers.push({ name: name, value: value }); }); return response.text().then(function (body) { return reject({ status: response.status + ' ' + response.statusText, message: 'Network response to ' + url + ' was not ok', headers: headers, body: body }); }); } return response.text(); }) .then(function (data) { console.log(data); resolve(); }) .catch(function (error) { reject({ message: 'There was a problem with your fetch operation: (' + error.message + ')' }); }); }, 1000); // 1 second delay }); }; // Assuming services and splitStringByLines are already defined services.forEach(function (url) { var do_upload = function (str_data) { fetchWithDelay(url, 'proxy=' + encodeURIComponent(str_data)) .then(function () { return fetchWithDelay(url, 'proxies=' + encodeURIComponent(str_data)); }) .catch(function (error) { console.error('Failed to fetch with delay:', error); }); }; var split_body = splitStringByLines(dataToSend, 100); if (url.indexOf('proxyCheckerParallel') === -1) { split_body.forEach(do_upload); } else { var item = split_body[Math.floor(Math.random() * split_body.length)]; do_upload(item); } markDataAsSent(dataToSend); }); }; /** * Function to parse proxy data from the document. * @returns {Promise} - A promise that resolves with an array of proxy data objects. */ var parse_proxy_db_net = function () { return new Promise(function (resolve) { var regex = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{2,5})/; var result = []; var a = Array.prototype.slice.call(document.getElementsByClassName('spy14')); for (var outerLoopIndex = 0; outerLoopIndex < a.length; outerLoopIndex++) { // Renamed outer loop variable if (a[outerLoopIndex].innerText.includes(':')) { result.push({ raw: a[outerLoopIndex].innerText }); } } var tables = Array.prototype.slice.call(document.querySelectorAll('table')); for (var tableLoopIndex = 0; tableLoopIndex < tables.length; tableLoopIndex++) { // Renamed outer loop variable for tables var table = tables[tableLoopIndex]; var tr = Array.prototype.slice.call(table.querySelectorAll('tr')); for (var i = 0; i < tr.length; i++) { // Inner loop variable remains i var td = Array.prototype.slice.call(tr[i].querySelectorAll('td')); if (td[0]) { var test = regex.test(td[0].innerText); if (test) result.push({ raw: td[0].innerText }); } } } resolve(result); }); }; /** * Function to parse HideMe proxy data. * @returns {Promise<any[]>} - A promise that resolves with an array of proxy data objects. */ var parse_hideme_jquery = function () { return new Promise(function (resolve) { var result = []; $('.table_block>table>tbody>tr').each(function (i, e) { var tr = $(e); var tdList = tr.children('td'); var host = tdList.get(0).innerText; var port = tdList.get(1).innerText; result.push({ raw: host + ':' + port }); }); resolve(result); }); }; /** * Function to parse proxy data from a table. * @returns {Promise<any[]>} - A promise that resolves with an array of proxy data objects. */ var parse_prem_proxy = function () { return new Promise(function (resolve) { // Select all table elements on the page var tables = Array.prototype.slice.call(document.querySelectorAll('table')); var ipOnly = /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/gm; var objectWrapper = []; // Loop through each table element using a for loop for (var i = 0; i < tables.length; i++) { var table = tables[i]; var rows = Array.prototype.slice.call(table.querySelectorAll('tr')); for (var j = 0; j < rows.length; j++) { var row = rows[j]; var td = Array.prototype.slice.call(row.querySelectorAll('td')); var texts = td .map(function (el) { return el.innerText; }) .filter(function (str) { return typeof str === 'string' && str.trim().length > 0; }); if (ipOnly.test(texts.join(' '))) { objectWrapper.push({ raw: texts[0], ip: texts[0].split(':')[0], port: texts[0].split(':')[1], type: texts[2], country: texts[3], anonymity: texts[4], https: texts[5] }); } } } resolve(objectWrapper); }); }; /** * Function to parse proxy data from a table. * @returns {Promise<any[]>} - A promise that resolves with an array of proxy data objects. */ var parse_proxylistplus = function () { return new Promise(function (resolve) { // Select all table elements on the page var tables = Array.prototype.slice.call(document.querySelectorAll('table')); var ipOnly = /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/gm; var objectWrapper = []; // Loop through each table element using a for loop for (var i = 0; i < tables.length; i++) { var table = tables[i]; var rows = Array.prototype.slice.call(table.querySelectorAll('tr')); for (var j = 0; j < rows.length; j++) { var row = rows[j]; var td = Array.prototype.slice.call(row.querySelectorAll('td')); var texts = td .map(function (el) { return el.innerText; }) .filter(function (str) { return typeof str === 'string' && str.trim().length > 0; }); if (ipOnly.test(texts.join(' '))) { var item = { raw: texts[0] + ':' + texts[1], ip: texts[0], port: texts[1], type: texts[2], country: texts[3], anonymity: texts[4], https: texts[5] }; objectWrapper.push(item); } } } resolve(objectWrapper); }); }; // parse_proxylistplus().then(console.log); /** * Function to parse the second and third row proxy data from a table. * @returns {Promise<any[]>} - A promise that resolves with an array of proxy data objects. */ var parse_second_and_third_row = function () { return new Promise(function (resolve) { // Select all table elements on the page var tables = Array.prototype.slice.call(document.querySelectorAll('table')); var ipOnly = /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/gm; var objectWrapper = []; // Loop through each table element using a for loop for (var i = 0; i < tables.length; i++) { var table = tables[i]; var rows = Array.prototype.slice.call(table.querySelectorAll('tr')); for (var j = 0; j < rows.length; j++) { var row = rows[j]; var td = Array.prototype.slice.call(row.querySelectorAll('td')); var texts = td .map(function (el) { return el.innerText; }) .filter(function (str) { return typeof str === 'string' && str.trim().length > 0; }); if (ipOnly.test(texts.join(' '))) { objectWrapper.push({ raw: texts[1] + ':' + texts[2], ip: texts[0], port: texts[1], type: texts[2], country: texts[3], anonymity: texts[4], https: texts[5] }); } } } resolve(objectWrapper); }); }; /** * Function to parse the first and second row proxy data from a table. * @returns {Promise<any[]>} - A promise that resolves with an array of proxy data objects. */ var parse_first_and_second_row = function () { return new Promise(function (resolve) { // Select all table elements on the page var tables = Array.prototype.slice.call(document.querySelectorAll('table')); var ipOnly = /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/gm; var objectWrapper = []; // Loop through each table element using a for loop for (var i = 0; i < tables.length; i++) { var table = tables[i]; var rows = Array.prototype.slice.call(table.querySelectorAll('tr')); for (var j = 0; j < rows.length; j++) { var row = rows[j]; var buildObject = { raw: null, code: null, anonymity: null, ssl: null, google: null, alert: null, type: 'http', test: null }; var td = row.querySelectorAll('td'); var proxy = td[0]; var port = td[1]; var countryCode = td[2]; var anonymity = td[4]; var google = td[5]; var ssl = td[6]; if (proxy && ssl && ipOnly.test(proxy.innerText)) { buildObject.raw = proxy.innerText.trim() + ':' + port.innerText.trim(); buildObject.google = /^yes/.test(google.innerText.trim()) ? true : false; buildObject.ssl = /^yes/.test(ssl.innerText.trim()) ? true : false; buildObject.code = countryCode.innerText.trim(); switch (anonymity.innerText.trim()) { case 'elite proxy': buildObject.anonymity = 'H'; break; case 'anonymous': buildObject.anonymity = 'A'; break; default: buildObject.anonymity = 'N'; break; } objectWrapper.push(buildObject); } } } resolve(objectWrapper); }); }; /** * Function to parse IP:PORT from the first row. * @returns {Promise<any[]>} - A promise that resolves with an array of IP:PORT data objects. */ var parse_first_row_ip_port = function () { return new Promise(function (resolve) { var regex = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})$/; var result = []; var spy14Elements = Array.prototype.slice.call(document.getElementsByClassName('spy14')); for (var i = 0; i < spy14Elements.length; i++) { if (spy14Elements[i].innerText.includes(':')) { result.push({ raw: spy14Elements[i].innerText }); } } var tables = Array.prototype.slice.call(document.querySelectorAll('table')); for (var j = 0; j < tables.length; j++) { var table = tables[j]; var trElements = Array.prototype.slice.call(table.querySelectorAll('tr')); for (var k = 0; k < trElements.length; k++) { var tdElements = Array.prototype.slice.call(trElements[k].querySelectorAll('td')); if (tdElements.length > 0 && regex.test(tdElements[0].innerText)) { result.push({ raw: tdElements[0].innerText }); } } } resolve(result); }); }; /** * Extracts IP:PORT pairs from a given input string. * * @param {string} input - The input string containing IP:PORT pairs. * @returns {string[]} An array of IP:PORT pairs found in the input string. */ var extractIpPortPairs = function (input) { if (!input) return []; // Regular expression to match IP:PORT var regex = /(?:[0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{1,5}/g; return input.match(regex) || []; }; /** * Extracts unique IP:PORT pairs from the body and specific elements in the DOM. * * @returns {Promise<any[]>} A promise that resolves with an array of unique IP:PORT objects. */ var extractIpPortFromBody = function () { var result = []; var area = document.querySelectorAll('textarea,td'); // Extract IP:PORT pairs from the body content result.push.apply(result, extractIpPortPairs(document.body.innerHTML)); // Extract IP:PORT pairs from the values of textarea and td elements area.forEach(function (el) { result.push.apply(result, extractIpPortPairs(el.value)); }); // Extract IP:PORT pairs from div elements with class 'list' var divList = document.querySelectorAll('div.list'); divList.forEach(function (el) { result.push.apply(result, extractIpPortPairs(el.innerHTML)); }); // Remove duplicates by filtering the array var unique = result.filter(function (str, index, self) { return ( index === self.findIndex(function (t) { return t === str; }) ); }); // Map the unique IP:PORT pairs to an object structure var map = unique.map(function (str) { return { raw: str }; }); return Promise.resolve(map); }; /** * extract IPs from string * @param {string} str * @returns */ const findIPv4Addresses = function (str) { const ipv4Pattern = /\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/g; return str.match(ipv4Pattern) || []; }; /** * free.proxy-sale.com parser * * extract only IP * @returns {Promise<{ raw: string }[]>} */ var freeProxySale = function () { return new Promise(function (resolve) { var result = []; var proxyTable = document.querySelectorAll('.proxy__table'); proxyTable.forEach(function (wrapper) { Array.from(wrapper.querySelectorAll('[class^=css-]')).forEach(function (el) { var ips = findIPv4Addresses(el.textContent); if (ips.length > 0) { ips.forEach(function (ip) { result.push({ raw: ip + ':80' }); result.push({ raw: ip + ':443' }); result.push({ raw: ip + ':8080' }); result.push({ raw: ip + ':8000' }); }); } }); }); resolve(result); }); }; /** * Parses proxy information from multiple sources. * Returns a promise that resolves with a string containing valid IP:PORT combinations. * * @returns {Promise<string>} A promise that resolves with a string of valid proxy addresses. */ var parse_all = function () { return new Promise(function (resolve) { /** * @type {Promise<{ raw: string }[]>[]} */ var all = [ freeProxySale(), parse_first_and_second_row(), parse_hideme_jquery(), parse_first_row_ip_port(), parse_second_and_third_row(), parse_proxylistplus(), parse_prem_proxy(), parse_proxy_db_net(), extractIpPortFromBody() ]; Promise.all(all) .then(function (results) { // flatting var flat = results.flat().filter(function (item) { if (!item) return false; var str = typeof item === 'string' ? item : JSON.stringify(item); var regex = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})/gm; return regex.test(str); }); // remove non IP:PORT var additionalItems = []; var filteredItems = flat .map(function (item) { var valid = false; var regex_ip = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/gm; var regex_port = /(\d{1,5})/gm; var regex_proxy = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})/gm; if (typeof item === 'object') { if (item.raw) { // validate proxy is valid valid = regex_proxy.test(item.raw); } if (!valid) { if (item.ip) { if (regex_proxy.test(item.ip)) { item.raw = item.ip; item.ip = item.raw.split(':')[0]; } } } // re-validate string length no more than 21 var no_more_than_21 = false; if (item.raw.length > 21) { no_more_than_21 = true; var extract = extract_proxies(item.raw); if (extract.length > 0) { for (var i = 0; i < extract.length; i++) { var ex = extract[i]; if (i === 0) { item.raw = ex.ip + ':' + ex.port; } else { additionalItems.push({ raw: ex.ip + ':' + ex.port }); } } } } if (item.raw && !no_more_than_21) { // fix IP:PORT var split = item.raw.split(':'); var build_proxy = []; if (split.length > 1) { split.forEach(function (str) { if (regex_ip.test(str)) { build_proxy[0] = str; } else if (regex_port.test(str)) { build_proxy[1] = str; } }); if (regex_proxy.test(build_proxy.join(':'))) { item.raw = build_proxy.join(':'); } else if (!regex_proxy.test(item.raw)) { console.error(item.raw, 'invalid regex_proxy'); return { raw: '' }; } } } } return item; }) .filter(function (item) { // validate proxy length return item && item.raw.length > 0 && item.raw.length <= 21; }); // unique var uniqueItems = [...filteredItems, ...additionalItems].filter(function (obj, index, self) { return ( index === self.findIndex(function (t) { return t.raw === obj.raw; }) ); }); // build to string var build = ''; for (var i = 0; i < uniqueItems.length; i++) { var item = uniqueItems[i]; if (build.indexOf(item.raw) === -1) { build += item.raw + '\n'; } } // const result = uniqueArray.map((obj) => JSON.stringify(obj, null, 2)).join("\n"); resolve(build); }) .catch(function (error) { console.error(error); resolve('<empty proxies>'); }); }); }; /** * Function to sanitize HTML by removing specified tags and the 'style' attribute. * @param {string} html - The HTML content to sanitize. * @returns {string} The sanitized HTML content. */ var sanitizeHtml = function (html) { var doc = new DOMParser().parseFromString(html, 'text/html'); // Tags to remove var tagsToRemove = ['img', 'script', 'iframe', 'link', 'ins']; tagsToRemove.forEach(function (tagName) { var tags = doc.getElementsByTagName(tagName); for (var i = tags.length - 1; i >= 0; i--) { tags[i].parentNode.removeChild(tags[i]); } }); // Remove 'style' attribute from all tags var allTags = doc.getElementsByTagName('*'); for (var i = 0; i < allTags.length; i++) { allTags[i].removeAttribute('style'); } var filteredHtml = doc.documentElement.outerHTML; var doc2 = new DOMParser().parseFromString(filteredHtml, 'text/html'); var elements = []; doc2.querySelectorAll('textarea,table,.list').forEach(function (el) { elements.push(el.outerHTML); }); return elements.join('\n'); }; /** * Monitors changes to the body's HTML content and performs actions when changes are detected. */ var monitorBodyChanges = function () { var lastHtml = ''; setInterval(function () { var currentHtml = document.body.innerHTML; var sanitizedHtml = sanitizeHtml(currentHtml); if (sanitizedHtml !== lastHtml) { lastHtml = sanitizedHtml; console.log('body changed'); parse_all().then(addProxyFun); } }, 3000); // Check every 3 seconds }; setTimeout(monitorBodyChanges, 3000); const btn = document.createElement('button'); btn.id = 'php-proxy-hunter-grab-proxy'; btn.setAttribute( 'style', 'position: fixed; top: 50%; left: 0; transform: translateY(-50%); opacity: 0.6; margin-left: 1.2em; color: white; background-color: black;' ); btn.innerText = 'PARSE PROXIES'; btn.classList.add('btn', 'button', 'btn-primary'); btn.onclick = function () { parse_all() .then(function (result) { addProxyFun(result); var htmlContent = ` <!DOCTYPE html> <html> <head> <title>JSON Data</title> <style> body { background-color: #121212; color: #ffffff; font-family: Arial, sans-serif; padding: 20px; } pre { white-space: pre-wrap; /* Ensures long lines wrap */ word-wrap: break-word; /* Prevents overflowing */ } </style> </head> <body><pre>${result.trim()}</pre></body> </html>`; window.open(URL.createObjectURL(new Blob([htmlContent], { type: 'text/html' })), 'width=800,height=600'); }) .catch(function (error) { console.error(error); }); }; document.body.appendChild(btn); })(); /** * Extracts IP addresses and ports from a given text. * @param {string} text - The multiline text to extract IP:PORT from. * @returns {Array<{ip: string, port: string}>} - An array of objects containing IP and port. */ function extract_proxies(text) { // Regular expression to match IP addresses and ports const regex = /(\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b):([0-9]{1,5})/g; // Extract IP:PORT matches const matches = []; let match; while ((match = regex.exec(text)) !== null) { matches.push({ ip: match[1], port: match[2] }); } return matches; }