diff --git a/mihomo_editor.py b/mihomo_editor.py index 226054f..824e248 100644 --- a/mihomo_editor.py +++ b/mihomo_editor.py @@ -330,6 +330,7 @@ button:hover{filter:brightness(1.1)}
+

Бэкапы

@@ -351,6 +352,18 @@ button:hover{filter:brightness(1.1)}

Π£Π΄Π°Π»ΠΈΡ‚ΡŒ прокси

Консоль

...
+
+

ΠŸΠ΅Ρ€Π΅ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Ρ‚ΡŒ прокси

+

Π’Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅ прокси для пСрСимСнования:

+ +

НовоС имя:

+ +
+ + +
+
+

Новый ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ

@@ -606,6 +619,62 @@ function doDel(){ } ed.setValue(nls.join('\\n')); } + +function showRename() { + var ls = ed.getValue().split(/\\r?\\n/); + var prs = [], inP = 0; + for (var l of ls) { + if (l.match(/^proxies:/)) inP = 1; + if (inP && l.match(/^[a-zA-Z]/) && !l.match(/^proxies:/)) inP = 0; + if (inP) { + var m = l.match(/^\s+-\s+name:\s+(.*)/); + if (m) prs.push(m[1].trim().replace(/^['"]|['"]$/g, '')) + } + } + var s = document.getElementById('sel-ren-proxy'); + s.innerHTML = ''; + prs.forEach(p => { + var o = document.createElement('option'); + o.text = p; + s.add(o) + }); + document.getElementById('inp-ren-newname').value = ''; + document.getElementById('m-ren').style.display = 'flex'; +} + +function doRename() { + var oldName = document.getElementById('sel-ren-proxy').value; + var newName = document.getElementById('inp-ren-newname').value.trim(); + if (!newName) { + alert("НовоС имя Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ пустым."); + return; + } + if (!oldName) { + alert("ΠŸΡ€ΠΎΠΊΡΠΈ Π½Π΅ Π²Ρ‹Π±Ρ€Π°Π½."); + return; + } + + var content = ed.getValue(); + var params = new URLSearchParams(); + params.append('act', 'rename_proxy'); + params.append('old_name', oldName); + params.append('new_name', newName); + params.append('content', content); + + fetch('/', { method: 'POST', body: params }) + .then(r => r.json()) + .then(d => { + if (d.error) { + alert('Ошибка: ' + d.error); + } else { + ed.setValue(d.new_content); + ed.clearSelection(); + closeM('m-ren'); + showToast("✏️ ΠŸΡ€ΠΎΠΊΡΠΈ ΠΏΠ΅Ρ€Π΅ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½!"); + } + }) + .catch(e => alert("БСтСвая ошибка: " + e)); +} """ @@ -789,6 +858,32 @@ class H(http.server.SimpleHTTPRequestHandler): s.wfile.write(json.dumps({'error': 'Profile not found'}).encode('utf-8')) return + if a == 'rename_proxy': + old_name = p.get('old_name') + new_name = p.get('new_name') + content = p.get('content', '') + if not all([old_name, new_name, content]): + s.wfile.write(json.dumps({'error': 'Missing parameters'}).encode('utf-8')) + return + + # 1. Π—Π°ΠΌΠ΅Π½Π° Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ прокси: - name: "old_name" + # Regex для поиска `name: 'old_name'`, `name: "old_name"` ΠΈΠ»ΠΈ `name: old_name` + # Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ `re.escape` для бСзопасности + escaped_old = re.escape(old_name) + # (?P['"]?) - Π·Π°Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΊΠ°Π²Ρ‹Ρ‡ΠΊΡƒ (Ссли ΠΎΠ½Π° Π΅ΡΡ‚ΡŒ) Π² Π³Ρ€ΡƒΠΏΠΏΡƒ 'quote' + # \\1 - ссылаСтся Π½Π° Π·Π°Ρ…Π²Π°Ρ‡Π΅Π½Π½ΡƒΡŽ ΠΊΠ°Π²Ρ‹Ρ‡ΠΊΡƒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π½Π° Ρ‚Π°ΠΊΡƒΡŽ ΠΆΠ΅ + pattern_def = r"(name\s*:\s*)(?P['\"]?)" + escaped_old + r"(?P=quote)" + # ЗамСняСм, сохраняя ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠ°Π²Ρ‹Ρ‡ΠΊΠΈ + content = re.sub(pattern_def, r'\g<1>"' + new_name + '"', content, count=1) + + # 2. Π—Π°ΠΌΠ΅Π½Π° Π² списках proxy-groups: - "old_name" + # Regex для поиска `- 'old_name'`, `- "old_name"` ΠΈΠ»ΠΈ `- old_name` + pattern_list = r"(-\s+)(?P['\"]?)" + escaped_old + r"(?P=quote)" + content = re.sub(pattern_list, r'\g<1>"' + new_name + '"', content) + + s.wfile.write(json.dumps({'status': 'ok', 'new_content': content}).encode('utf-8')) + return + # --- EXISTING ACTIONS --- if a == 'parse':