diff --git a/get_vpn.py b/get_vpn.py index 2ec4de5..83e0258 100644 --- a/get_vpn.py +++ b/get_vpn.py @@ -1,109 +1,64 @@ -import base64 -import json import os import sys import requests -def get_vpn_servers(): +def fetch_clash_config(): + # Получаем ссылку-подписку из секретов Gitea/GitHub sub_url = os.getenv("VPN_SUB_URL") if not sub_url: print("Ошибка: Переменная окружения VPN_SUB_URL не задана!") sys.exit(1) + # Имитируем заголовки оригинального клиента OpenClash / Mihomo headers = { - "User-Agent": "Happ/2.1.0 (iPhone; iOS 15.5; Scale/3.00)", + "User-Agent": "Clash.meta; mihomo; OpenClash", "Accept": "*/*", } + # На всякий случай проверяем, есть ли уже в ссылке флаг клиента. + # Если нет — панель может проигнорировать User-Agent, поэтому добавляем флаг принудительно. + if "flag=" not in sub_url: + separator = "&" if "?" in sub_url else "?" + sub_url += f"{separator}flag=clash" + try: - print("Отправка запроса к серверу VPN...") - response = requests.get(sub_url, headers=headers, timeout=15) + print("Отправка запроса к серверу VPN с заголовками Clash...") + response = requests.get(sub_url, headers=headers, timeout=20) if response.status_code != 200: - print(f"Ошибка服务器: Статус {response.status_code}") + print( + f"Ошибка сервера: Статус {response.status_code}. Проверьте ссылку." + ) sys.exit(1) - raw_content = response.text.strip() + content = response.text.strip() - # 1. Проверяем формат JSON - try: - data = json.loads(raw_content) - print("Обнаружен формат JSON.") + # Проверяем, что сервер вернул именно YAML-подобную структуру, а не ошибку JSON + if "proxies:" in content or "proxy-groups:" in content: + print("Успешно получен готовый Clash-конфиг от сервера!") - # Если сервер вернул словарь, ищем ключи. Если вернул сразу список — берем его как есть. - if isinstance(data, dict): - servers = data.get("data", {}).get("server_user", data) - else: - servers = data + # Сохраняем результат в файл + output_file = "clash.yaml" + with open(output_file, "w", encoding="utf-8") as f: + f.write(content) - with open("servers.json", "w", encoding="utf-8") as f: - json.dump(servers, f, indent=2, ensure_ascii=False) + print(f"Конфигурация сохранена в файл: {output_file}") + else: + print("Предупреждение: Сервер вернул ответ, но он не похож на Clash YAML.") + print("Первые 200 символов ответа для отладки:") + print(content[:200]) - # Выводим количество найденных элементов для наглядности в логах - count = len(servers) if isinstance(servers, list) else 1 - print( - f"Данные успешно сохранены в файл servers.json (Элементов: {count})" - ) - return - - except json.JSONDecodeError: - # Если не JSON, двигаемся к проверке Base64 - pass - - # 2. Проверяем формат Base64 (на случай изменения выдачи) - try: - padded_content = raw_content + "=" * (4 - len(raw_content) % 4) - decoded_bytes = base64.b64decode(padded_content) - decoded_text = decoded_bytes.decode("utf-8", errors="ignore").strip() - - if any( - proto in decoded_text - for proto in ["vless://", "vmess://", "ss://", "trojan://"] - ): - print("Обнаружена Base64 подписка.") - with open("servers.txt", "w", encoding="utf-8") as f: - f.write(decoded_text) - - links_list = [ - line.strip() - for line in decoded_text.splitlines() - if line.strip() - ] - with open("servers.json", "w", encoding="utf-8") as f: - json.dump(links_list, f, indent=2, ensure_ascii=False) - print("Ссылки сохранены в servers.txt и servers.json") - return - except Exception: - pass - - # 3. Проверяем сырой текст со ссылками - if any( - proto in raw_content - for proto in ["vless://", "vmess://", "ss://", "trojan://"] - ): - print("Сервер вернул сырой текст со ссылками.") - with open("servers.txt", "w", encoding="utf-8") as f: - f.write(raw_content) - - links_list = [ - line.strip() for line in raw_content.splitlines() if line.strip() - ] - with open("servers.json", "w", encoding="utf-8") as f: - json.dump(links_list, f, indent=2, ensure_ascii=False) - print("Данные сохранены в servers.txt и servers.json") - return - - print("Неизвестный формат ответа. Сохраняем в raw_response.txt") - with open("raw_response.txt", "w", encoding="utf-8") as f: - f.write(raw_content) - sys.exit(1) + # Сохраняем как есть, чтобы вы могли посмотреть, что пришло + with open("response_debug.txt", "w", encoding="utf-8") as f: + f.write(content) + sys.exit(1) except Exception as e: - print(f"Произошла критическая ошибка: {e}") + print(f"Критическая ошибка при запросе: {e}") sys.exit(1) if __name__ == "__main__": - get_vpn_servers() + fetch_clash_config()