import os import sys import requests def fetch_and_prepare_configs(): # Забираем ссылку из секретов Gitea/GitHub sub_url = os.getenv("VPN_SUB_URL") if not sub_url: print("Ошибка: Переменная окружения VPN_SUB_URL не задана!") sys.exit(1) # Имитируем заголовки оригинального ядра Mihomo (Clash.Meta) для OpenClash headers = { "User-Agent": "Mihomo/1.18.3 Clash.Meta OpenClash", "Accept": "application/yaml, text/yaml, */*", "Connection": "keep-alive", } # Принудительно заставляем панель выдать мета-конфиг if "flag=" not in sub_url: separator = "&" if "?" in sub_url else "?" sub_url += f"{separator}flag=meta" try: print("Отправка запроса к серверу VPN...") response = requests.get(sub_url, headers=headers, timeout=20) if response.status_code != 200: print( f"Ошибка сервера: Статус {response.status_code}. Проверьте ссылку-подписку." ) sys.exit(1) raw_content = response.text.strip() # Проверяем, что в ответе реально есть сервера if "proxies:" not in raw_content: print( "Ошибка: Сервер вернул YAML, но в нём отсутствует блок нод 'proxies:'." ) sys.exit(1) # ФАЙЛ 1: Сохраняем оригинальный чистый конфиг от провайдера with open("clash.yaml", "w", encoding="utf-8") as f: f.write(raw_content) print("Оригинальный конфиг успешно сохранен в clash.yaml") # ФАЙЛ 2: Создаем модифицированный конфиг для раздельного обхода # Переводим режим работы в rule (по правилам) вместо global (весь трафик) split_content = raw_content.replace("mode: global", "mode: rule") if "rules:" in split_content: # Отрезаем старые правила провайдера (всё, что после 'rules:') base_part = split_content.split("rules:")[0] # Формируем огромный расширенный список правил с разделением трафика advanced_rules = """rules: # 1. Локальные адреса и домашняя сеть (в обход VPN) - DOMAIN-SUFFIX,local,DIRECT - IP-CIDR,127.0.0.0/8,DIRECT - IP-CIDR,172.16.0.0/12,DIRECT - IP-CIDR,192.168.0.0/16,DIRECT - IP-CIDR,10.0.0.0/8,DIRECT - IP-CIDR,198.18.0.0/16,DIRECT # 2. Популярные заблокированные ресурсы и сервисы (через VPN) - GEOSITE,onion,→ Remnawave - GEOSITE,twitter,→ Remnawave - GEOSITE,instagram,→ Remnawave - GEOSITE,facebook,→ Remnawave - GEOSITE,meta,→ Remnawave - GEOSITE,youtube,→ Remnawave - GEOSITE,netflix,→ Remnawave - GEOSITE,openai,→ Remnawave - GEOSITE,chatgpt,→ Remnawave - GEOSITE,discord,→ Remnawave - GEOSITE,protonmail,→ Remnawave - GEOSITE,intel,→ Remnawave - GEOSITE,amd,→ Remnawave - GEOSITE,nvidia,→ Remnawave - GEOSITE,spotify,→ Remnawave - GEOSITE,linkedin,→ Remnawave - GEOSITE,rutracker,→ Remnawave - GEOSITE,notion,→ Remnawave - GEOSITE,docker,→ Remnawave - GEOSITE,medium,→ Remnawave - GEOSITE,behance,→ Remnawave - GEOSITE,pinterest,→ Remnawave - GEOSITE,canva,→ Remnawave - GEOSITE,epicgames,→ Remnawave # 3. Весь остальной зарубежный контент (по желанию, через VPN) - GEOSITE,geolocation-!cn,→ Remnawave # 4. Российские государственные сайты, банки и крупные ресурсы (напрямую, без VPN) - GEOSITE,win-russia,DIRECT - GEOSITE,category-gov-ru,DIRECT - GEOSITE,ru,DIRECT - GEOSITE,yandex,DIRECT - GEOSITE,vk,DIRECT - GEOSITE,mailru,DIRECT - GEOSITE,sberbank,DIRECT - GEOSITE,tinkoff,DIRECT - GEOSITE,kinopoisk,DIRECT - GEOSITE,avito,DIRECT - GEOIP,RU,DIRECT # 5. Финальное замыкающее правило: всё, что не подошло под списки выше, идет НАПРЯМУЮ - MATCH,DIRECT """ # Склеиваем настройки и новые правила full_split_yaml = base_part + advanced_rules with open("clash_split.yaml", "w", encoding="utf-8") as f: f.write(full_split_yaml) print("Раздельный конфиг успешно сохранен в clash_split.yaml") else: print( "Ошибка: В исходном конфиге не найдена секция rules: для замены!" ) sys.exit(1) except Exception as e: print(f"Критическая ошибка во время выполнения: {e}") sys.exit(1) if __name__ == "__main__": fetch_and_prepare_configs()