main.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. import ctypes
  2. import platform
  3. import subprocess
  4. import sys
  5. import os
  6. import threading
  7. import time
  8. from datetime import datetime
  9. from PyQt5.QtCore import Qt, QUrl, QDateTime, QThread, pyqtSignal, pyqtSlot
  10. from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QFileDialog, QMessageBox, QDateTimeEdit, QPushButton
  11. from PyQt5.QtGui import QDesktopServices
  12. from app import login_account, run_threading_order, run_daily_job, run_manual_job, cancel_manual_job, stop_order_job, \
  13. write_ticket_info
  14. from litter_helper import Ui_menu # 确保这个导入路径是正确的
  15. from tools.utils import save_all_proxy_ip_v3
  16. import winreg
  17. from pathlib import Path
  18. # 定义 Redis 安装程序路径
  19. REDIS_INSTALLER_PATH = "Redis-x64-5.0.14.1.msi" # 替换为实际的安装程序路径
  20. class ClickableLabel(QLabel):
  21. def __init__(self, parent=None, file_path=None):
  22. super().__init__(parent)
  23. self.file_path = file_path
  24. def mousePressEvent(self, event):
  25. if event.button() == Qt.LeftButton:
  26. self.emit_click_event()
  27. def emit_click_event(self):
  28. if self.file_path:
  29. self.parent().on_label_click(self.file_path)
  30. def get_resource_path(relative_path):
  31. """获取资源文件的绝对路径"""
  32. if getattr(sys, 'frozen', False): # 是否为PyInstaller打包的exe文件
  33. # 返回exe文件所在的绝对路径
  34. base_path = os.path.dirname(sys.executable)
  35. else: # 在开发环境下运行
  36. # 返回脚本文件所在的绝对路径
  37. base_path = os.path.dirname(__file__)
  38. return os.path.join(base_path, relative_path)
  39. def get_dir_path(relative_path):
  40. """获取资源文件路径"""
  41. base_path = getattr(sys, '_MEIPASS', str(Path(__file__).parent.absolute()))
  42. return Path(base_path, relative_path)
  43. # 停止定时任务
  44. def on_stop_time_button_click():
  45. print(f"停止定时任务: {time.time()}")
  46. cancel_manual_job()
  47. # 写入文件
  48. def on_write_file_button_click():
  49. print(f"写入文件:{time.time()}")
  50. write_ticket_info("abcd", "1234556")
  51. class WorkerThread(QThread):
  52. """用于执行下单逻辑的线程"""
  53. signal = pyqtSignal(str) # 定义一个信号,用于将信息传递回主线程
  54. def __init__(self, thread_num, accounts_file, net_url):
  55. super().__init__()
  56. self.thread_num = thread_num
  57. self.accounts_file = accounts_file
  58. self.net_url = net_url
  59. def run(self):
  60. try:
  61. run_threading_order(self.thread_num, self.accounts_file, self.net_url)
  62. self.signal.emit("下单完成") # 发送信号,通知主线程下单完成
  63. except Exception as e:
  64. self.signal.emit(f"下单失败: {e}") # 发送信号,通知主线程下单失败
  65. class LoginThread(QThread):
  66. """用于执行登录逻辑的线程"""
  67. signal = pyqtSignal(str) # 定义一个信号,用于将信息传递回主线程
  68. def __init__(self, thread_num, accounts_file, pocket_url):
  69. super().__init__()
  70. self.thread_num = thread_num
  71. self.accounts_file = accounts_file
  72. self.pocket_url = pocket_url
  73. def run(self):
  74. try:
  75. login_account(self.thread_num, self.accounts_file, self.pocket_url)
  76. self.signal.emit("登录成功") # 发送信号,通知主线程登录成功
  77. except Exception as e:
  78. self.signal.emit(f"登录失败: {e}") # 发送信号,通知主线程登录失败
  79. class MainWindow(QMainWindow, Ui_menu):
  80. def __init__(self, param1, param2):
  81. super().__init__()
  82. self.setupUi(self)
  83. # 使用传递的参数
  84. self.param1 = param1
  85. self.param2 = param2
  86. # 设置标签的文本为传递的参数
  87. # self.label.setText(f"参数1: {self.param1}, 参数2: {self.param2}")
  88. self.concurrencyLineEdit.setText("1")
  89. self.urlLineEdit.setText("https://t.livepocket.jp/e/l3im7")
  90. # 登录账号
  91. self.loginPushButton.clicked.connect(self.on_login_button_click)
  92. # 开始下单
  93. self.startPushButton.clicked.connect(self.on_start_button_click)
  94. # 停止下单
  95. self.stopOrderPushButton.clicked.connect(self.on_stop_button_click)
  96. # 定时开始
  97. self.startTimePushButton.clicked.connect(self.on_start_time_button_click)
  98. # 停止定时任务
  99. self.stopTimePushButton.clicked.connect(on_stop_time_button_click)
  100. # 写入文件
  101. # self.writeFilePushButton.clicked.connect(on_write_file_button_click)
  102. # 编辑账号
  103. # 获取 QLabel 控件并替换为 ClickableLabel
  104. self.accountsLabel = self.findChild(QLabel, "accountsLabel")
  105. if self.accountsLabel:
  106. # 替换为 ClickableLabel
  107. self.clickableAccountsLabel = ClickableLabel(self, file_path=get_resource_path("accounts.txt"))
  108. self.clickableAccountsLabel.setObjectName("accountsLabel")
  109. self.clickableAccountsLabel.setText("编辑账号")
  110. self.clickableAccountsLabel.setGeometry(self.accountsLabel.geometry())
  111. self.clickableAccountsLabel.show()
  112. self.accountsLabel.deleteLater() # 删除原来的 QLabel 控件
  113. # 编辑IP代理池
  114. # 获取 QLabel 控件并替换为 ClickableLabel
  115. self.ipPoolLabel = self.findChild(QLabel, "ipPoolLabel")
  116. if self.ipPoolLabel:
  117. # 替换为 ClickableLabel
  118. self.clickableIpPoolLabel = ClickableLabel(self, file_path=get_resource_path("proxy_list.txt"))
  119. self.clickableIpPoolLabel.setObjectName("ipPoolLabel")
  120. self.clickableIpPoolLabel.setText("编辑代理池")
  121. self.clickableIpPoolLabel.setGeometry(self.ipPoolLabel.geometry())
  122. self.clickableIpPoolLabel.show()
  123. self.ipPoolLabel.deleteLater() # 删除原来的 QLabel 控件
  124. # 获取 QDateTimeEdit 控件并设置显示格式
  125. self.startDateTimeEdit = self.findChild(QDateTimeEdit, "startDateTimeEdit")
  126. if self.startDateTimeEdit:
  127. self.startDateTimeEdit.setDisplayFormat("yyyy-MM-dd HH:mm:ss")
  128. # 设置当前时间
  129. self.startDateTimeEdit.setDateTime(QDateTime.currentDateTime())
  130. # 获取 QDateTimeEdit 控件并设置显示格式
  131. self.endDateTimeEdit = self.findChild(QDateTimeEdit, "endDateTimeEdit")
  132. if self.endDateTimeEdit:
  133. self.endDateTimeEdit.setDisplayFormat("yyyy-MM-dd HH:mm:ss")
  134. # 设置当前时间
  135. self.endDateTimeEdit.setDateTime(QDateTime.currentDateTime())
  136. # 连接 watchPushButton 点击事件到槽函数
  137. self.watchPushButton = self.findChild(QPushButton, "watchPushButton")
  138. if self.watchPushButton:
  139. self.watchPushButton.clicked.connect(self.on_watch_button_click)
  140. # 检查 Redis 是否安装
  141. self.check_redis_installation()
  142. def closeEvent(self, event):
  143. """重写 closeEvent 方法,在窗口关闭时终止程序"""
  144. reply = QMessageBox.question(self, '退出', "确定要退出吗?",
  145. QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
  146. if reply == QMessageBox.Yes:
  147. event.accept() # 接受关闭事件
  148. sys.exit() # 退出应用程序
  149. else:
  150. event.ignore() # 忽略关闭事件
  151. def on_label_click(self, file_path):
  152. if os.path.exists(file_path):
  153. try:
  154. QDesktopServices.openUrl(QUrl.fromLocalFile(file_path))
  155. except Exception as e:
  156. QMessageBox.critical(self, "Error", f"无法打开文件: {e}")
  157. else:
  158. QMessageBox.critical(self, "Error", f"文件不存在: {file_path}")
  159. def on_start_button_click(self):
  160. print(f"开始下单!")
  161. # 在按钮点击时执行的操作
  162. # print(f"按钮被点击了!参数1: {self.param1}, 参数2: {self.param2}")
  163. # 获取 QDateTimeEdit 控件的值
  164. if self.startDateTimeEdit:
  165. date_time_value = self.startDateTimeEdit.dateTime()
  166. # print(f"选中的日期和时间: {date_time_value.toString('yyyy-MM-dd HH:mm:ss')}")
  167. # 获取 QDateTimeEdit 控件的值
  168. if self.endDateTimeEdit:
  169. date_time_value = self.endDateTimeEdit.dateTime()
  170. # print(f"选中的日期和时间: {date_time_value.toString('yyyy-MM-dd HH:mm:ss')}")
  171. # 获取并发数
  172. thread_num = 1
  173. if self.concurrencyLineEdit:
  174. # print(f"并发数为: {self.concurrencyLineEdit.text()}")
  175. thread_num = self.concurrencyLineEdit.text()
  176. # url
  177. net_url = None
  178. if self.urlLineEdit:
  179. net_url = self.urlLineEdit.text()
  180. # 创建线程并启动
  181. self.worker_thread = WorkerThread(thread_num, get_resource_path("accounts.txt"), net_url)
  182. self.worker_thread.signal.connect(self.on_worker_thread_signal)
  183. self.worker_thread.start()
  184. # 登录账号
  185. def on_login_button_click(self):
  186. print(f"登录账号! {self.urlLineEdit.text()}")
  187. thread_num = 1
  188. if self.concurrencyLineEdit.text():
  189. thread_num = self.concurrencyLineEdit.text()
  190. pocket_url = None
  191. if self.urlLineEdit.text():
  192. pocket_url = self.urlLineEdit.text()
  193. save_all_proxy_ip_v3(get_resource_path("proxy_list.txt"))
  194. # 创建登录线程
  195. self.login_thread = LoginThread(thread_num, get_resource_path("accounts.txt"), pocket_url)
  196. self.login_thread.signal.connect(self.on_login_thread_signal)
  197. self.login_thread.start()
  198. else:
  199. QMessageBox.warning(self, '警告', '请输入URL')
  200. return
  201. # 定时开始
  202. def on_start_time_button_click(self):
  203. print(f"定时开始:{time.time()}")
  204. net_url = None
  205. if self.urlLineEdit:
  206. net_url = self.urlLineEdit.text()
  207. start_time = self.startDateTimeEdit.text()
  208. print(f"start_time:{start_time}")
  209. # 使用datetime模块解析时间字符串
  210. dt = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
  211. # 提取出时、分、秒
  212. hour = dt.hour
  213. minute = dt.minute
  214. second = dt.second
  215. print(f"Hour: {hour}, Minute: {minute}, Second: {second}")
  216. # 获取并发数
  217. thread_num = self.concurrencyLineEdit.text()
  218. # 创建一个新的线程来运行 run_manual_job 函数
  219. thread = threading.Thread(target=run_manual_job, args=(hour, minute, thread_num, net_url))
  220. thread.start()
  221. else:
  222. QMessageBox.warning(self, '警告', '请输入URL')
  223. return
  224. # 终止下单
  225. def on_stop_button_click(self):
  226. print(f"终止下单! 目标网址: {self.urlLineEdit.text()}")
  227. stop_order_job()
  228. def edit_accounts(self):
  229. # 编辑账号
  230. print(f"编辑账号: {self.urlLineEdit.text()}")
  231. # 查看结果
  232. def on_watch_button_click(self):
  233. # 获取项目当前路径
  234. current_path = sys.path[0]
  235. # 拼接文件夹路径
  236. folder_path = get_dir_path("results") # 假设文件夹名为 "results"
  237. # 判断文件夹是否存在,不存在则创建
  238. if not folder_path.exists():
  239. try:
  240. folder_path.mkdir(parents=True, exist_ok=True)
  241. print(f"文件夹 {folder_path} 已创建")
  242. except Exception as e:
  243. QMessageBox.critical(self, "Error", f"无法创建文件夹: {e}")
  244. return
  245. # 打开文件夹
  246. folder_path = get_resource_path("results") # 假设文件夹名为 "results"
  247. try:
  248. # 使用 QDesktopServices.openUrl 打开文件夹
  249. QDesktopServices.openUrl(QUrl.fromLocalFile(folder_path))
  250. except Exception as e:
  251. QMessageBox.critical(self, "Error", f"无法打开文件夹: {e}")
  252. # 检查 Redis 是否安装
  253. def check_redis_installation(self):
  254. # 检查操作系统
  255. system = platform.system()
  256. if system == "Windows":
  257. # 检查 Redis 服务是否正在运行
  258. try:
  259. key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Services\Redis")
  260. winreg.CloseKey(key)
  261. print("Redis 服务已安装并正在运行")
  262. return
  263. except FileNotFoundError as ex:
  264. print(f"Redis 服务未安装或未运行")
  265. # 如果 Redis 服务未安装,则启动安装程序
  266. if REDIS_INSTALLER_PATH:
  267. try:
  268. subprocess.run([REDIS_INSTALLER_PATH], shell=True)
  269. print("Redis 安装程序已启动")
  270. except Exception as e:
  271. QMessageBox.critical(self, "Error", f"无法启动 Redis 安装程序: {e}")
  272. else:
  273. # 在其他操作系统上,可以使用不同的方法检查 Redis 是否安装
  274. # 例如,可以使用 `which redis-server` 命令
  275. print("当前操作系统不支持自动安装 Redis")
  276. # 处理线程信号
  277. @pyqtSlot(str)
  278. def on_worker_thread_signal(self, message):
  279. QMessageBox.information(self, "下单结果", message)
  280. # 处理登录线程信号
  281. @pyqtSlot(str)
  282. def on_login_thread_signal(self, message):
  283. QMessageBox.information(self, "登录结果", message)
  284. if __name__ == "__main__":
  285. app = QApplication(sys.argv)
  286. # 创建窗口并传递参数
  287. window = MainWindow("Hello", "World")
  288. window.show()
  289. sys.exit(app.exec_())