自动购买.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import tkinter as tk
  2. from tkinter import ttk, scrolledtext, messagebox
  3. from datetime import datetime
  4. import threading
  5. import requests
  6. # ========== 固定配置 ==========
  7. BASE_URL = "http://task.port.run" # 服务器地址(固定)
  8. CHANNEL = "自动注册" # 频道
  9. TIMEOUT = "6000" # 任务超时秒数
  10. class NewToolGUI:
  11. def __init__(self, root):
  12. self.root = root
  13. self.root.title("新工具 - 批量购买平台")
  14. self.root.geometry("900x850")
  15. self.root.resizable(False, False)
  16. self.running = False
  17. # 样式
  18. style = ttk.Style()
  19. style.configure("TLabel", font=("微软雅黑", 10))
  20. style.configure("TButton", font=("微软雅黑", 10))
  21. style.configure("TEntry", font=("微软雅黑", 10))
  22. main_frame = ttk.Frame(root, padding="20 20 20 20")
  23. main_frame.pack(fill=tk.BOTH, expand=True)
  24. # ========== 账号列表 ==========
  25. account_frame = ttk.LabelFrame(main_frame, text="账号列表 (每行一个账号,格式:邮箱 | 密码)", padding="10 10 10 10")
  26. account_frame.pack(fill=tk.X, pady=(0, 15))
  27. self.account_list_text = tk.Text(account_frame, height=6, font=("Consolas", 9), wrap=tk.WORD)
  28. self.account_list_text.pack(fill=tk.X)
  29. self.account_list_text.insert(tk.END, "example1@mail.com | password123\n")
  30. self.account_list_text.insert(tk.END, "example2@mail.com | password456\n")
  31. # ========== 购买参数 ==========
  32. purchase_frame = ttk.LabelFrame(main_frame, text="购买参数", padding="10 10 10 10")
  33. purchase_frame.pack(fill=tk.X, pady=(0, 15))
  34. ttk.Label(purchase_frame, text="游戏购买地址:").grid(row=0, column=0, sticky=tk.W, pady=5)
  35. self.game_url_var = tk.StringVar(value="")
  36. game_url_entry = ttk.Entry(purchase_frame, textvariable=self.game_url_var, width=60)
  37. game_url_entry.grid(row=0, column=1, columnspan=2, sticky=tk.W, padx=(10, 0), pady=5)
  38. ttk.Label(purchase_frame, text="购买数量:").grid(row=1, column=0, sticky=tk.W, pady=5)
  39. self.quantity_var = tk.StringVar(value="1")
  40. quantity_entry = ttk.Entry(purchase_frame, textvariable=self.quantity_var, width=10)
  41. quantity_entry.grid(row=1, column=1, sticky=tk.W, padx=(10, 0), pady=5)
  42. ttk.Label(purchase_frame, text="游戏优惠券代码:").grid(row=2, column=0, sticky=tk.W, pady=5)
  43. self.coupon_var = tk.StringVar(value="")
  44. coupon_entry = ttk.Entry(purchase_frame, textvariable=self.coupon_var, width=30)
  45. coupon_entry.grid(row=2, column=1, sticky=tk.W, padx=(10, 0), pady=5)
  46. # ========== 操作按钮 ==========
  47. button_frame = ttk.Frame(main_frame)
  48. button_frame.pack(fill=tk.X, pady=(0, 15))
  49. self.start_btn = ttk.Button(button_frame, text="开始批量购买", command=self.start_purchase, width=18)
  50. self.start_btn.pack(side=tk.LEFT, padx=(0, 10))
  51. self.stop_btn = ttk.Button(button_frame, text="停止", command=self.stop_purchase, width=15, state="disabled")
  52. self.stop_btn.pack(side=tk.LEFT, padx=(0, 10))
  53. clear_btn = ttk.Button(button_frame, text="清空日志", command=self.clear_log, width=15)
  54. clear_btn.pack(side=tk.LEFT, padx=(10, 0))
  55. # ========== 执行状态 ==========
  56. status_frame = ttk.LabelFrame(main_frame, text="执行状态", padding="10 10 10 10")
  57. status_frame.pack(fill=tk.X, pady=(0, 15))
  58. self.status_label = ttk.Label(status_frame, text="就绪", font=("微软雅黑", 10))
  59. self.status_label.pack(anchor=tk.W)
  60. self.progress_var = tk.StringVar(value="0%")
  61. progress_frame = ttk.Frame(status_frame)
  62. progress_frame.pack(anchor=tk.W, pady=(5, 0))
  63. ttk.Label(progress_frame, text="进度:", font=("微软雅黑", 9)).pack(side=tk.LEFT)
  64. self.progress_bar = ttk.Label(progress_frame, textvariable=self.progress_var,
  65. font=("微软雅黑", 9), foreground="blue")
  66. self.progress_bar.pack(side=tk.LEFT, padx=(5, 0))
  67. # ========== 日志输出 ==========
  68. result_frame = ttk.LabelFrame(main_frame, text="日志输出", padding="10 10 10 10")
  69. result_frame.pack(fill=tk.BOTH, expand=True)
  70. self.result_text = scrolledtext.ScrolledText(
  71. result_frame, wrap=tk.WORD, font=("Consolas", 9), height=15
  72. )
  73. self.result_text.pack(fill=tk.BOTH, expand=True)
  74. self.result_text.tag_config("timestamp", foreground="gray")
  75. self.result_text.tag_config("info", foreground="black")
  76. self.result_text.tag_config("success", foreground="green")
  77. self.result_text.tag_config("error", foreground="red")
  78. self.result_text.tag_config("warning", foreground="orange")
  79. self.result_text.tag_config("debug", foreground="purple")
  80. # ================= 日志工具 =================
  81. def log(self, message, level="info"):
  82. def _append():
  83. ts = datetime.now().strftime("%H:%M:%S")
  84. self.result_text.insert(tk.END, f"[{ts}] ", "timestamp")
  85. self.result_text.insert(tk.END, f"{message}\n", level)
  86. self.result_text.see(tk.END)
  87. self.root.after(0, _append)
  88. def set_status(self, text, color="black"):
  89. self.root.after(0, lambda: self.status_label.config(text=text, foreground=color))
  90. def set_progress(self, current, total):
  91. pct = int(current / total * 100) if total else 0
  92. self.root.after(0, lambda: self.progress_var.set(f"{current}/{total} ({pct}%)"))
  93. # ================= 业务逻辑 =================
  94. def parse_accounts(self):
  95. raw = self.account_list_text.get("1.0", tk.END).strip()
  96. accounts = []
  97. for line in raw.splitlines():
  98. line = line.strip()
  99. if not line:
  100. continue
  101. if "|" in line:
  102. parts = [p.strip() for p in line.split("|", 1)]
  103. email, password = parts[0], parts[1]
  104. else:
  105. email, password = line, ""
  106. accounts.append((email, password))
  107. return accounts
  108. def publish_task(self, content):
  109. url = f"{BASE_URL.rstrip('/')}/publish/{CHANNEL}/{TIMEOUT}"
  110. try:
  111. resp = requests.post(url, json=content, timeout=10)
  112. data = resp.json()
  113. if data.get("success"):
  114. return True, data.get("taskId", "")
  115. return False, data.get("error", f"HTTP {resp.status_code}")
  116. except Exception as e:
  117. return False, str(e)
  118. def start_purchase(self):
  119. if self.running:
  120. messagebox.showwarning("提示", "任务正在执行中")
  121. return
  122. accounts = self.parse_accounts()
  123. if not accounts:
  124. messagebox.showwarning("提示", "账号列表为空")
  125. return
  126. game_url = self.game_url_var.get().strip()
  127. if not game_url:
  128. messagebox.showwarning("提示", "请填写游戏购买地址")
  129. return
  130. quantity = self.quantity_var.get().strip() or "1"
  131. coupon = self.coupon_var.get().strip()
  132. self.running = True
  133. self.start_btn.config(state="disabled")
  134. self.stop_btn.config(state="normal")
  135. self.set_status("正在提交...", "blue")
  136. self.set_progress(0, len(accounts))
  137. threading.Thread(
  138. target=self._publish_worker,
  139. args=(accounts, game_url, quantity, coupon),
  140. daemon=True
  141. ).start()
  142. def _publish_worker(self, accounts, game_url, quantity, coupon):
  143. total = len(accounts)
  144. success = 0
  145. fail = 0
  146. self.log(f"共 {total} 个账号,开始提交任务...", "info")
  147. for idx, (email, password) in enumerate(accounts, start=1):
  148. if not self.running:
  149. self.log("用户已停止任务", "warning")
  150. break
  151. content = {
  152. "email": email,
  153. "password": password,
  154. "game_url": game_url,
  155. "quantity": quantity,
  156. "coupon": coupon,
  157. }
  158. ok, info = self.publish_task(content)
  159. if ok:
  160. success += 1
  161. self.log(f"[{idx}/{total}] 已提交: {email} -> {info}", "success")
  162. else:
  163. fail += 1
  164. self.log(f"[{idx}/{total}] 提交失败: {email} -> {info}", "error")
  165. self.set_progress(idx, total)
  166. self.log(f"全部完成,成功 {success} 条,失败 {fail} 条", "info")
  167. self.set_status(f"完成 (成功 {success} / 失败 {fail})", "green")
  168. self.running = False
  169. self.root.after(0, lambda: self.start_btn.config(state="normal"))
  170. self.root.after(0, lambda: self.stop_btn.config(state="disabled"))
  171. def stop_purchase(self):
  172. if not self.running:
  173. return
  174. self.running = False
  175. self.log("正在停止任务...", "warning")
  176. self.set_status("已停止", "orange")
  177. def clear_log(self):
  178. self.result_text.delete(1.0, tk.END)
  179. self.status_label.config(text="已清空日志", foreground="gray")
  180. if __name__ == "__main__":
  181. root = tk.Tk()
  182. app = NewToolGUI(root)
  183. root.mainloop()