import requests import json import os import time import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) def get_router_credentials(config_path, isp_name="dimensi", router_name="router-dimensi-dell"): try: with open(config_path, 'r') as f: config = json.load(f) routers = config.get("isps", {}).get(isp_name, {}).get("routers", {}) return routers.get(router_name) except Exception as e: print(f"Error membaca config: {e}") return None def update_mangle_and_queue(): router = get_router_credentials("/home/wartana/myApp/billing-mcp/config.json") if not router: print("Kredensial router-dimensi-dell tidak ditemukan di config.") return host = router["host"] user = router["user"] password = router["pass"] port = router["port"] api_url = f"http://{host}/rest" if port != 80: api_url = f"http://{host}:{port}/rest" session = requests.Session() session.auth = (user, password) session.verify = False print(f"--- Menghubungi router {host}:{port} ---") # 1. CLEANUP (Hapus Mangle Mark-Packet, Queue Type 1/2 lama kalo ada, Queue Tree Lokal, dll jika script dijalankan berulang) print("Membersihkan Mangle & Queue peninggalan lama...") cleanup_script = """ /ip/firewall/mangle/remove [find chain=forward action=mark-packet] /queue/tree/remove [find name~"_LOKAL"] /queue/tree/remove [find name~"_local"] /queue/type/remove [find name~"_half"] """ try: session.post(f"{api_url}/execute", json={"script": cleanup_script}, timeout=30) except Exception as e: pass time.sleep(3) # Tunggu router bernafas # 2. DEFINISI PROFIL # Format: [Profile Name, Full Speed (Mbps), Half Speed (Mbps), Original Limit DL, Original Limit UL] # Catatan: Ini didasarkan pada file 178-queue-tree.rsc yang diupload profiles = [ # Hemat dan EXPIRED kita tangani special ("star_10", 10, 5, "2G", "500M"), ("star_20", 20, 10, "3G", "500M"), ("star_30", 30, 15, "3G", "500M"), ("star_50", 50, 25, "3G", "500M"), ("star_100", 100, 50, "3G", "500M"), ("star_150", 150, 75, "3G", "500M"), ("star_200", 200, 100, "3G", "500M"), ("star_500", 500, 250, "3G", "500M") ] commands = [] # --- A. SETUP QUEUE TYPES & QUEUE PARENT LOKAL --- # Bikin Queue Parent LOKAL commands.append("/queue/tree/add max-limit=5G name=1_all_dl_Dimensi_LOKAL parent=global queue=default") commands.append("/queue/tree/add max-limit=5G name=5_all_ul_Dimensi_LOKAL parent=global queue=default") print("Menyusun skrip untuk Profil Spesial (EXPIRED & Hemat)...") # PROFIL EXPIRED (Semua dilimit mati, pakai queue default saja) commands.append("/ip/firewall/mangle/add action=mark-packet chain=forward dst-address-list=EXPIRED new-packet-mark=EXPIRED_dl passthrough=no") commands.append("/ip/firewall/mangle/add action=mark-packet chain=forward src-address-list=EXPIRED new-packet-mark=EXPIRED_ul passthrough=no") # Queue Tree EXPIRED sudah ada di 178 eksisting, jadi kita tak ubah # PROFIL HEMAT (Bypass LOKAL penuh, Tidak di split speed) # Catatan: Hemat itu "Up to X", kita biarkan max-limit ikut apa yang ada di tree. Intinya LOKAL 5G loss, INT nya biarkan seperti biasa max-limit 3G (PCQ default hemat 6M). commands.append("/ip/firewall/mangle/add action=mark-packet chain=forward dst-address-list=hemat src-address-list=!ip-lokal new-packet-mark=hemat_dl passthrough=no") commands.append("/ip/firewall/mangle/add action=mark-packet chain=forward src-address-list=hemat dst-address-list=!ip-lokal new-packet-mark=hemat_ul passthrough=no") commands.append("/ip/firewall/mangle/add action=mark-packet chain=forward dst-address-list=hemat src-address-list=ip-lokal new-packet-mark=hemat_dl_local passthrough=no") commands.append("/ip/firewall/mangle/add action=mark-packet chain=forward src-address-list=hemat dst-address-list=ip-lokal new-packet-mark=hemat_ul_local passthrough=no") # Child Queue Lokal HEMAT commands.append("/queue/tree/add max-limit=5G name=hemat_dl_local packet-mark=hemat_dl_local parent=1_all_dl_Dimensi_LOKAL queue=hemat_dl_6m") commands.append("/queue/tree/add max-limit=5G name=hemat_ul_local packet-mark=hemat_ul_local parent=5_all_ul_Dimensi_LOKAL queue=hemat_ul_6m") # Update Queue Int Lama untuk sinkronisasi pembaruan nama packet-mark `_ul` commands.append("/queue/tree/set [find name=\"hemat_up\"] name=\"hemat_ul\" packet-mark=hemat_ul queue=hemat_ul_6m") commands.append("/queue/tree/set [find name=\"hemat_ul\"] packet-mark=hemat_ul queue=hemat_ul_6m") # --- B. SETUP PROFIL STAR REGULAR (Limit Int = Setengah) --- print(f"Menyusun skrip Mangle & Queue Tree untuk {len(profiles)} Profil Star...") for p in profiles: name, full, half, dl_limit, ul_limit = p # Penamaan Packet Marks dl_int = f"{name}_dl" up_int = f"{name}_ul" dl_loc = f"{name}_dl_local" up_loc = f"{name}_ul_local" # 1. BIKIN MANGLE INT (!ip-lokal) & LOKAL (ip-lokal) commands.append(f"/ip/firewall/mangle/add action=mark-packet chain=forward dst-address-list={name} src-address-list=!ip-lokal new-packet-mark={dl_int} passthrough=no") commands.append(f"/ip/firewall/mangle/add action=mark-packet chain=forward src-address-list={name} dst-address-list=!ip-lokal new-packet-mark={up_int} passthrough=no") commands.append(f"/ip/firewall/mangle/add action=mark-packet chain=forward dst-address-list={name} src-address-list=ip-lokal new-packet-mark={dl_loc} passthrough=no") commands.append(f"/ip/firewall/mangle/add action=mark-packet chain=forward src-address-list={name} dst-address-list=ip-lokal new-packet-mark={up_loc} passthrough=no") # 2. UBAH/BUAT BIKIN QUEUE TYPES SETENGAH (Hanya jika belum ada). # Kita menggunakan _half sebagai penanda pcq_dl_half = f"pcq_dl_{full}m_half" pcq_up_half = f"pcq_ul_{full}m_half" commands.append(f"/queue/type/add kind=pcq name={pcq_dl_half} pcq-classifier=dst-address pcq-rate={half}M") commands.append(f"/queue/type/add kind=pcq name={pcq_up_half} pcq-classifier=src-address pcq-rate={half}M") # Bikin pcq_dl lokal asalnya (Kalo kelewatan ga terconfig di router): pcq_dl_full = f"pcq_dl_{full}m" q_up_ori = f"pcq_ul_{full}m" # 3. SET QUEUE INTERNASIONAL (Yg Lama) PAKE PCQ SETENGAH # Deteksi nama asli Queue Upload Int di MikroTik Anda (dari dump 178-queue-tree) # Sebagian besar bernama star_X_ul, bukan _up q_up_ori_name = f"{name}_ul" commands.append(f"/queue/tree/set [find name=\"{name}_dl\"] queue={pcq_dl_half} packet-mark={dl_int}") commands.append(f"/queue/tree/set [find name=\"{q_up_ori_name}\"] packet-mark={up_int} queue={pcq_up_half}") # Tambahan backup apabila ada nama tree lama yg typo dengan "up" commands.append(f"/queue/tree/set [find name=\"{name}_up\"] name=\"{name}_ul\" packet-mark={up_int} queue={pcq_up_half}") # 4. BIKIN CHILD QUEUE LOKAL YANG BARU (Gunakan rate FULL / Queue eksisting PCQ ori) commands.append(f"/queue/tree/add max-limit=5G name={name}_dl_local packet-mark={dl_loc} parent=1_all_dl_Dimensi_LOKAL queue={pcq_dl_full}") commands.append(f"/queue/tree/add max-limit=5G name={name}_ul_local packet-mark={up_loc} parent=5_all_ul_Dimensi_LOKAL queue={q_up_ori}") # --- EKSEKUSI SEMUA COMMAND BARIS DEMI BARIS --- print(f"Mengeksekusi {len(commands)} baris konfigurasi secara antrean (Sequential)...") success_count = 0 fail_count = 0 for cmd in commands: try: res = session.post(f"{api_url}/execute", json={"script": cmd}, timeout=10) if res.status_code in (200, 201): success_count += 1 else: fail_count += 1 # print(f"Warning saat eksekusi: {cmd}\nResponse: {res.text}") except Exception as e: fail_count += 1 print(f"Error Timeout: {e}") print(f"Selesai! {success_count} berhasil, {fail_count} dilewati (Mungkin objek dicari tidak ada/sudah ada).") print("Mangle & Queue Lokal vs Int dual-stack telah disinkronisasi utuh.") if __name__ == "__main__": update_mangle_and_queue()