# -*- coding: utf-8 -*- from flask import Flask, render_template,jsonify from flask_socketio import SocketIO, emit from scriptBase.comon import * import pyautogui import base64 import threading from dongri_task import * from collections import deque import json from concurrent.futures import ThreadPoolExecutor from flask_caching import Cache from scriptBase.minio_manage import * import subprocess # 全局线程池,限制最大线程数为1 executor = ThreadPoolExecutor(max_workers=1) cache = Cache(config={'CACHE_TYPE': 'null'}) # 使用 null 缓存类型 app = Flask(__name__) cache.init_app(app) app.config['TEMPLATES_AUTO_RELOAD'] = True socketio = SocketIO(app, cors_allowed_origins="*", max_http_buffer_size=1e8) class GlobalState: event = threading.Event() g_status_list = [] last_time = 0.0 task_queue = deque() last_process = '' isGameBegin = True isReset = False g_times = 0 g_cureNum = 500 g_switch = False g_isRestart = True last_change_time = time.time() g_firstRunBear = True frp_process = None def startup_frpc(): GlobalState.frp_process = subprocess.Popen(["tool/frpc.exe", "-c", "tool/frpc-desktop.toml"]) def terminate_frpc(): if GlobalState.frp_process is not None: proc = GlobalState.frp_process proc.terminate() # 优雅终止 if proc.poll() is None: # 检查是否仍在运行 proc.kill() # 强制终止 @app.after_request def add_no_cache_header(response): # 添加禁用缓存的响应头 response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" response.headers["Pragma"] = "no-cache" response.headers["Expires"] = "0" return response def thread_runTask(): while True: if GlobalState.event.is_set(): GlobalState.task_queue.clear() if len(GlobalState.task_queue) != 0: # 初始时间 current_time = time.time() task = GlobalState.task_queue[-1] GlobalState.task_queue.pop() print(f"-----------{GlobalState.g_times} {task.name} 开始执行-----------") GlobalState.last_process = task.name try: task.run() except Exception as e: print(f"-----------{GlobalState.g_times} {task.name} 执行失败,错误原因:{e}-----------") cost_time = int(time.time() - current_time) send_status(f"{task.name} 执行完成,耗时{cost_time}秒") print(f"-----------{GlobalState.g_times} {task.name} 执行完成,耗时{cost_time}秒-----------") myTimeSleep_small() else: myTimeSleep_big() if GlobalState.isReset: GlobalState.isReset = False cfg = read_cfg() if cfg['switch']: type = update_rungame_type() print(f'启动游戏{type}') restart_game(type) else: restart_game(0) @app.route('/') def index(): return render_template('index_dongri.html') @socketio.on('connect') def handle_connect(): print('Client connected') @socketio.on('disconnect') def handle_disconnect(): print('Client disconnected') def send_hint(msg):#数组信息 emit('processing_hint', msg) def send_todo(): emit('processing_todo', get_todo_msgList()) def send_status(msg):#软件执行状态 try: if not msg == "": # 添加新的状态消息和时间到列表 timestamp = datetime.now().strftime('%H:%M:%S') # 获取当前时间 status_entry = {'msg': msg, 'time': timestamp} # 存储消息和时间 GlobalState.g_status_list.append(status_entry) # 如果列表超过 5 条,移除最早的一条 if len(GlobalState.g_status_list) > 5: GlobalState.g_status_list.pop(0) else: sendStr = '' for item in GlobalState.g_status_list: sendStr = f"{GlobalState.g_times}次-{item['time']}-{item['msg']}
" + sendStr emit('processing_status', sendStr) # 如果消息是 "结束",发送所有状态并清空列表 if msg == "结束": GlobalState.g_status_list = [] # 清空列表 GlobalState.event.clear() except Exception as e: print(f"Error in send_status: {e}") return @socketio.on('monitor_begin') def monitor_begin(): current_time = time.time() elapsed_time = current_time - GlobalState.last_time if elapsed_time < 0.5: return GlobalState.last_time = current_time regionRet, regionPos = game_region() screenshot = pyautogui.screenshot(region=regionPos) compressed_data = compress_image(screenshot) image_data_base64 = base64.b64encode(compressed_data).decode('utf-8') socketio.emit('image_data', image_data_base64) task_arr = [] if not GlobalState.event.is_set(): task_arr.append(GlobalState.last_process) for item in reversed(GlobalState.task_queue): task_arr.append(item.name) latest_tasks = task_arr[:5] # only show the last 5 tasks send_hint(json.dumps(latest_tasks, ensure_ascii=False)) send_todo() send_status('') #print("send img") @socketio.on('end_script') def handle_end_script(): GlobalState.event.set() @socketio.on('end_game') def handle_end_game(): GlobalState.event.set() task_close_game() send_status("结束2") GlobalState.event.clear() @socketio.on('get_title') def handle_get_title(): str = task_getComputerName() dst = str + ' machine' emit('processing_title', dst) @socketio.on('reset_script') def handle_reset_script(): python = sys.executable script = os.path.abspath(sys.argv[0]) # 获取当前脚本的绝对路径 # 构建新的参数列表,移除旧的 --reset 并添加新的 new_args = [arg for arg in sys.argv[1:] if arg != '--reset'] # 排除脚本名和旧的 --reset print(f"当前 Python 解释器: {python}") print(f"当前脚本路径: {script}") print(f"重置参数: {[python, script, *new_args, '']}") terminate_frpc() try: os.execv(python, [python, script, *new_args, '']) except Exception as e: print(f"重置失败: {e}") subprocess.Popen([python, script, *new_args, '']) sys.exit(0) # 终止当前进程 @socketio.on('restart_game') def handle_restart_game(): python = sys.executable script = os.path.abspath(sys.argv[0]) # 获取当前脚本的绝对路径 # 构建新的参数列表,移除旧的 --reset 并添加新的 new_args = [arg for arg in sys.argv[1:] if arg != '--reset'] # 排除脚本名和旧的 --reset print(f"当前 Python 解释器: {python}") print(f"当前脚本路径: {script}") print(f"重启参数: {[python, script, *new_args, '--reset']}") terminate_frpc() try: os.execv(python, [python, script, *new_args, '--reset']) except Exception as e: print(f"重启失败: {e}") subprocess.Popen([python, script, *new_args, '--reset']) sys.exit(0) # 终止当前进程 @app.route('/restart_game', methods=['POST']) def http_restart_game(): print("HTTP 触发 restart_game") socketio.start_background_task(handle_restart_game) return jsonify({"status": "success", "message": "已重启"}) @socketio.on('close_game') def handle_close_game(): task_close_game() send_status("结束2") GlobalState.event.clear() @app.route('/close_game', methods=['POST']) def http_close_game(): print("HTTP 触发 close_game") handle_close_game() socketio.start_background_task(handle_reset_script) return jsonify({"status": "success", "message": "已关闭"}) @socketio.on('read_cfg') def handle_read_cfg(): cfg = read_cfg() emit('processing_cfg', cfg) def restart_game(type=0): GlobalState.isGameBegin = False while True: task_close_game() if True == task_start_game(type): break else: send_status("启动失败") GlobalState.isGameBegin = True send_status("结束") config = read_cfg() print("config", config) auto_task(config) def auto_participate(): GlobalState.task_queue.appendleft(task_returnAllLine()) timeout = 40 * 60 start_time = time.time() # 记录开始时间 while not GlobalState.event.is_set(): if len(GlobalState.task_queue) < 4: GlobalState.task_queue.appendleft(task_useAnnimalSkill(True)) GlobalState.task_queue.appendleft(task_paticipateInTeam(False)) GlobalState.task_queue.appendleft(task_paticipateInTeam()) GlobalState.task_queue.appendleft(task_paticipateInTeam(False)) GlobalState.task_queue.appendleft(task_paticipateInTeam()) myTimeSleep_big() # 每次循环检查已用时间 current_time = time.time() elapsed_time = current_time - start_time if elapsed_time >= timeout: handle_restart_game() break def auto_palace(): timeout = 180 * 60 start_time = time.time() # 记录开始时间 read_cfg() while not GlobalState.event.is_set(): GlobalState.g_times += 1 if len(GlobalState.task_queue) < 4: GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum * 5)) GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum * 3)) GlobalState.task_queue.appendleft(task_fight_enemy()) myTimeSleep_big() current_time = time.time() elapsed_time = current_time - start_time if elapsed_time >= timeout: handle_restart_game() def add_auto_task(isMaxCollect, isJina, isSimple = False, isAddStrengh = False, activity = 'None', isAutoParticipate = True, isDailyConfig = False, train_type = 'None', always = False): collectArr = [int(x) for x in isMaxCollect.split(",")] print("collectArr", collectArr) if len(collectArr) == 1: collectArr = collectArr[0] while not GlobalState.event.is_set(): print(f"----第{GlobalState.g_times}次循环-----") if isSimple == False and is_within_n_minutes(get_todo_time("巨熊行动"), 30, 35): print("in fight bear") if len(GlobalState.task_queue) < 5: if GlobalState.g_firstRunBear: GlobalState.g_firstRunBear = False GlobalState.task_queue.appendleft(task_useAnnimalSkill(True)) GlobalState.task_queue.appendleft(task_returnAllLine()) GlobalState.task_queue.appendleft(task_useAnnimalSkill(True)) GlobalState.task_queue.appendleft(task_returnAllLine()) GlobalState.task_queue.appendleft(task_useAnnimalSkill(True)) GlobalState.task_queue.appendleft(task_returnAllLine()) GlobalState.task_queue.appendleft(task_useAnnimalSkill(True)) GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch)) GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch)) GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch)) GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch)) GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch)) GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch)) GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch)) GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch)) GlobalState.task_queue.appendleft(task_paticipateInTeam(False)) myTimeSleep_big() send_status(f'巨熊行动中') continue elif isSimple == False and is_within_n_minutes(get_todo_time("巨熊行动"), 60, 0): # 设置无尽运行和启动的游戏为0 always = True if GlobalState.g_switch: update_rungame_type(0) send_status(f'巨熊行动:在60min内,切换到无尽模式') print("add special activity") # special activity if activity == 'lianmeng': GlobalState.task_queue.appendleft(task_activity_lianmeng()) elif activity == 'cure': GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum)) elif activity == 'only_cure': GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum)) GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum)) GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum)) return print("add normal activity") GlobalState.task_queue.appendleft(task_checkActivities()) if GlobalState.g_switch == True: GlobalState.task_queue.appendleft(task_checkBenifitStatus()) if isSimple == False: GlobalState.task_queue.appendleft(task_information()) GlobalState.task_queue.appendleft(task_check_Research()) GlobalState.task_queue.appendleft(task_checkStoreRoom()) if not isSimple: if isJina == 'jina': GlobalState.task_queue.appendleft(task_fight_jina(isAddStrengh)) elif isJina == 'yongbing': GlobalState.task_queue.appendleft(task_fight_yongbing(isAddStrengh)) elif isJina == 'monster': GlobalState.task_queue.appendleft(task_fightMonster(isAddStrengh, False, isSimple)) elif isJina == 'big_monster' or isJina == 'bigMonster_max': GlobalState.task_queue.appendleft(task_fightMonster(isAddStrengh, True, isSimple)) elif isJina == 'jina_call': ### 全部聊天记录都是新吉娜 GlobalState.task_queue.appendleft(task_call_jina()) GlobalState.task_queue.appendleft(task_call_jina()) GlobalState.task_queue.appendleft(task_call_jina()) GlobalState.task_queue.appendleft(task_call_jina()) elif isJina == 'jina_onlyFight': GlobalState.task_queue.appendleft(task_fight_jina_only()) GlobalState.task_queue.appendleft(task_collect(collectArr, isSimple, isAddStrengh)) GlobalState.task_queue.appendleft(task_train(train_type)) if isSimple == False: if not isAddStrengh: # 如果不是添加体力,则添加一次采集 GlobalState.task_queue.appendleft(task_collect(collectArr, isSimple, isAddStrengh)) if isJina == 'monster' and isAddStrengh: GlobalState.task_queue.appendleft(task_fightMonster(isAddStrengh, False, isSimple)) else: GlobalState.task_queue.appendleft(task_collect(collectArr, isSimple, isAddStrengh)) else: GlobalState.task_queue.appendleft(task_collect(collectArr, isSimple, isAddStrengh)) print("add rare activity") if GlobalState.g_times % 3 == 0: GlobalState.task_queue.appendleft(task_useAnnimalSkill()) GlobalState.task_queue.appendleft(task_checkDiamond()) if GlobalState.g_times % 5 == 0: if GlobalState.g_switch and get_rungame_type() == 0: GlobalState.task_queue.appendleft(check_buildOrResearch()) GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum)) GlobalState.task_queue.appendleft(task_information()) GlobalState.task_queue.appendleft(task_checkDonata()) GlobalState.task_queue.appendleft(task_checkMaster()) GlobalState.task_queue.appendleft(task_checkAdventure()) GlobalState.task_queue.appendleft(task_train(train_type)) GlobalState.task_queue.appendleft(task_read_mails()) GlobalState.task_queue.appendleft(task_getStrength()) if auto_participate: GlobalState.task_queue.appendleft(task_checkConfilits()) GlobalState.task_queue.appendleft(task_fight_campion()) GlobalState.task_queue.appendleft(task_get_fire_crystal()) GlobalState.task_queue.appendleft(task_checkUnionTreasure()) #GlobalState.task_queue.appendleft(task_checkBenifitStatus()) GlobalState.task_queue.appendleft(task_gotoTree()) GlobalState.task_queue.appendleft(task_checkHelp()) if activity == 'redPackage': GlobalState.task_queue.appendleft(task_get_redPackage()) if isJina == 'bigMonster_max': GlobalState.task_queue.appendleft(task_fightMonster(isAddStrengh, True, isSimple)) print("check restart") GlobalState.g_times += 1 restart_times = 7 if GlobalState.g_switch: restart_times = 4 if GlobalState.g_times % restart_times == 0 and GlobalState.g_times != 0: if GlobalState.g_isRestart: handle_end_game() if GlobalState.g_switch == False: if always: nextTaskTime = random.randint(400, 450) set_nextTaskTime(nextTaskTime) myTimeSleep(nextTaskTime, send_status) else: nextTaskTime = random.randint(1000, 2000) set_nextTaskTime(nextTaskTime) myTimeSleep(nextTaskTime, send_status) else: nextTaskTime = random.randint(20, 50) set_nextTaskTime(nextTaskTime) myTimeSleep(nextTaskTime, send_status) if GlobalState.g_isRestart: handle_restart_game() else: nextTaskTime = random.randint(400, 450) set_nextTaskTime(nextTaskTime) myTimeSleep(nextTaskTime, send_status) GlobalState.task_queue.clear() send_status(f'自动模式结束') GlobalState.event.clear() daily_config = { "login_task": False, "fight_bigMonster_times": 0 } def check_daily_config(config): today = datetime.now().strftime('%Y-%m-%d') # 获取当前日期 print(f"Today: {today}") # 打印当前日期 print(f"Config: {config}") # 打印传入的配置 if "daily" not in config: print("Daily key not found, creating it.") # 调试信息 config["daily"] = {} return False if today not in config["daily"]: print(f"Today's config not found: {today}") # 调试信息 return False else: print(f"Today's config found: {today}") # 调试信息 return True def update_rungame_type(dstType=None): config = read_Dailycfg() runTypeStr = 'runType' if runTypeStr not in config: if dstType is not None: config[runTypeStr] = dstType else: config[runTypeStr] = 1 write_Dailycfg(config) print(f"更新下次启动{config[runTypeStr]}") return 0 else: value = config[runTypeStr] if dstType is not None: config[runTypeStr] = dstType else: config[runTypeStr] = (value + 1) % 2 write_Dailycfg(config) print(f"更新下次启动{config[runTypeStr]}") return value def get_rungame_type(): config = read_Dailycfg() runTypeStr = 'runType' if runTypeStr not in config: return 0 else: if config[runTypeStr] == 0: return 1 else: return 0 # 修改或添加 "login_task" 的值 def set_login_task(config, value): today = datetime.now().strftime('%Y-%m-%d') # 获取当前日期 if today not in config["daily"]: # 如果当天的配置不存在 config["daily"][today] = {} # 创建当天的配置 config["daily"][today]["login_task"] = value # 设置或更新 "login_task" return config # 修改或添加 "fight_bigMonster_times" 的值 def set_fight_big_monster_times(config, value): today = datetime.now().strftime('%Y-%m-%d') # 获取当前日期 if today not in config["daily"]: # 如果当天的配置不存在 config["daily"][today] = {} # 创建当天的配置 config["daily"][today]["fight_bigMonster_times"] = value # 设置或更新 "fight_bigMonster_times" return config def add_today_daily_config(config, daily_config, overwrite=False): today = datetime.now().strftime('%Y-%m-%d') # 获取当前日期 if today not in config["daily"] or overwrite: # 如果不存在或允许覆盖 config["daily"][today] = daily_config # 添加或更新 return config # 清理非当天的每日配置 def clean_old_daily_configs(config): today = datetime.now().strftime('%Y-%m-%d') # 获取当前日期 keys_to_remove = [key for key in config["daily"] if key != today] # 找到非当天的每日配置 for key in keys_to_remove: del config["daily"][key] # 删除非当天的每日配置 return config def write_cfg(config): try: config_manager = MinIOConfigManager() localCfg_name = task_getComputerName() + '_config' config_manager.set_config(localCfg_name, config) except Exception as e: print("写入minIO错误, 尝试写入本地") with open('config.json', 'w') as config_file: json.dump(config, config_file, indent=4) def read_cfg(): try: config_manager = MinIOConfigManager() localCfg_name = task_getComputerName() + '_config' localCfg = config_manager.get_config(localCfg_name) config = json.loads(localCfg) GlobalState.g_cureNum = int(config['cureNumber']) return config except Exception as e: print("读取minIO错误, 尝试读取本地") try: with open('config.json', 'r') as config_file: config = json.load(config_file) GlobalState.g_cureNum = int(config['cureNumber']) return config except FileNotFoundError: print("配置文件不存在,请检查文件路径。") return None except PermissionError: print("没有权限读取配置文件。") return None except json.JSONDecodeError: print("配置文件格式错误,请检查文件内容是否为有效的 JSON。") return None def write_Dailycfg(config): try: config_manager = MinIOConfigManager() localCfg_name = task_getComputerName() + '_daily' config_manager.set_config(localCfg_name, config) except Exception as e: print("写入minIO错误, 尝试写入本地") with open('daily.json', 'w') as config_file: json.dump(config, config_file, indent=4) def read_Dailycfg(): try: config_manager = MinIOConfigManager() localCfg_name = task_getComputerName() + '_daily' localCfg = config_manager.get_config(localCfg_name) config = json.loads(localCfg) return config except Exception as e: print("读取minIO错误, 尝试读取本地") config = { "daily": { "2025-07-11": { "login_task": True, "fight_bigMonster_times": 0 } }, "runType": 0 } return @socketio.on('begin_auto') def handle_auto(data): write_cfg(data) config = read_cfg() print("config", config) auto_task(config) def auto_task(data): if data == None: isMaxCollect = '4,3,2,1' isSimple = False isJina = 'jina' isAddStrengh = False activity = 'none' participateJijie = False auto_daily = False train_type = 'none' always = False cureNumber = 500 lineCheck = False switch = False GlobalState.g_isRestart = True else: isMaxCollect = data['maxCollect'] isSimple = data['simple'] isJina = data['jina'] isAddStrengh = data['add_strength'] activity = data['activity'] participateJijie = data['participate_jijie'] auto_daily = False train_type = data['train'] always = data['always'] cureNumber = int(data['cureNumber']) lineCheck = data['lineCheck'] switch = data['switch'] GlobalState.g_isRestart = data['is_restart'] GlobalState.g_cureNum = cureNumber GlobalState.g_switch = switch set_lineCheck(lineCheck) send_status(f'开始自动模式') executor.submit(add_auto_task, isMaxCollect, isJina, isSimple, isAddStrengh, activity, participateJijie, auto_daily, train_type, always) @socketio.on('begin_auto_participate') def handle_auto_participate(): send_status(f'开始自动集结模式') executor.submit(auto_participate) @socketio.on('begin_testNewFun') def handle_auto_testNewFun(): send_status(f'开始自动测试新功能') task_testFun().run() @socketio.on('auto_palace') def handle_auto_palace(): send_status(f'开始自动王城') executor.submit(auto_palace) def monitor_game_runtime(): last_value = GlobalState.g_times while True: current_value = GlobalState.g_times if current_value != last_value: last_value = current_value GlobalState.last_change_time = time.time() print(f"g_times changed to {current_value}") # 检查是否超过60分钟没有变化 if time.time() - GlobalState.last_change_time > 3600: # 3600秒=60分钟 print("g_times hasn't changed for 60 minutes!") handle_restart_game() time.sleep(60) if __name__ == '__main__': init() startup_frpc() print("FRPC已启动,主程序继续运行...") if '--reset' in sys.argv: time.sleep(2) GlobalState.isReset = True print("需要重启游戏") runTask = threading.Thread(target=thread_runTask)#启动线程往里面添加任务 runTask.daemon = True runTask.start() monitor_thread = threading.Thread(target=monitor_game_runtime, daemon=True) monitor_thread.start() socketio.run(app, host= '0.0.0.0', debug=True, use_reloader=False)#关闭自动重载