import tkinter as tk from tkinter import ttk, scrolledtext import threading, time, cv2, numpy as np, os from ppadb.client import Client as AdbClient from PIL import Image, ImageTk class AutoBotGUI: def __init__(self, root): self.root = root self.root.title("Double Number Merging - Auto Cày Lv 30") self.root.geometry("950x620") self.root.configure(bg="#1a1a2e") self.running = False self.level = 1 self.device = None # ===== LEFT PANEL - Preview ===== left = tk.Frame(root, bg="#1a1a2e") left.pack(side=tk.LEFT, padx=15, pady=15) tk.Label(left, text="PREVIEW", fg="#00f5ff", bg="#1a1a2e", font=("Consolas", 12, "bold")).pack(anchor="w") self.preview_label = tk.Label(left, bg="#0f0f1a", width=360, height=640, text="Chưa kết nối") self.preview_label.pack(pady=10) # resize preview to fit self.preview_label.config(width=400, height=500) # ===== RIGHT PANEL - Controls ===== right = tk.Frame(root, bg="#1a1a2e") right.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=15, pady=15) tk.Label(right, text="DOUBLE NUMBER BOT", fg="white", bg="#1a1a2e", font=("Arial", 18, "bold")).pack(anchor="w") tk.Label(right, text="Auto farm - Xem QC - Replay", fg="#aaa", bg="#1a1a2e", font=("Arial", 10)).pack(anchor="w", pady=(0,15)) # Status status_frame = tk.Frame(right, bg="#16213e", padx=12, pady=12) status_frame.pack(fill=tk.X, pady=5) self.status_var = tk.StringVar(value="● Chưa kết nối") tk.Label(status_frame, textvariable=self.status_var, fg="#ff5e5e", bg="#16213e", font=("Consolas", 11)).pack(anchor="w") # Level Progress tk.Label(right, text="Tiến trình lên Lv 30", fg="white", bg="#1a1a2e").pack(anchor="w", pady=(15,5)) self.progress = ttk.Progressbar(right, length=300, mode='determinate') self.progress.pack(fill=tk.X) self.level_var = tk.StringVar(value="Lv: 1 / 30") tk.Label(right, textvariable=self.level_var, fg="#00f5ff", bg="#1a1a2e", font=("Arial", 12, "bold")).pack(anchor="w", pady=5) # Config cfg_frame = tk.Frame(right, bg="#1a1a2e") cfg_frame.pack(fill=tk.X, pady=10) tk.Label(cfg_frame, text="BOARD_REGION (x1,y1,x2,y2)", fg="#ccc", bg="#1a1a2e", font=("Consolas", 9)).grid(row=0, column=0, sticky="w") self.region_entry = tk.Entry(cfg_frame, bg="#0f0f1a", fg="white", insertbackground="white", font=("Consolas", 10)) self.region_entry.insert(0, "80,550,1000,1450") self.region_entry.grid(row=1, column=0, sticky="ew", pady=5) cfg_frame.columnconfigure(0, weight=1) tk.Label(cfg_frame, text="GRID (vd 5x5)", fg="#ccc", bg="#1a1a2e", font=("Consolas", 9)).grid(row=0, column=1, padx=10) self.grid_entry = tk.Entry(cfg_frame, bg="#0f0f1a", fg="white", width=8, font=("Consolas", 10)) self.grid_entry.insert(0, "5,5") self.grid_entry.grid(row=1, column=1) # Buttons btn_frame = tk.Frame(right, bg="#1a1a2e") btn_frame.pack(fill=tk.X, pady=15) self.connect_btn = tk.Button(btn_frame, text="KẾT NỐI ADB", command=self.connect_adb, bg="#0f3460", fg="white", font=("Arial", 11, "bold"), padx=15, pady=8, relief=tk.FLAT, cursor="hand2") self.connect_btn.pack(side=tk.LEFT, padx=(0,10)) self.start_btn = tk.Button(btn_frame, text="▶ START AUTO", command=self.toggle_bot, bg="#00f5ff", fg="#000", font=("Arial", 11, "bold"), padx=15, pady=8, relief=tk.FLAT, state=tk.DISABLED, cursor="hand2") self.start_btn.pack(side=tk.LEFT) # Log tk.Label(right, text="LOG", fg="#ccc", bg="#1a1a2e", font=("Consolas", 9)).pack(anchor="w", pady=(15,5)) self.log = scrolledtext.ScrolledText(right, bg="#0f0f1a", fg="#00ff9d", font=("Consolas", 9), height=14, relief=tk.FLAT) self.log.pack(fill=tk.BOTH, expand=True) self.log_msg("Sẵn sàng. Bật LDPlayer và bấm Kết nối ADB.") def log_msg(self, msg): t = time.strftime("%H:%M:%S") self.log.insert(tk.END, f"[{t}] {msg}\n") self.log.see(tk.END) def connect_adb(self): try: client = AdbClient(host="127.0.0.1", port=5037) devices = client.devices() if not devices: self.log_msg("❌ Không thấy device. Mở giả lập lên!") return self.device = devices[0] self.status_var.set(f"● Đã kết nối: {self.device.serial}") self.connect_btn.config(bg="#2ecc71", text="ĐÃ KẾT NỐI") self.start_btn.config(state=tk.NORMAL) self.log_msg(f"✅ Kết nối thành công: {self.device.serial}") # start preview thread threading.Thread(target=self.preview_loop, daemon=True).start() except Exception as e: self.log_msg(f"❌ Lỗi ADB: {e}") def preview_loop(self): while True: if self.device and not self.running: try: img = self.get_screenshot() # resize for preview img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) pil = Image.fromarray(img_rgb) pil = pil.resize((360, 640)) tk_img = ImageTk.PhotoImage(pil) self.preview_label.config(image=tk_img, text="") self.preview_label.image = tk_img except: pass time.sleep(0.5) def get_screenshot(self): result = self.device.screencap() img = cv2.imdecode(np.frombuffer(result, np.uint8), cv2.IMREAD_COLOR) return img def toggle_bot(self): if not self.running: self.running = True self.start_btn.config(text="■ STOP", bg="#ff5e5e", fg="white")