diff --git a/mihomo_editor.py b/mihomo_editor.py index 824e248..eb172a7 100644 --- a/mihomo_editor.py +++ b/mihomo_editor.py @@ -90,6 +90,84 @@ def parse_vless(link): return None, str(e) +def parse_wireguard(config_text): + try: + name = "WireGuard" + params = {} + current_section = None + for line in config_text.splitlines(): + line = line.strip() + if not line or line.startswith('#'): + continue + if line.startswith('[') and line.endswith(']'): + current_section = line[1:-1].lower() + continue + if '=' in line: + key, value = map(str.strip, line.split('=', 1)) + if current_section: + if current_section not in params: + params[current_section] = {} + params[current_section][key] = value + + if 'interface' not in params or 'peer' not in params: + return None, "Invalid WireGuard config: missing [Interface] or [Peer] section." + + interface = params.get('interface', {}) + peer = params.get('peer', {}) + + # Extract name from comment if exists + name_match = re.search(r'#\s*(.+)', config_text.splitlines()[0]) + if name_match: + name = name_match.group(1).strip() + + name = f"WG-{name}" + + server, port = peer.get('Endpoint', ':').rsplit(':', 1) + + y = [ + f'- name: "{name}"', + ' type: wireguard', + f' server: {server}', + f' port: {port}', + f' private-key: "{interface.get("PrivateKey")}"', + f' public-key: "{peer.get("PublicKey")}"', + f' ip: "{interface.get("Address").split("/")[0]}"' + ] + + if interface.get('DNS'): + dns_servers = [d.strip() for d in interface.get('DNS').split(',')] + y.append(f' dns: {dns_servers}') + + if peer.get('PresharedKey'): + y.append(f' preshared-key: "{peer.get("PresharedKey")}"') + + if peer.get('PersistentKeepalive'): + y.append(f' keep-alive: {peer.get("PersistentKeepalive")}') + + amnezia_opts = { + 'Jc': interface.get('Jc'), + 'Jmin': interface.get('Jmin'), + 'Jmax': interface.get('Jmax'), + 'S1': interface.get('S1'), + 'S2': interface.get('S2'), + 'H1': interface.get('H1'), + 'H2': interface.get('H2'), + 'H3': interface.get('H3'), + 'H4': interface.get('H4') + } + + if any(v is not None for v in amnezia_opts.values()): + y.append(' amnezia-wg-opts:') + for key, value in amnezia_opts.items(): + if value is not None: + y.append(f' {key.lower()}: {value}') + + return {"yaml": "\n".join(y), "name": name}, None + + except Exception as e: + return None, str(e) + + def insert_proxy_logic(content, proxy_name, target_groups): lines = content.splitlines() new_lines = [] @@ -272,6 +350,21 @@ button:hover{filter:brightness(1.1)} .g-item input:checked + label {background: var(--btn-s);color: white;border-color: var(--btn-s);font-weight: bold;} .toast {position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: var(--btn-r); color: white; padding: 10px 20px; border-radius: 5px; z-index: 3000; display: none; box-shadow: 0 2px 10px rgba(0,0,0,0.5);} +.modal-tabs { display: flex; border-bottom: 1px solid var(--bd); margin-bottom: 15px; } +.modal-tabs button { + flex: 1; justify-content: center; background: none; border: none; border-bottom: 2px solid transparent; + border-radius: 0; padding: 10px; font-size: 14px; color: var(--txt-sec); height: auto; +} +.modal-tabs button.active { color: var(--txt); border-bottom-color: var(--btn-s); font-weight: bold; } +.tab-content { display: none; } +.tab-content.active { display: block; } +.file-drop-zone { + border: 2px dashed var(--bd); border-radius: 4px; padding: 20px; text-align: center; + color: var(--txt-sec); cursor: pointer; transition: 0.2s; margin-bottom: 10px; +} +.file-drop-zone:hover { background: var(--bg-ter); border-color: var(--btn-s); } +.file-drop-zone.dragover { background: var(--bg-ter); border-color: var(--btn-s); } + .log-time { color: #888; margin-right: 8px; } .log-info { color: #2196f3; font-weight: bold; } .log-warn { color: #ff9800; font-weight: bold; } @@ -324,11 +417,8 @@ button:hover{filter:brightness(1.1)}