diff --git a/mihomo_editor.py b/mihomo_editor.py index a7edae5..1b12fe4 100644 --- a/mihomo_editor.py +++ b/mihomo_editor.py @@ -100,9 +100,7 @@ def parse_wireguard(config_text, custom_name=None): conf = {"interface": {}, "peer": {}} section = None - # 1. Читаем построчно, чистим комментарии и собираем секции for line in config_text.splitlines(): - # Удаляем inline комментарии (# или ;) line = line.split('#')[0].split(';')[0].strip() if not line: continue @@ -124,11 +122,9 @@ def parse_wireguard(config_text, custom_name=None): if not iface or not peer: return None, "Invalid WireGuard config: missing Interface or Peer" - # 2. Endpoint (Server + Port) endpoint = peer.get('endpoint', '') if not endpoint: return None, "No Endpoint found" - # Обработка IPv6 в Endpoint [::1]:port if ']:' in endpoint: server = endpoint.split(']:')[0][1:] port = endpoint.split(']:')[1] @@ -137,19 +133,16 @@ def parse_wireguard(config_text, custom_name=None): else: return None, "Invalid Endpoint format" - # 3. Name Logic name = "WireGuard" if custom_name: name = custom_name else: - # Пытаемся взять имя из первой строки оригинального текста, если там комментарий first_line = config_text.splitlines()[0].strip() if first_line.startswith('#') and len(first_line) > 2: name = first_line[1:].strip() else: name = f"WG_{server}" - # 4. Address (IP + IPv6) address_raw = iface.get('address', '') if not address_raw: return None, "No Address found" @@ -158,7 +151,6 @@ def parse_wireguard(config_text, custom_name=None): ip_v6 = None for ip in ips: - # Убираем маску /32, /24 и т.д. clean_ip = ip.split('/')[0] if ':' in clean_ip: if not ip_v6: ip_v6 = clean_ip @@ -168,7 +160,6 @@ def parse_wireguard(config_text, custom_name=None): if not ip_v4 and not ip_v6: return None, "No valid IP address found" - # 5. Сборка YAML y = [] y.append(f'- name: "{name}"') y.append(f' type: wireguard') @@ -184,11 +175,9 @@ def parse_wireguard(config_text, custom_name=None): pubk = peer.get('publickey') if pubk: y.append(f' public-key: {pubk}') - # Исправлено: pre-shared-key (с дефисом) psk = peer.get('presharedkey') if psk: y.append(f' pre-shared-key: {psk}') - # DNS dns_raw = iface.get('dns') if dns_raw: dns_list = [d.strip() for d in dns_raw.split(',')] @@ -199,27 +188,24 @@ def parse_wireguard(config_text, custom_name=None): y.append(' udp: true') - # 6. AmneziaWG Specific amnezia_keys = ['jc', 'jmin', 'jmax', 's1', 's2', 'h1', 'h2', 'h3', 'h4'] amn_opts = {} for k in amnezia_keys: if k in iface: val = iface[k] if val.isdigit(): - amn_opts[k] = int(val) # Важно: int, не string + amn_opts[k] = int(val) if amn_opts: y.append(' amnezia-wg-option:') for k, v in amn_opts.items(): y.append(f' {k}: {v}') - # 7. AllowedIPs (добавлено) allowed = peer.get('allowedips') if allowed: al_list = [x.strip() for x in allowed.split(',')] y.append(f' allowed-ips: {json.dumps(al_list)}') - # Исправлено: persistent-keepalive ka = peer.get('persistentkeepalive') if ka: y.append(f' persistent-keepalive: {ka}') @@ -250,7 +236,6 @@ def insert_proxy_logic(content, proxy_name, target_groups): if is_new_group: if in_proxies_list and current_group_name in target_groups and current_group_name not in inserted_in_group: - # End of list section prefix = " " * (proxies_list_indent + 2) new_lines.append(prefix + '- "' + proxy_name + '"') inserted_in_group.add(current_group_name) @@ -269,14 +254,11 @@ def insert_proxy_logic(content, proxy_name, target_groups): current_group_name = raw_name.strip("'").strip('"') if current_group_name in target_groups and stripped.startswith('proxies:'): - # Check for inline list style: proxies: [a, b] if '[' in stripped and stripped.rstrip().endswith(']'): start = line.find('[') end = line.rfind(']') if start != -1 and end != -1: content_inner = line[start + 1:end] - # Check if proxy already exists in the list - # Simple check: name in text (robust enough for simple cases) if proxy_name not in content_inner: sep = ", " if content_inner.strip() else "" new_content = content_inner + sep + f'"{proxy_name}"' @@ -327,8 +309,6 @@ def replace_proxy_block(content, target_name, new_yaml_lines): found_target = False replaced = False - # Регулярка для поиска начала блока прокси с указанным именем - # Учитывает кавычки и пробелы: - name: "target_name" name_pattern = re.compile(r'^\s*-\s+name:\s*(["\'])?' + re.escape(target_name) + r'(\1)?\s*$') i = 0 @@ -336,33 +316,19 @@ def replace_proxy_block(content, target_name, new_yaml_lines): line = lines[i] stripped = line.strip() - # Определяем секцию proxies if stripped.startswith('proxies:'): in_proxies = True new_content_lines.append(line) i += 1 continue - # Если вышли из proxies (новая секция начинается без отступа) if in_proxies and line and not line.startswith(' ') and not line.startswith('\t') and not line.startswith('#'): in_proxies = False if in_proxies and not replaced: if name_pattern.match(stripped): - # Нашли целевой прокси. - # 1. Определяем отступ этого блока (обычно 2 пробела) indent_len = len(line) - len(line.lstrip()) - - # 2. Добавляем новый YAML. - # new_yaml_lines приходят без отступов (или с базовыми). - # Нам нужно убедиться, что первая строка имеет дефис, а остальные - отступ. - # Обычно new_yaml_lines[0] уже "- name: ...". - # Просто добавим отступ всем строкам. - - # Принудительно меняем имя в новом YAML на целевое, чтобы сохранить структуру - # (хотя парсеры уже могли вернуть новое имя, но лучше перестраховаться) if new_yaml_lines and "name:" in new_yaml_lines[0]: - # Заменяем имя в первой строке нового конфига на старое (target_name) new_yaml_lines[0] = re.sub(r'name:\s*".*"', f'name: "{target_name}"', new_yaml_lines[0]) for n_line in new_yaml_lines: @@ -371,28 +337,16 @@ def replace_proxy_block(content, target_name, new_yaml_lines): replaced = True found_target = True - # 3. Пропускаем старый блок - # Читаем дальше, пока не найдем строку с ТАКИМ ЖЕ отступом, начинающуюся с '-' (следующий элемент списка) - # или строку с МЕНЬШИМ отступом (конец секции) i += 1 while i < len(lines): next_line = lines[i] next_stripped = next_line.strip() next_indent = len(next_line) - len(next_line.lstrip()) - - if not next_stripped: # Пустые строки пропускаем/удаляем внутри блока + if not next_stripped: i += 1 continue - - if next_indent < indent_len: - # Конец секции proxies - break - - if next_indent == indent_len and next_stripped.startswith('-'): - # Следующий элемент списка - break - - # Это всё еще часть старого блока, пропускаем + if next_indent < indent_len: break + if next_indent == indent_len and next_stripped.startswith('-'): break i += 1 continue @@ -403,11 +357,11 @@ def replace_proxy_block(content, target_name, new_yaml_lines): HTML_TEMPLATE = """ - + -Mihomo Editor v18.8 +Mihomo Editor v18.9 -
✅ Успешно сохранено
+
✅ Успешно сохранено
-

Mihomo Studio

- v18.8 Auto-Panel +

Mihomo Studio

+ v18.9 Auto-Panel
Loaded: __TIME__
- - - - + + + + +
+ + +
-

Профили

+

Профили

- - + +
- - + +
-

Управление прокси

+

Управление

- - - - + + + +
-

Бэкапы

+

Бэкапы

- Оставить: + Оставить: - +
__BACKUPS__
-

Добавить в группы:

-
+

Добавить в группы:

+
-
+
-

Удалить прокси

-

Консоль

...
+

Удалить прокси

+

Консоль

...
-

Переименовать прокси

-

Выберите прокси для переименования:

+

Переименовать прокси

+

Выберите прокси для переименования:

-

Новое имя:

- +

Новое имя:

+
- - + +
-

Новый профиль

- +

Новый профиль

+ - +
- +
- +
- - + +
-

Добавить прокси

+

Добавить прокси

- +
- +
- +
- +
- +
- - + +
-

Просмотр бэкапа

+

Просмотр бэкапа


     
- - + +