diff --git a/get_vpn.py b/get_vpn.py index f5741b0..2ec4de5 100644 --- a/get_vpn.py +++ b/get_vpn.py @@ -6,15 +6,12 @@ import requests def get_vpn_servers(): - # Получаем ссылку из секретов Gitea sub_url = os.getenv("VPN_SUB_URL") if not sub_url: print("Ошибка: Переменная окружения VPN_SUB_URL не задана!") sys.exit(1) - # 1. Сначала пробуем сделать запрос по исходной ссылке - # Имитируем заголовки приложения Happ headers = { "User-Agent": "Happ/2.1.0 (iPhone; iOS 15.5; Scale/3.00)", "Accept": "*/*", @@ -25,47 +22,50 @@ def get_vpn_servers(): response = requests.get(sub_url, headers=headers, timeout=15) if response.status_code != 200: - print(f"Ошибка сервера: Статус {response.status_code}") + print(f"Ошибка服务器: Статус {response.status_code}") sys.exit(1) raw_content = response.text.strip() - # 2. Проверяем, не JSON ли это (на случай, если в секрет сразу зашит appConfig URL) + # 1. Проверяем формат JSON try: data = json.loads(raw_content) - print("Обнаружен формат JSON (панель Happ API).") - servers = data.get("data", {}).get("server_user", data) + print("Обнаружен формат JSON.") + + # Если сервер вернул словарь, ищем ключи. Если вернул сразу список — берем его как есть. + if isinstance(data, dict): + servers = data.get("data", {}).get("server_user", data) + else: + servers = data with open("servers.json", "w", encoding="utf-8") as f: json.dump(servers, f, indent=2, ensure_ascii=False) - print("Данные сохранены в файл servers.json") + + # Выводим количество найденных элементов для наглядности в логах + count = len(servers) if isinstance(servers, list) else 1 + print( + f"Данные успешно сохранены в файл servers.json (Элементов: {count})" + ) return + except json.JSONDecodeError: - # Если не JSON, идем дальше + # Если не JSON, двигаемся к проверке Base64 pass - # 3. Проверяем, не Base64 ли это (стандартная подписка) + # 2. Проверяем формат Base64 (на случай изменения выдачи) try: - # Добавляем padding, если строка обрезана (стандартный трюк для base64 в Python) 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() - # Если внутри есть vless/ss/ssr/trojan/vmess ссылки if any( proto in decoded_text for proto in ["vless://", "vmess://", "ss://", "trojan://"] ): - print( - "Обнаружена Base64 подписка. Успешно декодировано в список ссылок." - ) - - # Вариант А: Сохраняем как простой текстовый список серверов + print("Обнаружена Base64 подписка.") with open("servers.txt", "w", encoding="utf-8") as f: f.write(decoded_text) - print("Ссылки сохранены в файл servers.txt") - # Вариант Б: Для удобства сохраняем этот же список в JSON массив links_list = [ line.strip() for line in decoded_text.splitlines() @@ -73,12 +73,12 @@ def get_vpn_servers(): ] with open("servers.json", "w", encoding="utf-8") as f: json.dump(links_list, f, indent=2, ensure_ascii=False) - print("Ссылки также структурированы в servers.json") + print("Ссылки сохранены в servers.txt и servers.json") return - except Exception as b64_err: - print(f"Попытка декодировать Base64 не удалась: {b64_err}") + except Exception: + pass - # 4. Если это и не JSON, и не Base64, возможно это уже готовый сырой текст со ссылками + # 3. Проверяем сырой текст со ссылками if any( proto in raw_content for proto in ["vless://", "vmess://", "ss://", "trojan://"] @@ -95,10 +95,7 @@ def get_vpn_servers(): print("Данные сохранены в servers.txt и servers.json") return - # 5. Если вообще ничего не подошло, сохраняем как есть для анализа - print( - "Неизвестный формат ответа. Сохраняем raw-текст в raw_response.txt для отладки." - ) + print("Неизвестный формат ответа. Сохраняем в raw_response.txt") with open("raw_response.txt", "w", encoding="utf-8") as f: f.write(raw_content) sys.exit(1)