diff --git a/main.py b/main.py index 4828938..e229a6e 100644 --- a/main.py +++ b/main.py @@ -7,103 +7,110 @@ import sys import subprocess import json -PROXIES_LIST = "https://nnp.nnchan.ru/mahoproxy.php?u=https://api.sandvpn.com/fetch-free-proxys" +PROXIES_LIST_URL = "https://nnp.nnchan.ru/mahoproxy.php?u=https://api.sandvpn.com/fetch-free-proxys" SPEEDTEST_URL = "http://212.183.159.230/5MB.zip" -def get_proxies(): - request = requests.get(PROXIES_LIST) - if request.status_code == 200: - return request.json() - else: - request.raise_for_status() - +def fetch_proxies(): + """Fetch the list of proxies from the defined URL.""" + response = requests.get(PROXIES_LIST_URL) + response.raise_for_status() + return response.json() -def get_best_proxy(proxy_json): - proxy_times = [] - for i, item in enumerate(proxy_json): - if item["host"] != "" and item["country"] != "Russia": - proxy_str = "" - print(f'Testing {item["host"]}:{item["port"]}') - if item["username"]: - proxy_str = f'{item["username"]}:{item["password"]}@{item["host"]}:{item["port"]}' - else: - proxy_str = f'{item["host"]}:{item["port"]}' - with io.BytesIO() as f: - start = time.perf_counter() - try: - r = requests.get(SPEEDTEST_URL, stream=True, proxies={"http": proxy_str}, timeout=20) - except: - print("Proxy is dead, skiping...") - del proxy_json[i] - continue - total_length = r.headers.get('content-length') - dl = 0 - if total_length is None: # no content length header - print("no content") - f.write(r.content) - elif int(total_length) == 5242880: - for chunk in r.iter_content(1024): - dl += len(chunk) - f.write(chunk) - done = int(30 * dl / int(total_length)) - if done > 3 and (dl//(time.perf_counter() - start) / 100000) < 1.0: - print("\nProxy is too slow, skiping...") - start = 500 - break - sys.stdout.write("\r[%s%s] %s Mbps" % ('=' * done, ' ' * (30-done), dl//(time.perf_counter() - - start) / 100000)) - else: - del proxy_json[i] - continue - item.update({"time": round(time.perf_counter() - start, 2)}) - proxy_times.append(item) - print("\n") - - else: - del proxy_json[i] +def is_valid_proxy(proxy): + """Check if the proxy is valid and not from Russia (youtube is slowed down there).""" + return proxy["host"] and proxy["country"] != "Russia" - best_five_proxies = sorted(proxy_times, key=lambda x: x['time'])[:5] - return best_five_proxies +def construct_proxy_string(proxy): + """Construct a proxy string from the proxy dictionary.""" + if proxy.get("username"): + return f'{proxy["username"]}:{proxy["password"]}@{proxy["host"]}:{proxy["port"]}' + return f'{proxy["host"]}:{proxy["port"]}' + +def test_proxy(proxy): + """Test the proxy by measuring the download time.""" + proxy_str = construct_proxy_string(proxy) + print(f'Testing {proxy_str}') + + start_time = time.perf_counter() + try: + response = requests.get(SPEEDTEST_URL, stream=True, proxies={"http": proxy_str}, timeout=5) + response.raise_for_status() # Ensure we raise an error for bad responses + + total_length = response.headers.get('content-length') + if total_length is None or int(total_length) != 5242880: + print("No content or unexpected content size.") + return None + + with io.BytesIO() as f: + download_time, downloaded_bytes = download_with_progress(response, f, total_length, start_time) + return {"time": download_time, **proxy} # Include original proxy info + except requests.RequestException: + print("Proxy is dead, skipping...") + return None + +def download_with_progress(response, f, total_length, start_time): + """Download content from the response with progress tracking.""" + downloaded_bytes = 0 + for chunk in response.iter_content(1024): + downloaded_bytes += len(chunk) + f.write(chunk) + done = int(30 * downloaded_bytes / int(total_length)) + if done > 3 and (downloaded_bytes//(time.perf_counter() - start_time) / 100000) < 1.0: + print("\nProxy is too slow, skipping...") + return float('inf'), downloaded_bytes + sys.stdout.write("\r[%s%s] %s Mbps" % ('=' * done, ' ' * (30-done), downloaded_bytes//(time.perf_counter() - + start_time) / 100000)) + sys.stdout.write("\n") + return round(time.perf_counter() - start_time, 2), downloaded_bytes + +def get_best_proxies(proxies): + """Return the top five proxies based on speed.""" + proxy_times = [test_proxy(proxy) for proxy in proxies if is_valid_proxy(proxy)] + return sorted(filter(None, proxy_times), key=lambda x: x['time'])[:5] + +def save_proxies_to_file(proxies, filename="proxy.json"): + """Save the best proxies to a JSON file.""" + with open(os.path.join(os.path.dirname(__file__), filename), "w") as f: + json.dump(proxies, f, indent=4) def update_proxies(): - proxy_json = get_proxies() - best_proxy_json = get_best_proxy(proxy_json) - with open(os.path.abspath(__file__).split("main.py")[0]+"proxy.json", "w") as f: - f.write(json.dumps(best_proxy_json, indent=4)) - print("All done.") - + """Update the proxies list and save the best ones.""" + proxies = fetch_proxies() + best_proxies = get_best_proxies(proxies) + save_proxies_to_file(best_proxies) + print("All done.") def run_yt_dlp(): - proxy_url = "" - error = True - while error: - with open(os.path.abspath(__file__).split("main.py")[0]+"proxy.json", "r") as f: - proxy_dict = random.choice(json.load(f)) - print(f"Using proxy based in {proxy_dict['city']}, {proxy_dict['country']}") - if proxy_dict["username"]: - proxy_url = f'{proxy_dict["username"]}:{proxy_dict["password"]}@{proxy_dict["host"]}:{proxy_dict["port"]}' - else: - proxy_url = f'{proxy_dict["host"]}:{proxy_dict["port"]}' - subprocess.run(f"yt-dlp --color always --proxy '{proxy_url}' {" ".join([str(arg) for arg in sys.argv])} 2>&1 | tee tempout", shell=True) - with open("tempout", 'r') as log_fl: - if 'Sign in to' in log_fl.readlines()[-1]: - error = True - print("Got 'Sign in to confirm' error. Trying again with another proxy...") - else: - error = False - os.remove("tempout") + """Run yt-dlp with a randomly selected proxy.""" + while True: + with open("proxy.json", "r") as f: + proxy = random.choice(json.load(f)) + proxy_str = construct_proxy_string(proxy) + print(f"Using proxy from {proxy['city']}, {proxy['country']}") + if execute_yt_dlp_command(proxy_str): + break # Exit loop if command was successful + print("Got 'Sign in to confirm' error. Trying again with another proxy...") + +def execute_yt_dlp_command(proxy_str): + """Execute the yt-dlp command with the given proxy.""" + command = f"yt-dlp --color always --proxy '{proxy_str}' {" ".join([str(arg) for arg in sys.argv])} 2>&1 | tee tempout" + subprocess.run(command, shell=True) + with open("tempout", 'r') as log_fl: + return 'Sign in to' not in log_fl.read() def main(): - try: - if "update" in sys.argv: - update_proxies() - elif len(sys.argv) == 1: - print("usage: main.py update | \n\nScript for starting yt-dlp with best free proxy\n\nCommands:\n update Update best proxy\n") - else: - sys.argv.pop(0) - run_yt_dlp() - except KeyboardInterrupt: - print("Canceled by user") + """Main function to handle script arguments and execute the appropriate command.""" + try: + if "update" in sys.argv: + update_proxies() + elif len(sys.argv) < 2: + print("usage: main.py update | \nScript for starting yt-dlp with best free proxy\nCommands:\n update Update best proxy") + else: + sys.argv.pop(0) + run_yt_dlp() + except KeyboardInterrupt: + print("Canceled by user") -main() +if __name__ == "__main__": + main() diff --git a/proxy.json b/proxy.json index 78da9f7..6cc3a13 100644 --- a/proxy.json +++ b/proxy.json @@ -1,29 +1,6 @@ [ { - "city": "Chicago 2", - "country": "USA", - "host": "107.152.38.99", - "new": false, - "paid": false, - "password": "L5KT7rSkCrxn8mm4HngTbK8f4k", - "port": "3128", - "premium": true, - "username": "chicago_squid_user", - "time": 15.72 - }, - { - "city": "New York 2", - "country": "USA", - "host": "107.152.44.132", - "new": false, - "paid": false, - "password": "Xs6QjgCMeiGsX68KMdjnRJbmLmD", - "port": "3128", - "premium": true, - "username": "nc_squid_user", - "time": 17.03 - }, - { + "time": 7.21, "city": "New York 1", "country": "USA", "host": "107.152.43.179", @@ -32,31 +9,54 @@ "password": "pJTg94JCukVjz2b", "port": "3128", "premium": true, - "username": "ny_premium", - "time": 20.92 + "username": "ny_premium" }, { - "city": "Hesse", - "country": "Germany", - "host": "162.19.230.101", + "time": 7.99, + "city": "Chicago 2", + "country": "USA", + "host": "107.152.38.99", "new": false, "paid": false, - "password": "enfo8BM3YDbGfyANYJRCKyL7hGrH", + "password": "L5KT7rSkCrxn8mm4HngTbK8f4k", "port": "3128", - "premium": false, - "username": "hesse_squid_user", - "time": 62594.22 + "premium": true, + "username": "chicago_squid_user" }, { - "city": "London", - "country": "UK", - "host": "83.147.17.103", + "time": 12.86, + "city": "New York 2", + "country": "USA", + "host": "107.152.44.132", "new": false, "paid": false, - "password": "dsRLomjPDynq7mJQmhKX7QJCLid", + "password": "Xs6QjgCMeiGsX68KMdjnRJbmLmD", + "port": "3128", + "premium": true, + "username": "nc_squid_user" + }, + { + "time": 13.09, + "city": "Los Angeles", + "country": "USA", + "host": "107.152.47.150", + "new": false, + "paid": false, + "password": "!K3o!nHrs4M5Lxtg", "port": "3128", "premium": false, - "username": "london_squid_user", - "time": 62614.32 + "username": "la_premium" + }, + { + "time": Infinity, + "city": "Chicago 3", + "country": "USA", + "host": "107.152.38.47", + "new": false, + "paid": false, + "password": "yirXePSAqCE8jhLg88FBTfCz", + "port": "3128", + "premium": false, + "username": "chicago_squid_user_free" } ] \ No newline at end of file