""" This plugin provides a command to get random SOCKS5 proxies. """ import os import logging import random import aiohttp import socket import time from datetime import datetime, timedelta import concurrent.futures import asyncio import simplematrixbotlib as botlib import sqlite3 from plugins.common import is_public_destination, html_escape SOCKS5_LIST_URL = 'https://raw.githubusercontent.com/TheSpeedX/SOCKS-List/master/socks5.txt' MAX_TRIES = 64 PROXY_LIST_FILENAME = 'socks5.txt' PROXY_LIST_EXPIRATION = timedelta(hours=8) MAX_THREADS = 64 # lowered to avoid resource exhaustion PROXIES_DB_FILE = 'proxies.db' MAX_PROXIES_IN_DB = 10 def test_proxy(proxy): """Test a SOCKS5 proxy and return (success, proxy, latency).""" try: ip, port = proxy.split(':') start_time = time.time() with socket.create_connection((ip, int(port)), timeout=12) as client: client.sendall(b'\x05\x01\x00') response = client.recv(2) if response == b'\x05\x00': latency = int(round((time.time() - start_time) * 1000)) return True, proxy, latency else: return False, proxy, None except Exception: return False, proxy, None async def download_proxy_list(): try: if not os.path.exists(PROXY_LIST_FILENAME) or \ datetime.now() - datetime.fromtimestamp(os.path.getctime(PROXY_LIST_FILENAME)) > PROXY_LIST_EXPIRATION: logging.info("Downloading SOCKS5 proxy list") async with aiohttp.ClientSession() as session: async with session.get(SOCKS5_LIST_URL, timeout=20) as response: response.raise_for_status() text = await response.text() with open(PROXY_LIST_FILENAME, 'w') as f: f.write(text) logging.info("Proxy list downloaded") return True else: return True except Exception as e: logging.error(f"Error downloading proxy list: {e}") return False def check_db_for_proxy(): try: with sqlite3.connect(PROXIES_DB_FILE) as conn: cursor = conn.cursor() cursor.execute("""CREATE TABLE IF NOT EXISTS proxies ( id INTEGER PRIMARY KEY AUTOINCREMENT, proxy TEXT, latency INTEGER, status TEXT)""") cursor.execute("SELECT proxy, latency FROM proxies WHERE status='working' AND latency<3000 ORDER BY RANDOM() LIMIT 1") row = cursor.fetchone() if row: proxy, latency = row success, _, _ = test_proxy(proxy) if success: return proxy, latency else: cursor.execute("DELETE FROM proxies WHERE proxy=?", (proxy,)) conn.commit() return None, None except Exception as e: logging.error(f"DB error: {e}") return None, None def save_proxy_to_db(proxy, latency): try: with sqlite3.connect(PROXIES_DB_FILE) as conn: cursor = conn.cursor() cursor.execute("""CREATE TABLE IF NOT EXISTS proxies ( id INTEGER PRIMARY KEY AUTOINCREMENT, proxy TEXT, latency INTEGER, status TEXT)""") cursor.execute("INSERT INTO proxies (proxy, latency, status) VALUES (?,?,'working')", (proxy, latency)) conn.commit() except Exception as e: logging.error(f"Error saving proxy: {e}") async def handle_command(room, message, bot, prefix, config): match = botlib.MessageMatch(room, message, bot, prefix) if match.is_not_from_this_bot() and match.prefix() and match.command("proxy"): logging.info("Received !proxy command") working_proxy, latency = check_db_for_proxy() if working_proxy: safe_proxy = html_escape(working_proxy) await bot.api.send_markdown_message(room.room_id, f"✅ Using cached working SOCKS5 Proxy: **{safe_proxy}** - Latency: **{latency} ms**") return if not await download_proxy_list(): await bot.api.send_markdown_message(room.room_id, "Error downloading proxy list") return try: with open(PROXY_LIST_FILENAME, 'r') as f: socks5_proxies = [line.replace("socks5://", "") for line in f.read().splitlines()] socks5_proxies = [p for p in socks5_proxies if is_public_destination(p.split(':')[0])] random.shuffle(socks5_proxies) loop = asyncio.get_running_loop() tested = 0 with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor: futures = [loop.run_in_executor(executor, test_proxy, proxy) for proxy in socks5_proxies[:MAX_TRIES]] for future in asyncio.as_completed(futures): success, proxy, latency = await future if success: safe_proxy = html_escape(proxy) await bot.api.send_markdown_message(room.room_id, f"✅ Anonymous SOCKS5 Proxy: **{safe_proxy}** - Latency: **{latency} ms**") save_proxy_to_db(proxy, latency) tested += 1 if tested >= MAX_PROXIES_IN_DB: break if tested == 0: await bot.api.send_markdown_message(room.room_id, "❌ No working anonymous SOCKS5 proxy found") except Exception as e: logging.error(f"Error handling !proxy command: {e}") await bot.api.send_markdown_message(room.room_id, "❌ Error handling !proxy command") __version__ = "1.0.2" __author__ = "Funguy Bot" __description__ = "Working SOCKS5 proxy finder (SSRF‑safe, async)" __help__ = """
!proxy – Random working SOCKS5 proxy

Fetches, tests, and returns a random working SOCKS5 proxy with latency.

"""