autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
110
skills/account-validation/scripts/proxy_checker.py
Normal file
110
skills/account-validation/scripts/proxy_checker.py
Normal file
@@ -0,0 +1,110 @@
|
||||
"""
|
||||
Proxy rotation checker for V2EX/Discourse account validation.
|
||||
Usage: python proxy_checker.py <accounts_file>
|
||||
"""
|
||||
import requests
|
||||
import json
|
||||
import itertools
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
|
||||
# === CONFIG ===
|
||||
PROXY_SOURCES = [
|
||||
'https://proxylist.geonode.com/api/proxy-list?limit=20&protocols=socks5',
|
||||
'https://api.proxyscrape.com/v4/free-proxy-list/get?request=display_proxies&protocol=socks5&timeout=10000&limit=20',
|
||||
'https://openproxy.space/list/socks5',
|
||||
]
|
||||
|
||||
def fetch_proxies():
|
||||
"""Get fresh SOCKS5 proxies from multiple sources."""
|
||||
proxies = []
|
||||
for url in PROXY_SOURCES:
|
||||
try:
|
||||
r = requests.get(url, timeout=10)
|
||||
if 'geonode' in url:
|
||||
data = r.json()
|
||||
for p in data.get('data', []):
|
||||
proxies.append(f"socks5://{p['ip']}:{p['port']}")
|
||||
elif 'openproxy' in url:
|
||||
for line in r.text.strip().split('\n')[:20]:
|
||||
if ':' in line and not line.startswith('#'):
|
||||
proxies.append(f"socks5://{line.strip()}")
|
||||
else:
|
||||
for line in r.text.strip().split('\n'):
|
||||
if line.strip():
|
||||
proxies.append(f"socks5://{line.strip()}")
|
||||
except Exception as e:
|
||||
print(f" [!] Proxy source failed: {url[:50]}... {e}")
|
||||
|
||||
return list(set(proxies))
|
||||
|
||||
def test_proxies(proxies, test_url, max_test=20):
|
||||
"""Filter proxies that can reach the target."""
|
||||
working = []
|
||||
for proxy_url in proxies[:max_test]:
|
||||
try:
|
||||
proxy_dict = {'http': proxy_url, 'https': proxy_url}
|
||||
r = requests.get(test_url, proxies=proxy_dict, timeout=10,
|
||||
headers={'User-Agent': 'Mozilla/5.0'})
|
||||
if r.status_code == 200 and 'Restricted' not in r.text:
|
||||
working.append(proxy_url)
|
||||
print(f" [+] {proxy_url}")
|
||||
except:
|
||||
pass
|
||||
return working
|
||||
|
||||
def parse_accounts(filepath):
|
||||
"""Parse user:pass file. Returns list of (host, username, password)."""
|
||||
entries = []
|
||||
with open(filepath, encoding='utf-8') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
parts = line.split(':')
|
||||
if len(parts) >= 3:
|
||||
pw = parts[-1]
|
||||
user = parts[-2]
|
||||
host = ':'.join(parts[:-2])
|
||||
entries.append((host, user, pw))
|
||||
|
||||
# Dedup
|
||||
seen = set()
|
||||
unique = []
|
||||
for h, u, p in entries:
|
||||
key = (u.lower().strip(), p)
|
||||
if key not in seen:
|
||||
seen.add(key)
|
||||
unique.append((h, u, p))
|
||||
|
||||
return unique
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python proxy_checker.py <accounts_file>")
|
||||
sys.exit(1)
|
||||
|
||||
filepath = sys.argv[1]
|
||||
print(f"[*] Parsing {filepath}...")
|
||||
accounts = parse_accounts(filepath)
|
||||
print(f"[*] {len(accounts)} unique accounts")
|
||||
|
||||
print("[*] Fetching proxies...")
|
||||
proxies = fetch_proxies()
|
||||
print(f"[*] {len(proxies)} proxies fetched")
|
||||
|
||||
print("[*] Testing proxies against target...")
|
||||
working = test_proxies(proxies, 'https://www.v2ex.com/signin')
|
||||
print(f"[*] {len(working)} working proxies")
|
||||
|
||||
# Save
|
||||
out = os.path.splitext(filepath)[0] + '_parsed.json'
|
||||
with open(out, 'w') as f:
|
||||
json.dump([{"host": h, "user": u, "pass": p} for h, u, p in accounts], f, indent=2, ensure_ascii=False)
|
||||
print(f"[*] Saved parsed accounts to {out}")
|
||||
|
||||
proxy_out = os.path.join(os.path.dirname(filepath), 'working_socks5.txt')
|
||||
with open(proxy_out, 'w') as f:
|
||||
f.write('\n'.join(working))
|
||||
print(f"[*] Saved working proxies to {proxy_out}")
|
||||
Reference in New Issue
Block a user