[Python] 纯文本查看 复制代码import subprocess
import re
import base64
import json
import time
import urllib.request
import urllib.error
import ssl
import sys
import os
import threading
import tkinter as tk
from tkinter import ttk, messagebox
def is_admin():
"""
检查程序是否以管理员权限运行
"""
try:
return os.getuid() == 0
except AttributeError:
# Windows系统
import ctypes
return ctypes.windll.shell32.IsUserAnAdmin() != 0
def get_client_info():
"""
通过WMIC命令获取LeagueClient的端口和token信息
"""
try:
# 执行WMIC命令获取LeagueClientUx.exe的命令行参数
cmd = 'WMIC PROCESS WHERE "name=\'LeagueClientUx.exe\'" GET commandline'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print("执行WMIC命令失败")
return None, None
# 从输出中提取端口和token
commandline_output = result.stdout
# 使用正则表达式提取port和token
port_match = re.search(r'"--app-port=(\d+)"', commandline_output)
token_match = re.search(r'"--remoting-auth-token=([^"]+)"', commandline_output)
if port_match and token_match:
port = port_match.group(1)
token = token_match.group(1)
return port, token
else:
print("未找到端口或token信息")
return None, None
except Exception as e:
print(f"获取客户端信息时出错: {e}")
return None, None
def create_auth_header(token):
"""
创建认证头
"""
# 将token编码为base64
auth_string = f"riot:{token}"
encoded_auth = base64.b64encode(auth_string.encode('utf-8')).decode('utf-8')
return {
"Authorization": f"Basic {encoded_auth}",
"Accept": "application/json",
"Content-Type": "application/json"
}
def check_game_status(port, token):
"""
检查游戏状态
"""
try:
url = f"https://127.0.0.1:{port}/lol-gameflow/v1/session"
headers = create_auth_header(token)
# 创建不验证SSL的请求上下文
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request, context=context, timeout=5)
data = json.loads(response.read().decode())
return data.get('phase', 'None')
except urllib.error.URLError as e:
# print(f"URL错误: {e}")
return 'None'
except Exception as e:
# print(f"检查游戏状态时出错: {e}")
return 'None'
def check_ready_check_status(port, token):
"""
检查是否处于准备确认状态
"""
try:
url = f"https://127.0.0.1:{port}/lol-matchmaking/v1/ready-check"
headers = create_auth_header(token)
# 创建不验证SSL的请求上下文
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request, context=context, timeout=5)
data = json.loads(response.read().decode())
return data.get('state', 'None')
except urllib.error.URLError as e:
# print(f"URL错误: {e}")
return 'None'
except Exception as e:
# print(f"检查准备状态时出错: {e}")
return 'None'
def accept_match(port, token):
"""
接受匹配
"""
try:
url = f"https://127.0.0.1:{port}/lol-matchmaking/v1/ready-check/accept"
headers = create_auth_header(token)
# 创建不验证SSL的请求上下文
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
# 创建POST请求
request = urllib.request.Request(url, headers=headers, method='POST')
response = urllib.request.urlopen(request, context=context, timeout=5)
if response.status == 204:
print("成功接受匹配!")
return True
else:
print(f"接受匹配失败,状态码: {response.status}")
return False
except urllib.error.HTTPError as e:
if e.code == 204:
print("成功接受匹配!")
return True
else:
print(f"接受匹配失败,HTTP错误码: {e.code}")
return False
except Exception as e:
print(f"接受匹配时出错: {e}")
return False
class LolAutoAcceptGUI:
def __init__(self, root):
self.root = root
self.root.title("LOL 自动接受匹配")
self.root.geometry("500x450")
self.root.resizable(False, False)
# 初始化变量
self.port = None
self.token = None
self.is_running = False
self.delay = 5 # 默认延迟5秒
self.last_accepted = 0 # 上次接受匹配的时间
self.animation_id = None
self.client_check_job = None # 客户端检查任务
# 状态映射
self.status_mapping = {
'None': '未运行',
'Lobby': '大厅中',
'Matchmaking': '正在匹配',
'ReadyCheck': '等待接受',
'ChampSelect': '英雄选择中',
'InProgress': '游戏中',
'Reconnect': '重新连接',
'WaitingForStats': '等待统计',
'PreEndOfGame': '游戏结束前',
'EndOfGame': '游戏结束'
}
# 准备状态映射
self.ready_check_mapping = {
'None': '未知',
'InProgress': '等待接受',
'EveryoneReady': '所有人已准备',
'StrangerCancelled': '陌生人取消',
'PartyCancelled': '队伍取消',
'Error': '错误'
}
self.setup_ui()
self.check_admin()
# 程序启动后自动开始检测
self.root.after(1000, self.auto_start_detection)
def setup_ui(self):
# 设置样式
self.style = ttk.Style()
self.style.theme_use('clam')
# 自定义样式
self.style.configure('Title.TLabel', font=('Arial', 16, 'bold'), foreground='#333333')
self.style.configure('Status.TLabel', font=('Arial', 12, 'bold'), foreground='#333333')
self.style.configure('Section.TLabelframe', font=('Arial', 10, 'bold'))
self.style.configure('Custom.TEntry', font=('Arial', 10))
self.style.configure('Switch.TLabel', font=('Arial', 10, 'bold'))
# 主框架
main_frame = ttk.Frame(self.root, padding="20")
main_frame.pack(fill=tk.BOTH, expand=True)
# 标题
title_label = ttk.Label(main_frame, text="LOL 自动接受匹配", style='Title.TLabel')
title_label.pack(pady=(0, 20))
# 状态显示框架
status_frame = ttk.LabelFrame(main_frame, text="当前状态", padding="15", style='Section.TLabelframe')
status_frame.pack(fill=tk.X, pady=(0, 15))
self.status_label = ttk.Label(status_frame, text="未运行", style='Status.TLabel')
self.status_label.pack()
# 延迟设置框架
delay_frame = ttk.LabelFrame(main_frame, text="接受延迟设置", padding="15", style='Section.TLabelframe')
delay_frame.pack(fill=tk.X, pady=(0, 15))
delay_inner_frame = ttk.Frame(delay_frame)
delay_inner_frame.pack(fill=tk.X)
ttk.Label(delay_inner_frame, text="延迟(秒):", font=('Arial', 10)).pack(side=tk.LEFT)
self.delay_var = tk.StringVar(value="5")
self.delay_entry = ttk.Entry(delay_inner_frame, textvariable=self.delay_var, width=10,
font=('Arial', 10))
self.delay_entry.pack(side=tk.LEFT, padx=(10, 10))
ttk.Label(delay_inner_frame, text="(检测到匹配后延迟多少秒接受)", font=('Arial', 9)).pack(side=tk.LEFT)
# 开关控制框架
switch_frame = ttk.LabelFrame(main_frame, text="自动接受控制", padding="15", style='Section.TLabelframe')
switch_frame.pack(fill=tk.X, pady=(0, 15))
switch_inner_frame = ttk.Frame(switch_frame)
switch_inner_frame.pack(fill=tk.X)
ttk.Label(switch_inner_frame, text="关闭", font=('Arial', 10)).pack(side=tk.LEFT)
# 开关滑块 (0=关闭, 1=开启)
self.switch_var = tk.IntVar(value=1) # 默认设置为开启
self.switch_scale = tk.Scale(switch_inner_frame, from_=0, to=1, orient=tk.HORIZONTAL,
variable=self.switch_var, length=100,
highlightthickness=0, showvalue=0,
troughcolor='#cccccc', bg='#f0f0f0',
activebackground='#0078d7', relief='flat')
self.switch_scale.pack(side=tk.LEFT, padx=10)
ttk.Label(switch_inner_frame, text="开启", font=('Arial', 10)).pack(side=tk.LEFT)
self.switch_status_label = ttk.Label(switch_inner_frame, text="已开启",
font=('Arial', 10, 'bold'), foreground='#008000')
self.switch_status_label.pack(side=tk.LEFT, padx=(10, 0))
# 绑定开关事件
self.switch_scale.configure(command=self.toggle_auto_accept)
# 日志显示框架
log_frame = ttk.LabelFrame(main_frame, text="运行日志", padding="10", style='Section.TLabelframe')
log_frame.pack(fill=tk.BOTH, expand=True)
# 创建日志文本框和滚动条
log_text_frame = ttk.Frame(log_frame)
log_text_frame.pack(fill=tk.BOTH, expand=True)
self.log_text = tk.Text(log_text_frame, height=10, state=tk.DISABLED,
font=("Consolas", 9))
log_scrollbar = ttk.Scrollbar(log_text_frame, orient=tk.VERTICAL, command=self.log_text.yview)
self.log_text.configure(yscrollcommand=log_scrollbar.set)
self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
def auto_start_detection(self):
"""程序启动后自动开始检测"""
self.switch_var.set(1)
self.switch_status_label.config(text="已开启", foreground='#008000')
self.start_listening()
def toggle_auto_accept(self, value):
"""切换自动接受功能"""
if int(value) == 1: # 开启
self.switch_status_label.config(text="已开启", foreground='#008000') # 绿色
self.start_listening()
else: # 关闭
self.switch_status_label.config(text="已关闭", foreground='#cc0000') # 红色
self.stop_listening()
def check_admin(self):
if not is_admin():
messagebox.showerror("权限错误", "请以管理员权限运行此程序!\n右键点击程序,选择'以管理员身份运行'。")
self.root.destroy()
return False
return True
def log_message(self, message):
self.log_text.config(state=tk.NORMAL)
self.log_text.insert(tk.END, f"[{time.strftime('%H:%M:%S')}] {message}\n")
self.log_text.see(tk.END)
self.log_text.config(state=tk.DISABLED)
def update_status(self, gameflow_status, ready_check_status=None):
# 根据游戏流程状态和准备状态显示更准确的信息
if gameflow_status == 'ReadyCheck' and ready_check_status:
display_status = self.ready_check_mapping.get(ready_check_status, ready_check_status)
else:
display_status = self.status_mapping.get(gameflow_status, gameflow_status)
self.status_label.config(text=display_status)
# 如果状态是"等待接受",添加动画效果
if display_status == '等待接受':
self.start_animation()
else:
self.stop_animation()
def start_animation(self):
"""开始状态标签的动画效果"""
self.stop_animation() # 先停止之前的动画
def animate():
current_text = self.status_label.cget("text")
if current_text.endswith("..."):
self.status_label.config(text=current_text[:-3])
else:
self.status_label.config(text=current_text + ".")
self.animation_id = self.root.after(500, animate)
self.animation_id = self.root.after(500, animate)
def stop_animation(self):
"""停止动画效果"""
if self.animation_id:
self.root.after_cancel(self.animation_id)
self.animation_id = None
def get_client_info_wrapper(self):
self.log_message("正在获取League of Legends客户端信息...")
self.port, self.token = get_client_info()
if not self.port or not self.token:
self.log_message("请确保League of Legends客户端正在运行!")
return False
self.log_message(f"成功获取客户端信息:")
self.log_message(f"端口: {self.port}")
self.log_message(f"Token: {self.token}")
return True
def start_listening(self):
# 如果已经在运行,则不重复启动
if self.is_running:
return
try:
self.delay = int(self.delay_var.get())
except ValueError:
messagebox.showwarning("输入错误", "延迟时间必须是数字!")
self.switch_var.set(0) # 将开关设置为关闭
self.switch_status_label.config(text="已关闭", foreground='#cc0000')
return
if self.delay 10: # 至少间隔10秒
self.log_message(f"检测到匹配,将在 {self.delay} 秒后接受...")
# 延迟接受
time.sleep(self.delay)
if self.is_running: # 再次检查是否仍在运行
success = accept_match(self.port, self.token)
if success:
self.log_message("成功接受匹配!")
self.last_accepted = time.time()
else:
self.log_message("接受匹配失败!")
# 每秒检查一次
time.sleep(1)
except Exception as e:
# 检查是否是因为连接断开导致的错误
if self.is_running: # 只有在运行状态下才记录错误
self.log_message(f"运行时出错: {e}")
# 等待5秒后继续
time.sleep(5)
else:
# 如果已经停止,则退出循环
break
def main():
root = tk.Tk()
app = LolAutoAcceptGUI(root)
root.mainloop()
if __name__ == "__main__":
main()
提供一个成品,小伙伴自取.
https://wwuf.lanzoum.com/iw4co33pmyzi
密码:52pj