import tkinter as tk from tkinter import ttk, scrolledtext, messagebox from datetime import datetime import threading import requests # ========== 固定配置 ========== BASE_URL = "http://task.port.run" # 服务器地址(固定) CHANNEL = "自动注册" # 频道 TIMEOUT = "6000" # 任务超时秒数 class NewToolGUI: def __init__(self, root): self.root = root self.root.title("新工具 - 批量购买平台") self.root.geometry("900x850") self.root.resizable(False, False) self.running = False # 样式 style = ttk.Style() style.configure("TLabel", font=("微软雅黑", 10)) style.configure("TButton", font=("微软雅黑", 10)) style.configure("TEntry", font=("微软雅黑", 10)) main_frame = ttk.Frame(root, padding="20 20 20 20") main_frame.pack(fill=tk.BOTH, expand=True) # ========== 账号列表 ========== account_frame = ttk.LabelFrame(main_frame, text="账号列表 (每行一个账号,格式:邮箱 | 密码)", padding="10 10 10 10") account_frame.pack(fill=tk.X, pady=(0, 15)) self.account_list_text = tk.Text(account_frame, height=6, font=("Consolas", 9), wrap=tk.WORD) self.account_list_text.pack(fill=tk.X) self.account_list_text.insert(tk.END, "example1@mail.com | password123\n") self.account_list_text.insert(tk.END, "example2@mail.com | password456\n") # ========== 购买参数 ========== purchase_frame = ttk.LabelFrame(main_frame, text="购买参数", padding="10 10 10 10") purchase_frame.pack(fill=tk.X, pady=(0, 15)) ttk.Label(purchase_frame, text="游戏购买地址:").grid(row=0, column=0, sticky=tk.W, pady=5) self.game_url_var = tk.StringVar(value="") game_url_entry = ttk.Entry(purchase_frame, textvariable=self.game_url_var, width=60) game_url_entry.grid(row=0, column=1, columnspan=2, sticky=tk.W, padx=(10, 0), pady=5) ttk.Label(purchase_frame, text="购买数量:").grid(row=1, column=0, sticky=tk.W, pady=5) self.quantity_var = tk.StringVar(value="1") quantity_entry = ttk.Entry(purchase_frame, textvariable=self.quantity_var, width=10) quantity_entry.grid(row=1, column=1, sticky=tk.W, padx=(10, 0), pady=5) ttk.Label(purchase_frame, text="游戏优惠券代码:").grid(row=2, column=0, sticky=tk.W, pady=5) self.coupon_var = tk.StringVar(value="") coupon_entry = ttk.Entry(purchase_frame, textvariable=self.coupon_var, width=30) coupon_entry.grid(row=2, column=1, sticky=tk.W, padx=(10, 0), pady=5) # ========== 操作按钮 ========== button_frame = ttk.Frame(main_frame) button_frame.pack(fill=tk.X, pady=(0, 15)) self.start_btn = ttk.Button(button_frame, text="开始批量购买", command=self.start_purchase, width=18) self.start_btn.pack(side=tk.LEFT, padx=(0, 10)) self.stop_btn = ttk.Button(button_frame, text="停止", command=self.stop_purchase, width=15, state="disabled") self.stop_btn.pack(side=tk.LEFT, padx=(0, 10)) clear_btn = ttk.Button(button_frame, text="清空日志", command=self.clear_log, width=15) clear_btn.pack(side=tk.LEFT, padx=(10, 0)) # ========== 执行状态 ========== status_frame = ttk.LabelFrame(main_frame, text="执行状态", padding="10 10 10 10") status_frame.pack(fill=tk.X, pady=(0, 15)) self.status_label = ttk.Label(status_frame, text="就绪", font=("微软雅黑", 10)) self.status_label.pack(anchor=tk.W) self.progress_var = tk.StringVar(value="0%") progress_frame = ttk.Frame(status_frame) progress_frame.pack(anchor=tk.W, pady=(5, 0)) ttk.Label(progress_frame, text="进度:", font=("微软雅黑", 9)).pack(side=tk.LEFT) self.progress_bar = ttk.Label(progress_frame, textvariable=self.progress_var, font=("微软雅黑", 9), foreground="blue") self.progress_bar.pack(side=tk.LEFT, padx=(5, 0)) # ========== 日志输出 ========== result_frame = ttk.LabelFrame(main_frame, text="日志输出", padding="10 10 10 10") result_frame.pack(fill=tk.BOTH, expand=True) self.result_text = scrolledtext.ScrolledText( result_frame, wrap=tk.WORD, font=("Consolas", 9), height=15 ) self.result_text.pack(fill=tk.BOTH, expand=True) self.result_text.tag_config("timestamp", foreground="gray") self.result_text.tag_config("info", foreground="black") self.result_text.tag_config("success", foreground="green") self.result_text.tag_config("error", foreground="red") self.result_text.tag_config("warning", foreground="orange") self.result_text.tag_config("debug", foreground="purple") # ================= 日志工具 ================= def log(self, message, level="info"): def _append(): ts = datetime.now().strftime("%H:%M:%S") self.result_text.insert(tk.END, f"[{ts}] ", "timestamp") self.result_text.insert(tk.END, f"{message}\n", level) self.result_text.see(tk.END) self.root.after(0, _append) def set_status(self, text, color="black"): self.root.after(0, lambda: self.status_label.config(text=text, foreground=color)) def set_progress(self, current, total): pct = int(current / total * 100) if total else 0 self.root.after(0, lambda: self.progress_var.set(f"{current}/{total} ({pct}%)")) # ================= 业务逻辑 ================= def parse_accounts(self): raw = self.account_list_text.get("1.0", tk.END).strip() accounts = [] for line in raw.splitlines(): line = line.strip() if not line: continue if "|" in line: parts = [p.strip() for p in line.split("|", 1)] email, password = parts[0], parts[1] else: email, password = line, "" accounts.append((email, password)) return accounts def publish_task(self, content): url = f"{BASE_URL.rstrip('/')}/publish/{CHANNEL}/{TIMEOUT}" try: resp = requests.post(url, json=content, timeout=10) data = resp.json() if data.get("success"): return True, data.get("taskId", "") return False, data.get("error", f"HTTP {resp.status_code}") except Exception as e: return False, str(e) def start_purchase(self): if self.running: messagebox.showwarning("提示", "任务正在执行中") return accounts = self.parse_accounts() if not accounts: messagebox.showwarning("提示", "账号列表为空") return game_url = self.game_url_var.get().strip() if not game_url: messagebox.showwarning("提示", "请填写游戏购买地址") return quantity = self.quantity_var.get().strip() or "1" coupon = self.coupon_var.get().strip() self.running = True self.start_btn.config(state="disabled") self.stop_btn.config(state="normal") self.set_status("正在提交...", "blue") self.set_progress(0, len(accounts)) threading.Thread( target=self._publish_worker, args=(accounts, game_url, quantity, coupon), daemon=True ).start() def _publish_worker(self, accounts, game_url, quantity, coupon): total = len(accounts) success = 0 fail = 0 self.log(f"共 {total} 个账号,开始提交任务...", "info") for idx, (email, password) in enumerate(accounts, start=1): if not self.running: self.log("用户已停止任务", "warning") break content = { "email": email, "password": password, "game_url": game_url, "quantity": quantity, "coupon": coupon, } ok, info = self.publish_task(content) if ok: success += 1 self.log(f"[{idx}/{total}] 已提交: {email} -> {info}", "success") else: fail += 1 self.log(f"[{idx}/{total}] 提交失败: {email} -> {info}", "error") self.set_progress(idx, total) self.log(f"全部完成,成功 {success} 条,失败 {fail} 条", "info") self.set_status(f"完成 (成功 {success} / 失败 {fail})", "green") self.running = False self.root.after(0, lambda: self.start_btn.config(state="normal")) self.root.after(0, lambda: self.stop_btn.config(state="disabled")) def stop_purchase(self): if not self.running: return self.running = False self.log("正在停止任务...", "warning") self.set_status("已停止", "orange") def clear_log(self): self.result_text.delete(1.0, tk.END) self.status_label.config(text="已清空日志", foreground="gray") if __name__ == "__main__": root = tk.Tk() app = NewToolGUI(root) root.mainloop()