503 lines
20 KiB
Python
503 lines
20 KiB
Python
# -*- coding:utf-8 -*-
|
||
import configparser
|
||
import os
|
||
import pathlib
|
||
import re
|
||
import subprocess
|
||
import sys
|
||
import time
|
||
from configparser import ExtendedInterpolation
|
||
# import winreg
|
||
from subprocess import Popen
|
||
|
||
import psutil
|
||
import pymysql
|
||
import requests
|
||
from PyQt5.QtCore import pyqtSignal, QThread
|
||
from PyQt5.QtGui import QTextCursor
|
||
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
|
||
|
||
# 界面文件为 mainui.py
|
||
from mainui import *
|
||
|
||
configFile = 'config.ini'
|
||
# 创建配置文件对象
|
||
config = configparser.ConfigParser(interpolation=ExtendedInterpolation(), inline_comment_prefixes=['#', ';'], allow_no_value=True)
|
||
# 读取配置文件
|
||
config.read(configFile, encoding='utf-8')
|
||
|
||
|
||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||
def __init__(self, parent=None):
|
||
super(MainWindow, self).__init__(parent)
|
||
self.setupUi(self)
|
||
|
||
self.apktool_path = config['TOOL_PATH']['apktool_path']
|
||
self.android_name = config['ANDROID']['android_name']
|
||
self.android_name_file = config['ANDROID']['android_name_file']
|
||
self.tmp_android_name = config['ANDROID']['tmp_android_name']
|
||
self.new_android_name = config['ANDROID']['new_android_name']
|
||
|
||
# 初始赋值
|
||
self.nowIpLabel.setText(config['GAME']['now_ip'])
|
||
self.newIpInput.setText(config['GAME']['new_ip'])
|
||
self.nowGameLabel.setText(config['GAME']['game_name'])
|
||
self.newGameInput.setText(config['GAME']['game_name'])
|
||
|
||
# 设置按钮状态
|
||
if not config.has_section('NGINX') and not config.has_section('APACHE'):
|
||
self.nginxButton.setDisabled(True)
|
||
elif config.has_section('APACHE'):
|
||
self.nginxButton.setText("启动Apache")
|
||
if isinstance(checkprocess("httpd.exe"), int):
|
||
self.nginxButton.setText("关闭Apache")
|
||
else:
|
||
self.nginxButton.setText("启动Nginx")
|
||
if isinstance(checkprocess("nginx.exe"), int):
|
||
self.nginxButton.setText("关闭Nginx")
|
||
|
||
if not config.has_section('MYSQL'):
|
||
self.mysqlButton.setDisabled(True)
|
||
else:
|
||
if isinstance(checkprocess("mysqld.exe"), int):
|
||
self.mysqlButton.setText("关闭MySql")
|
||
else:
|
||
self.mysqlButton.setText("启动MySql")
|
||
|
||
if not config.has_section('WEB'):
|
||
self.gmurlButton.setDisabled(True)
|
||
self.yyurlButton.setDisabled(True)
|
||
else:
|
||
self.gmurlButton.setToolTip("<html><head/><body><p>网址:" + config['WEB']['gm_url'] + "<br/>帐号:" + config['WEB']['gm_user'] + "<br/>密码:" + config['WEB']['gm_pass'] + "<br/>校验码:" + config['WEB']['gm_code'] + "</p></body></html>")
|
||
self.yyurlButton.setToolTip("<html><head/><body><p>网址:" + config['WEB']['game_url'] + "<br/>帐号:" + config['WEB']['game_user'] + "<br/>密码:" + config['WEB']['game_pass'] + "<br/>校验码:" + config['WEB']['game_code'] + "</p></body></html>")
|
||
|
||
if config.has_section('ANDROID'):
|
||
self.fanbianyiButton.setToolTip("反编译的APK路径:<br>" + config['ANDROID']['android_name'] + "<br>反编译后的文件路径:<br>" + config['ANDROID']['android_name_file'])
|
||
self.shengchengButton.setToolTip("生成的APK路径:<br>" + config['ANDROID']['tmp_android_name'])
|
||
self.qianmingButton.setToolTip("签名后的APK路径:<br>" + config['ANDROID']['new_android_name'] + "<br>密钥路径:<br>" + config['TOOL_PATH']['apktool_path'] + "key.keystore")
|
||
# 初始化JAVA配置
|
||
if not os.getenv('JAVA_HOME'):
|
||
java_path = config['TOOL_PATH']['java_path']
|
||
os.environ['JAVA_HOME'] = java_path
|
||
os.environ['path'] = os.getenv('path') + java_path + 'bin;' + java_path + 'jre\\bin;'
|
||
os.environ['CLASSPATH'] = java_path + 'bin;' + java_path + 'lib\\dt.jar;' + java_path + 'lib\\tools.jar;'
|
||
# print(os.getenv('JAVA_HOME'))
|
||
# print(os.getenv('CLASSPATH'))
|
||
# print(os.getenv('path'))
|
||
|
||
def saveSet(self, event):
|
||
print('保存设置,按钮被单击')
|
||
message = QMessageBox.information(self, "提示信息", "确定要保存设置吗?", QMessageBox.Ok | QMessageBox.No, QMessageBox.No)
|
||
if message == QMessageBox.No:
|
||
return
|
||
|
||
# 取值
|
||
now_ip = config['GAME']['now_ip']
|
||
new_ip = self.newIpInput.text()
|
||
now_game = config['GAME']['game_name']
|
||
new_game = self.newGameInput.text()
|
||
compile_ip = re.compile('^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$')
|
||
|
||
# 验证IP地址格式
|
||
if (new_ip == "") or new_game == "" or not (compile_ip.match(new_ip)):
|
||
QMessageBox.information(self, "提示信息", "IP地址、游戏名称为空或有误,请正确填写IPv4地址或游戏名称!")
|
||
return
|
||
|
||
# 处理SQL语句
|
||
if config.has_section('GAME_DATA_SQL'):
|
||
sqls = []
|
||
for key, value in config.items('GAME_DATA_SQL'):
|
||
print(key, value)
|
||
sql = value.replace('~【game_ip】~', new_ip)
|
||
sql = sql.replace('~【game_name】~', new_game)
|
||
sqls.append(sql)
|
||
print(key, sql)
|
||
|
||
# 判断MYSQL是否启动
|
||
if sqls:
|
||
if isinstance(checkprocess("mysqld.exe"), int):
|
||
mysql_run(sqls)
|
||
else:
|
||
message = QMessageBox.information(self, "提示信息", "MYSQL尚未启动,数据库相关脚本无法执行,是否现在启动MYSQL?", QMessageBox.Ok | QMessageBox.No, QMessageBox.Ok)
|
||
if message == QMessageBox.Ok:
|
||
self.mysql(self.mysqlButton) # 触发MYSQL启动按钮
|
||
sum = 0
|
||
# 以0.5秒的频次检测MYSQL是否启动,超过20次则超时
|
||
while not isinstance(checkprocess("mysqld.exe"), int):
|
||
if sum > 20:
|
||
QMessageBox.information(self, "提示信息", "MYSQL启动失败,请重新尝试!")
|
||
return
|
||
time.sleep(0.5)
|
||
sum = sum + 1
|
||
mysql_run(sqls)
|
||
else:
|
||
return
|
||
|
||
# 配置文件处理
|
||
sum = 0
|
||
for key, value in config.items('GAME_FILE_PATH'):
|
||
print(key, value)
|
||
# 处理文件编码
|
||
if len(value.split(",")) < 2:
|
||
code = config['GAME']['file_encoding']
|
||
else:
|
||
code = value.split(",")[1]
|
||
filename = value.split(",")[0]
|
||
|
||
# 执行文件内容替换
|
||
try:
|
||
with open(filename, 'rt+', encoding=code) as f:
|
||
t = f.read()
|
||
t = t.replace(now_ip, new_ip)
|
||
t = t.replace(now_game, new_game)
|
||
# 读写偏移位置移到最开始处
|
||
f.seek(0, 0)
|
||
f.write(t)
|
||
# 设置文件结尾 EOF
|
||
f.truncate()
|
||
sum = sum + 1
|
||
except:
|
||
QMessageBox.information(self, "提示信息", "替换“" + filename + "”出错,可能文件不存在或编码不对,请检查需要替换的文件编码与配置文件编码是否相符!")
|
||
return
|
||
# 写入配置文件
|
||
config.set('GAME', 'game_name', new_game)
|
||
config.set('GAME', 'now_ip', new_ip)
|
||
config.set('GAME', 'new_ip', new_ip)
|
||
saveconfig = open(configFile, 'wt', encoding=config['GAME']['file_encoding'])
|
||
config.write(saveconfig) # 把要修改的节点的内容写到文件中
|
||
saveconfig.close()
|
||
|
||
# 设置按钮文字变化
|
||
self.nowGameLabel.setText(new_game)
|
||
self.nowIpLabel.setText(new_ip)
|
||
|
||
# 成功提示
|
||
QMessageBox.information(self, "提示信息", "配置保存成功!重启游戏后生效!<br>游戏名称:" + new_game + "----游戏IP:" + new_ip + "<br>共配置了" + str(sum) + "个文件")
|
||
print('修改完成:' + new_game + ':' + new_ip)
|
||
|
||
def nginx(self, event):
|
||
if self.nginxButton.text() == '启动Nginx':
|
||
Popen('start .\\nginx.exe',
|
||
shell=True,
|
||
cwd=config['NGINX']['nginx_path'],
|
||
# encoding='utf-8'
|
||
)
|
||
Popen(
|
||
config['PHP']['php_spawner_path'] + 'php-cgi-spawner.exe "' + config['PHP']['php_path'] + 'php-cgi.exe -c ' + config['PHP']['php_path'] + 'php.ini" ' + config['PHP']['php_cgi_port'] + ' 1+16',
|
||
shell=True,
|
||
# cwd=config['GAME']['dir'] + 'phpstudy_pro',
|
||
# encoding='utf-8'
|
||
)
|
||
self.nginxButton.setText("关闭Nginx")
|
||
elif self.nginxButton.text() == '关闭Nginx':
|
||
Popen('.\\nginx.exe -s stop',
|
||
shell=True,
|
||
cwd=config['NGINX']['nginx_path'],
|
||
# encoding='utf-8'
|
||
)
|
||
Popen('taskkill /f /t /im php-cgi-spawner.exe',
|
||
shell=True,
|
||
# encoding='utf-8'
|
||
)
|
||
Popen('taskkill /f /t /im php-cgi.exe',
|
||
shell=True,
|
||
# encoding='utf-8'
|
||
)
|
||
self.nginxButton.setText("启动Nginx")
|
||
elif self.nginxButton.text() == '启动Apache':
|
||
Popen('.\\httpd.exe',
|
||
shell=True,
|
||
cwd=config['APACHE']['apache_path'] + 'bin\\',
|
||
# encoding='utf-8'
|
||
)
|
||
self.nginxButton.setText("关闭Apache")
|
||
elif self.nginxButton.text() == '关闭Apache':
|
||
Popen('.\\httpd.exe –k stop',
|
||
shell=True,
|
||
cwd=config['APACHE']['apache_path'] + 'bin\\',
|
||
# encoding='utf-8'
|
||
)
|
||
Popen('taskkill /f /t /im httpd.exe',
|
||
shell=True,
|
||
# encoding='utf-8'
|
||
)
|
||
self.nginxButton.setText("启动Apache")
|
||
|
||
# print(process)
|
||
# os.chdir("D:\\LYserver\\phpstudy_pro\\Extensions\\Nginx1.15.11")
|
||
# nginxtype = os.system('start .\\nginx.exe') # 不弹出界面
|
||
# if nginxtype
|
||
# os.system('start .\\nginx.exe') #弹出界面
|
||
print('启动Nginx,按钮被单击')
|
||
|
||
def mysql(self, event):
|
||
if self.mysqlButton.text() == '启动MySql':
|
||
Popen('.\\mysqld.exe --console',
|
||
shell=True,
|
||
cwd=config['MYSQL']['mysql_path'] + 'bin',
|
||
# encoding='utf-8'
|
||
)
|
||
self.mysqlButton.setText("关闭MySql")
|
||
else:
|
||
Popen('taskkill /f /t /im mysqld.exe',
|
||
shell=True,
|
||
# encoding='utf-8'
|
||
)
|
||
self.mysqlButton.setText("启动MySql")
|
||
print('启动MySql,按钮被单击')
|
||
|
||
def game(self, event):
|
||
if self.gameButton.text() == '启动游戏':
|
||
# 读取游戏启动路径
|
||
for key, value in config.items('GAME_PATH'):
|
||
print(key, value)
|
||
# 处理启动时间
|
||
if len(value.split(",")) < 2:
|
||
sleeptime = 0
|
||
else:
|
||
sleeptime = float(value.split(",")[1])
|
||
game_file = value.split(",")[0]
|
||
# 处理启动路径
|
||
game_path = '\\'.join(value.split("\\")[0:-1])
|
||
# print(game_path)
|
||
|
||
try:
|
||
Popen('start ' + game_file,
|
||
shell=True,
|
||
cwd=game_path,
|
||
# encoding='utf-8'
|
||
)
|
||
time.sleep(float(sleeptime)) # 延迟启动时间
|
||
except:
|
||
QMessageBox.information(self, "提示信息", "启动“" + game_file + "”出错,可能文件不存在或配置不对!")
|
||
return
|
||
self.gameButton.setText("关闭游戏")
|
||
else:
|
||
# 读取游戏启动路径
|
||
for key, value in config.items('GAME_PATH'):
|
||
print(key, value)
|
||
# 获取进程名称并结束进程
|
||
game_file = value.split(",")[0].split("\\")
|
||
game_file = game_file[len(game_file) - 1]
|
||
try:
|
||
Popen(
|
||
'taskkill /f /t /im ' + game_file,
|
||
shell=True,
|
||
# encoding='utf-8'
|
||
)
|
||
except:
|
||
QMessageBox.information(self, "提示信息", "关闭游戏进程:“" + game_file + "”出错!")
|
||
return
|
||
# Popen(
|
||
# 'taskkill /f /t /im LocalLogServer64_R.exe & taskkill /f /t /im LoggerServer64_R.exe & taskkill /f /t /im SessionServer64_R.exe & taskkill /f /t /im NameServer64_R.exe & taskkill /f /t /im LogicServerCQ64_R.exe & taskkill /f /t /im GateServer64_R.exe & taskkill /f /t /im DBCenterServer64_R.exe & taskkill /f /t /im DBServer64_R.exe & taskkill /f /t /im BackStageServer64_R.exe & taskkill /f /t /im AMServer64_R.exe',
|
||
# shell=True,
|
||
# # encoding='utf-8'
|
||
# )
|
||
self.gameButton.setText("启动游戏")
|
||
print('启动游戏,按钮被单击')
|
||
|
||
def fanbianyi(self, event):
|
||
obj = self.fanbianyiButton
|
||
# obj.setText('运行中')
|
||
title = obj.text()
|
||
cmd = 'apktool d ' + self.android_name + ' -f -o ' + self.android_name_file
|
||
cwd = self.apktool_path
|
||
code = "gbk"
|
||
path = self.android_name_file
|
||
self.add_cmd_msg(cmd, cwd, title, obj, path, code)
|
||
print('反编译APK,按钮被单击')
|
||
|
||
def shengcheng(self, event):
|
||
obj = self.shengchengButton
|
||
# obj.setText('运行中')
|
||
title = obj.text()
|
||
cmd = 'apktool b ' + self.android_name_file + ' -o ' + self.tmp_android_name
|
||
cwd = self.apktool_path
|
||
code = "gbk"
|
||
path = self.tmp_android_name
|
||
self.add_cmd_msg(cmd, cwd, title, obj, path, code)
|
||
print('生成APK,按钮被单击')
|
||
|
||
def qianming(self, event):
|
||
obj = self.qianmingButton
|
||
# obj.setText('运行中')
|
||
title = obj.text()
|
||
cmd = 'jarsigner -verbose -keystore key.keystore -storepass 123456 -signedjar ' + self.new_android_name + ' ' + self.tmp_android_name + ' key.keystore'
|
||
cwd = self.apktool_path
|
||
code = "gbk"
|
||
path = self.new_android_name
|
||
self.add_cmd_msg(cmd, cwd, title, obj, path, code)
|
||
print('APK签名,按钮被单击')
|
||
|
||
def heidisql(self, event):
|
||
cmd = 'start "" ' + config['TOOL_PATH']['heidisql_path']
|
||
Popen(cmd,
|
||
shell=True,
|
||
# cwd=config['MYSQL']['mysql_path'] + 'bin',
|
||
# encoding='utf-8'
|
||
)
|
||
print('heidisql,按钮被单击')
|
||
|
||
def gmurl(self, event):
|
||
cmd = 'start ' + config['WEB']['gm_url']
|
||
Popen(cmd,
|
||
shell=True,
|
||
# cwd=config['MYSQL']['mysql_path'] + 'bin',
|
||
# encoding='utf-8'
|
||
)
|
||
print('gmurl,按钮被单击')
|
||
# TODO 增加自动登录GM后台功能
|
||
|
||
def yyurl(self, event):
|
||
cmd = 'start ' + config['WEB']['game_url']
|
||
Popen(cmd,
|
||
shell=True,
|
||
# cwd=config['MYSQL']['mysql_path'] + 'bin',
|
||
# encoding='utf-8'
|
||
)
|
||
print('yyurl,按钮被单击')
|
||
# TODO 增加自动登录后台功能
|
||
|
||
# VC运行库
|
||
def msvbcrt(self, event):
|
||
cmd = 'start "" ' + config['TOOL_PATH']['msvbcrt_path']
|
||
Popen(cmd,
|
||
shell=True,
|
||
# cwd=config['MYSQL']['mysql_path'] + 'bin',
|
||
# encoding='utf-8'
|
||
)
|
||
print('VC运行库,按钮被单击')
|
||
|
||
# 程序升级
|
||
def up(self, event):
|
||
if self.upButton.text() == '检查新版' or self.upButton.text() == '无新版本':
|
||
newVersion = getNewVersion() # 获取新版本号
|
||
# if os.path.isfile("upgrade.bat"): # 判断是否有upgrade.bat这个文件,有就删除
|
||
# os.remove("upgrade.bat")
|
||
if version < newVersion: # 判断当前程序是否是最新版本
|
||
self.upButton.setText("新版本:" + str(newVersion))
|
||
else:
|
||
self.upButton.setText("无新版本")
|
||
print('当前版本:', version, '\t最新版本:', newVersion)
|
||
else:
|
||
cmd = 'start ' + 'https://shileiye.com/'
|
||
Popen(cmd,
|
||
shell=True,
|
||
)
|
||
print('检查新版,按钮被单击')
|
||
# TODO 增加自动下载更新功能
|
||
|
||
# 利用新线程进行脚本执行回显
|
||
def add_cmd_msg(self, cmd, cwd="", title="", obj="", path="", code="utf8"):
|
||
obj.setEnabled(False)
|
||
self.CMDtextEdit.clear()
|
||
self.CMDtextEdit.append(title + "脚本开始执行!")
|
||
self.work = Thread(cmd, cwd, title, obj, path, code)
|
||
self.work.trigger.connect(self.show_msg) # 线程中的trigger与主类中的方法进行绑定
|
||
self.work.daemon = True # 主进程退出则该线程也退出
|
||
self.work.start() # 开启线程
|
||
|
||
# 更新UI方法
|
||
def show_msg(self, str):
|
||
self.CMDtextEdit.moveCursor(QTextCursor.End)
|
||
self.CMDtextEdit.append(str)
|
||
# self.CMDtextEdit.insertPlainText(str)
|
||
# self.CMDtextEdit.insertHtml(str)
|
||
|
||
|
||
# 线程类
|
||
class Thread(QThread):
|
||
trigger = pyqtSignal(str) # 注意pyqtSignal一定要实例到__init__前面
|
||
|
||
def __init__(self, cmd, cwd="", title="", obj="", path="", code="utf8"):
|
||
super(Thread, self).__init__()
|
||
# 定义的变量
|
||
self.cmd = cmd
|
||
self.cwd = cwd
|
||
self.title = title
|
||
self.obj = obj
|
||
self.path = path
|
||
self.code = code
|
||
self.state = True
|
||
|
||
# 执行耗时操作
|
||
def run(self):
|
||
process = subprocess.Popen(self.cmd, shell=True, cwd=self.cwd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||
while process.poll() is None:
|
||
line = process.stdout.readline()
|
||
line = line.strip()
|
||
if line:
|
||
self.trigger.emit(line.decode(self.code, 'ignore'))
|
||
print(line.decode(self.code, 'ignore'))
|
||
self.trigger.emit(self.title + '脚本执行结束!')
|
||
self.obj.setEnabled(True)
|
||
# self.obj.setText(self.title)
|
||
# print(self.obj)
|
||
# self.fanbianyiButton.setEnabled(False)
|
||
# self.fanbianyiButton.setText('运行中')
|
||
if self.path != "":
|
||
self.trigger.emit('文件路径:' + self.path)
|
||
startfile(self.path)
|
||
|
||
|
||
# MYSQL操作函数
|
||
def mysql_run(sqls, table=""):
|
||
print(sqls)
|
||
# 打开数据库连接
|
||
db = pymysql.connect(host=config['MYSQL']['mysql_host'],
|
||
user=config['MYSQL']['mysql_user'],
|
||
password=config['MYSQL']['mysql_pass'],
|
||
database=table,
|
||
port=int(config['MYSQL']['mysql_port'])
|
||
)
|
||
# 使用cursor()方法获取操作游标
|
||
cursor = db.cursor()
|
||
for sql in sqls:
|
||
try:
|
||
# 执行SQL语句
|
||
cursor.execute(sql)
|
||
# 提交到数据库执行
|
||
db.commit()
|
||
print('更新成功')
|
||
except:
|
||
print('出错了')
|
||
# 发生错误时回滚
|
||
db.rollback()
|
||
# 关闭数据库连接
|
||
db.close()
|
||
print('MySql执行完毕')
|
||
|
||
|
||
# 进程判断,返回进程ID
|
||
def checkprocess(processname):
|
||
pl = psutil.pids()
|
||
for pid in pl:
|
||
if psutil.Process(pid).name() == processname:
|
||
return pid
|
||
|
||
|
||
# 打开文件或文件夹,并且选中文件
|
||
def startfile(filename):
|
||
try:
|
||
os.startfile(f'explorer /select, "{pathlib.Path(filename)}')
|
||
except:
|
||
subprocess.Popen(f'explorer /select, "{pathlib.Path(filename)}')
|
||
|
||
|
||
# 获取最新程序版本号
|
||
def getNewVersion():
|
||
url = r'http://127.0.0.1:82/Version.txt'
|
||
try:
|
||
value = requests.get(url, timeout=10).content.decode()
|
||
except:
|
||
value = 0
|
||
return float(value)
|
||
|
||
|
||
if __name__ == '__main__':
|
||
version = 1.0
|
||
app = QApplication(sys.argv)
|
||
myWin = MainWindow()
|
||
myWin.show()
|
||
sys.exit(app.exec_())
|