import tkinter as tk
from tkinter import filedialog, messagebox
import threading
import time
import random
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
def center_window(root, width=950, height=470):
# Lấy kích thước màn hình
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
# Tính vị trí bắt đầu trục ngang và trục đứng
aaaxxx = (screen_width // 2) - (width // 2)
bbbyyy = (screen_height // 2) - (height // 2) - (40)
# Đặt geometry
root.geometry(f"{width}x{height}+{aaaxxx}+{bbbyyy}")
class AccessLinksApp:
def __init__(self, root):
self.root = root
self.root.title("Access Multilinks With Timer - DarkCorners")
center_window(self.root, 950, 470)
self.links = []
self.running = False
self.drivers = []
self.threads = []
self.max_threads = 20
# Row 1: Title label
self.title_label = tk.Label(root, text="Access Multilinks With Timer - DarkCorners", font=("Arial", 16, "bold"))
self.title_label.pack(pady=10)
# Row 2: File path, select button, and note
file_frame_wrapper = tk.LabelFrame(root, text="TỆP TXT CHỨA URL", padx=10, pady=5, bd=2, font=("Arial", 10, "bold"))
file_frame_wrapper.pack(padx=10, pady=5, fill=tk.X)
file_frame = tk.Frame(file_frame_wrapper)
file_frame.pack(fill=tk.X)
self.file_entry = tk.Entry(file_frame, width=60)
self.file_entry.pack(side=tk.LEFT, padx=5)
self.browse_button = tk.Button(file_frame, text="Chọn File", command=self.browse_file)
self.browse_button.pack(side=tk.LEFT, padx=2)
note_frame = tk.LabelFrame(file_frame, bd=2, relief=tk.GROOVE, padx=5, pady=2)
note_frame.pack(side=tk.LEFT, padx=10)
self.note_label = tk.Label(note_frame, text="Lưu Ý : Tệp txt mỗi link 1 dòng! Tệp chromedrive.exe cùng thư mục tool.", fg="red", font=("Arial", 9, "bold"))
self.note_label.pack()
# Row 3: Configuration block + Control buttons frame
config_frame = tk.Frame(root)
config_frame.pack(padx=10, pady=(0, 5), fill=tk.X)
# [DaLuong-CauHinh]
thread_config = tk.LabelFrame(config_frame, text="ĐA LUỒNG", padx=5, pady=5, font=("Arial", 10, "bold"))
thread_config.pack(side=tk.LEFT, padx=10, pady=(0, 10))
self.thread_count_var = tk.IntVar(value=15)
self.thread_count_spinbox = tk.Spinbox(thread_config, from_=1, to=self.max_threads, textvariable=self.thread_count_var, width=3)
self.thread_count_spinbox.pack(side=tk.LEFT)
tk.Label(thread_config, text="Tối Đa 20").pack(side=tk.LEFT, padx=2)
# [Thời Gian Ngẫu Nhiên]
time_config = tk.LabelFrame(config_frame, text="THỜI GIAN NGẪU NHIÊN", padx=5, pady=5, font=("Arial", 10, "bold"))
time_config.pack(side=tk.LEFT, padx=10, pady=(0, 10))
tk.Label(time_config, text="Từ").pack(side=tk.LEFT)
self.time_from_var = tk.IntVar(value=3)
self.time_to_var = tk.IntVar(value=10)
self.time_from_entry = tk.Spinbox(time_config, from_=1, to=999, width=3, textvariable=self.time_from_var)
self.time_from_entry.pack(side=tk.LEFT, padx=2)
tk.Label(time_config, text="Đến").pack(side=tk.LEFT)
self.time_to_entry = tk.Spinbox(time_config, from_=1, to=999, width=3, textvariable=self.time_to_var)
self.time_to_entry.pack(side=tk.LEFT, padx=2)
tk.Label(time_config, text="(giây)").pack(side=tk.LEFT, padx=2)
# [Options]
option_config = tk.LabelFrame(config_frame, text="TÙY CHỈNH PHẦN MỀM", padx=5, pady=5, font=("Arial", 10, "bold"))
option_config.pack(side=tk.LEFT, padx=10, pady=(0, 10))
self.loop_var = tk.BooleanVar()
self.headless_var = tk.BooleanVar()
self.loop_checkbox = tk.Checkbutton(option_config, text="Lặp Lại", variable=self.loop_var)
self.headless_checkbox = tk.Checkbutton(option_config, text="Ẩn Trình Duyệt", variable=self.headless_var)
self.loop_checkbox.pack(side=tk.LEFT, padx=2)
self.headless_checkbox.pack(side=tk.LEFT, padx=2)
tk.Label(option_config, text="Giãn Cách Luồng (giây):").pack(side=tk.LEFT, padx=(2, 2))
self.delay_between_threads_var = tk.IntVar(value=3)
self.delay_entry = tk.Spinbox(option_config, from_=1, to=60, width=2, textvariable=self.delay_between_threads_var)
self.delay_entry.pack(side=tk.LEFT, padx=(0, 5))
# [Control Buttons Moved Here]
control_button_frame = tk.LabelFrame(config_frame, text="ĐIỀU KHIỂN PHẦN MỀM", bd=2, relief=tk.GROOVE, padx=5, pady=5, font=("Arial", 10, "bold"))
control_button_frame.pack(side=tk.LEFT, padx=10, pady=(0, 10))
self.start_button = tk.Button(control_button_frame, text="Bắt Đầu", command=self.start)
self.start_button.pack(side=tk.LEFT, padx=3)
self.stop_button = tk.Button(control_button_frame, text="Dừng Lại", command=self.stop)
self.stop_button.pack(side=tk.LEFT, padx=3)
self.exit_button = tk.Button(control_button_frame, text="Thoát Hết", command=self.root.quit)
self.exit_button.pack(side=tk.LEFT, padx=3)
# Row 4: [DaLuong-ListLogs] 20 logs
log_frame = tk.LabelFrame(root, text="TRẠNG THÁI ĐA LUỒNG", bd=2, padx=10, pady=10, font=("Arial", 10, "bold"))
log_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 10))
self.log_labels = []
self.thread_status = [False] * self.max_threads # Theo dõi tình trạng luồng. True nếu đang chạy, False nếu dừng
left_column = tk.Frame(log_frame)
left_column.grid(row=0, column=0, padx=(0, 5), sticky='n')
separator = tk.Frame(log_frame, width=2, bg="gray")
separator.grid(row=0, column=1, sticky='ns')
right_column = tk.Frame(log_frame)
right_column.grid(row=0, column=2, padx=(5, 0), sticky='n')
for i in range(20):
col_frame = left_column if i < 10 else right_column
log_row = tk.Frame(col_frame)
log_row.pack(anchor='w', pady=1)
label = tk.Label(log_row, text=f"Đa Luồng {i+1:02}:", width=12)
label.pack(side=tk.LEFT)
log_text = tk.Label(log_row, text="Dừng", width=50, anchor='w', bg="white", relief=tk.SUNKEN)
log_text.pack(side=tk.LEFT, fill=tk.X, expand=True)
self.log_labels.append(log_text)
def browse_file(self):
file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
if file_path:
self.file_entry.delete(0, tk.END)
self.file_entry.insert(0, file_path)
def read_links(self, path):
try:
with open(path, 'r') as f:
return [line.strip() for line in f.readlines() if line.strip()]
except:
return []
def setup_driver(self):
options = Options()
if self.headless_var.get():
options.add_argument('--headless')
options.add_experimental_option("detach", True)
return webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
def worker(self, idx):
try:
driver = self.setup_driver()
self.thread_status[idx] = True
self.drivers.append(driver)
while self.running:
link = random.choice(self.links)
driver.get(link)
title = driver.title or "(Không có tiêu đề)"
self.log_labels[idx].config(text=title)
delay = random.randint(self.time_from_var.get(), self.time_to_var.get())
for _ in range(delay):
if not self.running:
break
time.sleep(1)
if not self.loop_var.get():
break
except:
pass
self.thread_status[idx] = False
self.log_labels[idx].config(text="Dừng")
driver.quit()
def monitor_threads(self):
while self.running:
time.sleep(60) # kiểm tra mỗi 60 giây, bạn có thể chỉnh thời gian
for i in range(self.active_threads):
alive = self.thread_status[i]
if not alive and self.running:
try:
self.log_labels[i].config(text="Khởi động lại...")
t = threading.Thread(target=self.worker, args=(i,), daemon=True)
self.threads[i] = t # Ghi đè lại thread cũ
t.start()
except Exception as e:
print(f"Lỗi khi khởi động lại luồng {i}: {e}")
def start(self):
if self.running:
return
file_path = self.file_entry.get()
if not file_path:
messagebox.showerror("Lỗi", "Vui lòng chọn file chứa link")
return
try:
t1 = int(self.time_from_entry.get())
t2 = int(self.time_to_entry.get())
if t1 > t2:
raise ValueError("Giá trị 'Từ' phải nhỏ hơn hoặc bằng 'Đến'")
except:
messagebox.showerror("Lỗi", "Vui lòng nhập đúng định dạng thời gian")
return
self.links = self.read_links(file_path)
if not self.links:
messagebox.showerror("Lỗi", "Không tìm thấy link hợp lệ trong file")
return
self.running = True
self.drivers = []
self.threads = []
self.active_threads = min(self.thread_count_var.get(), self.max_threads)
threading.Thread(target=self.launch_threads_sequentially, daemon=True).start()
monitor = threading.Thread(target=self.monitor_threads, daemon=True)
monitor.start()
# Giãn cách thời mở từng luồng tránh gây lag đơ máy
def launch_threads_sequentially(self):
for i in range(self.active_threads):
if not self.running:
break
t = threading.Thread(target=self.worker, args=(i,), daemon=True)
self.threads.append(t)
t.start()
time.sleep(self.delay_between_threads_var.get())
def stop(self):
self.running = False
for t in self.threads:
t.join(timeout=1)
for driver in self.drivers:
try:
driver.quit()
except:
pass
if __name__ == '__main__':
root = tk.Tk()
app = AccessLinksApp(root)
root.mainloop()