# coding=UTF-8
"""
 Copyright (c) 2025 Alexander-Porter & fwilliamhe

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program. If not, see <https://www.gnu.org/licenses/>.
 """


import logging
import sys
import time
from flask import Flask, request, Response, jsonify
from gevent import pywsgi
import gevent
from channelHandler.channelUtils import getShortGameId
from envmgr import genv
from logutil import setup_logger
from gamemgr import Game, GameManager
import socket
import requests
import json
import os
import psutil
import const
import subprocess


app = Flask(__name__)
game_helper = GameManager()
logger=setup_logger()



loginMethod = [
    {
        "name": "手机账号",
        "icon_url": "",
        "text_color": "",
        "hot": True,
        "type": 7,
        "icon_url_large": "",
    },
    {
        "name": "快速游戏",
        "icon_url": "",
        "text_color": "",
        "hot": True,
        "type": 2,
        "icon_url_large": "",
    },
    {
        "login_url": "",
        "name": "网易邮箱",
        "icon_url": "",
        "text_color": "",
        "hot": True,
        "type": 1,
        "icon_url_large": "",
    },
    {
        "login_url": "",
        "name": "扫码登录",
        "icon_url": "",
        "text_color": "",
        "hot": True,
        "type": 17,
        "icon_url_large": "",
    },
]
pcInfo = {
    "extra_unisdk_data": "",
    "from_game_id": "h55",
    "src_app_channel": "netease",
    "src_client_ip": "",
    "src_client_type": 1,
    "src_jf_game_id": "h55",
    "src_pay_channel": "netease",
    "src_sdk_version": "3.15.0",
    "src_udid": "",
}

g_req = requests.session()
g_req.trust_env = False


def requestGetAsCv(request, cv,body_mapping={}):

    query = request.args.copy()
    if cv:
        query["cv"] = cv
    for k,v in body_mapping.items():
        query[k]=v
    url = request.base_url
    if request.host == "localhost":
        url = url.replace("localhost", genv.get("DOMAIN_TARGET"))
    resp = g_req.request(
        method=request.method,
        url=genv.get("URI_REMOTEIP") + request.path,
        params=query,
        headers=request.headers,
        cookies=request.cookies,
        allow_redirects=False,
        verify=False,
    )
    excluded_headers = [
        "content-encoding",
        "content-length",
        "transfer-encoding",
        "connection",
    ]
    headers = [
        (name, value)
        for (name, value) in resp.raw.headers.items()
        if name.lower() not in excluded_headers
    ]
    return Response(resp.text, resp.status_code, headers)


def proxy(request,query={}):
    if query=={}:
        query = request.args.copy()
    new_body = request.get_data(as_text=True)
    # 向目标服务发送代理请求
    resp = requests.request(
        method=request.method,
        url=genv.get("URI_REMOTEIP") + request.path,
        params=query,
        headers=request.headers,
        data=new_body,
        cookies=request.cookies,
        allow_redirects=False,
        verify=False,
    )
    app.logger.info(resp.url)
    # 构造代理响应
    excluded_headers = [
        "content-encoding",
        "content-length",
        "transfer-encoding",
        "connection",
    ]
    headers = [
        (name, value)
        for (name, value) in resp.raw.headers.items()
        if name.lower() not in excluded_headers
    ]

    response = Response(resp.content, resp.status_code, headers)
    return response


def requestPostAsCv(request, cv,body_mapping={}):

    query = request.args.copy()
    if cv:
        query["cv"] = cv
    try:
        new_body = request.get_json()
        new_body["cv"] = cv
        new_body.pop("arch", None)
        for k,v in body_mapping.items():
            new_body[k]=v
    except:
        new_body = dict(x.split("=") for x in request.get_data(as_text=True).split("&"))
        new_body["cv"] = cv
        new_body.pop("arch", None)
        for k,v in body_mapping.items():
            new_body[k]=v
        new_body = "&".join([f"{k}={v}" for k, v in new_body.items()])

    app.logger.info(new_body)
    resp = g_req.request(
        method=request.method,
        url=genv.get("URI_REMOTEIP") + request.path,
        params=query,
        data=new_body,
        headers=request.headers,
        cookies=request.cookies,
        allow_redirects=False,
        verify=False,
    )
    excluded_headers = [
        "content-encoding",
        "content-length",
        "transfer-encoding",
        "connection",
    ]
    headers = [
        (name, value)
        for (name, value) in resp.raw.headers.items()
        if name.lower() not in excluded_headers
    ]
    return Response(resp.text, resp.status_code, headers)


@app.route("/mpay/games/<game_id>/login_methods", methods=["GET"])
def handle_login_methods(game_id):
    try:
        resp: Response = requestGetAsCv(request, "i4.7.0")
        new_login_methods = resp.get_json()
        new_login_methods["entrance"] = [(loginMethod)]
        new_login_methods["select_platform"] = True
        new_login_methods["qrcode_select_platform"] = True
        for i in new_login_methods["config"]:
            new_login_methods["config"][i]["select_platforms"] = [0, 1, 2, 3, 4]
        resp.set_data(json.dumps(new_login_methods))
        return resp
    except:
        return proxy(request)


@app.route("/mpay/api/users/login/mobile/finish", methods=["POST"])
@app.route("/mpay/api/users/login/mobile/get_sms", methods=["POST"])
@app.route("/mpay/api/users/login/mobile/verify_sms", methods=["POST"])
@app.route("/mpay/games/<game_id>/devices/<device_id>/users", methods=["POST"])
def handle_first_login(game_id=None, device_id=None):
    try:
        return requestPostAsCv(request, "i4.7.0")
    except:
        return proxy(request)


@app.route("/mpay/games/<game_id>/devices/<device_id>/users/<user_id>", methods=["GET"])
def handle_login(game_id, device_id, user_id):
    try:
        mapping={
            "opt_fields": "nickname,avatar,realname_status,mobile_bind_status,exit_popup_info,mask_related_mobile,related_login_status,detect_is_new_user",
            "verify_status": "1",
            "login_for": "1", 
            "gv": "251881013",
            "gvn": "2025.0707.1013",
            "sv": "35",
            "app_type": "games",
            "app_mode": "2",
            "app_channel": "netease.wyzymnqsd_cps_dev",
            "_cloud_extra_base64": "e30=",
            "sc": "1"
        }
        resp: Response = requestGetAsCv(request, "i4.7.0",mapping)

        new_devices = resp.get_json()
        new_devices["user"]["pc_ext_info"] = pcInfo
        resp.set_data(json.dumps(new_devices))
        return resp
    except:
        return proxy(request)

@app.route("/mpay/api/qrcode/image", methods=["GET"])
def handle_qrcode_image():
    try:
        resp=proxy(request)
        if genv.get("CLOUD_RES").get_risk_wm()!="":
            from riskWmUtils import wm
            resp.set_data(wm(resp.get_data(),genv.get("CLOUD_RES").get_risk_wm()))
            return resp
        return resp
    except:
        return proxy(request)

@app.route("/mpay/games/pc_config", methods=["GET"])
def handle_pc_config():
    try:
        resp: Response = requestGetAsCv(request, "i4.7.0")
        new_config = resp.get_json()
        new_config["game"]["config"]["cv_review_status"] = 1
        new_config["game"]["config"]["web_token_persist"]=True
        new_config["game"]["config"]["mobile_related_login"]["guide_related_mobile"]=True
        new_config["game"]["config"]["mobile_related_login"]["force_related_login"]=True
        new_config["game"]["config"]["login"]["login_style"]=2
        resp.set_data(json.dumps(new_config))
        return resp
    except:
        return proxy(request)


@app.route("/mpay/api/qrcode/create_login", methods=["GET"])
def handle_create_login():
    try:
        query=request.args.to_dict()
        # 设置二维码登录的渠道类型和其他必要参数
        query["qrcode_channel_type"] = "3"
        query["gv"] = "251881013"
        query["gvn"] = "2025.0707.1013" 
        query["cv"] = "i4.7.0"
        query["sv"] = "35"
        query["app_type"] = "games"
        query["app_mode"] = "2"
        query["app_channel"] = "netease.wyzymnqsd_cps_dev"
        query["_cloud_extra_base64"] = "e30="
        query["sc"] = "1"
        resp: Response = proxy(request,query)
        genv.set("CHANNEL_ACCOUNT_SELECTED", "")
        data={
            "uuid":resp.get_json()["uuid"],
            "game_id":request.args["game_id"]
        }
        genv.set("CACHED_QRCODE_DATA",data)
        genv.set("pending_login_info",None)
        #auto login start
        if genv.get(f"auto-{request.args['game_id']}", "") != "":
                delay=game_helper.get_login_delay(request.args["game_id"])
                logger.info(f"即将自动登录，{delay}秒后开始扫码")
                uuid=genv.get(f"auto-{request.args['game_id']}")
                genv.set("CHANNEL_ACCOUNT_SELECTED",uuid)
                gevent.spawn_later(
                    delay,
                    genv.get("CHANNELS_HELPER").simulate_scan,
                    uuid,
                    data["uuid"],
                    data["game_id"]
                )
        new_config = resp.get_json()
        new_config["qrcode_scanners"][0]["url"] = "https://localhost/_idv-login/index?game_id="+request.args["game_id"]
        return jsonify(new_config)
    except:
        return proxy(request)



@app.route("/_idv-login/manualChannels",methods=["GET"])
def _manual_list():
    try:
        game_id=request.args["game_id"]
        if game_id:
            data=genv.get("CLOUD_RES").get_all_by_game_id(getShortGameId(game_id))
            return jsonify(data)
        else:
            return jsonify(const.manual_login_channels)
    finally:
        return jsonify(const.manual_login_channels)

@app.route("/_idv-login/list", methods=["GET"])
def _list_channels():
    try:
        body=genv.get("CHANNELS_HELPER").list_channels(request.args["game_id"])
    except Exception as e:
        body = {
            "error": str(e)
        }
    return jsonify(body)

@app.route("/_idv-login/switch", methods=["GET"])
def _switch_channel():
    genv.set("CHANNEL_ACCOUNT_SELECTED",request.args["uuid"])
    if genv.get("CACHED_QRCODE_DATA"):
         data=genv.get("CACHED_QRCODE_DATA")
         genv.get("CHANNELS_HELPER").simulate_scan(request.args["uuid"],data["uuid"],data["game_id"])
    #debug only
    else:
        genv.get("CHANNELS_HELPER").simulate_scan(request.args["uuid"],"Kinich","aecfrt3rmaaaaajl-g-g37")
    return {"current":genv.get("CHANNEL_ACCOUNT_SELECTED")}

@app.route("/_idv-login/del", methods=["GET"])
def _del_channel():
    resp={
        "success":genv.get("CHANNELS_HELPER").delete(request.args["uuid"])
    }
    return jsonify(resp)

@app.route("/_idv-login/rename", methods=["GET"])
def _rename_channel():
    resp={
        "success":genv.get("CHANNELS_HELPER").rename(request.args["uuid"],request.args["new_name"])
    }
    return jsonify(resp)

@app.route("/_idv-login/import", methods=["GET"])
def _import_channel():
    resp={
        "success":genv.get("CHANNELS_HELPER").manual_import(request.args["channel"],request.args["game_id"])
    }
    return jsonify(resp)

@app.route("/_idv-login/setDefault", methods=["GET"])
def _set_default_channel():
    try:
        genv.set(f"auto-{request.args['game_id']}",request.args["uuid"],True)
        resp={
            "success":True,
        }
    except:
        logger.exception("设置默认账号失败")
        resp={
            "success":False,
        }
    return jsonify(resp)

@app.route("/_idv-login/clearDefault", methods=["GET"])
def _clear_default_channel():
    try:
        genv.set(f"auto-{request.args['game_id']}","",True)
        resp={
            "success":True,
        }
    except:
        resp={
            "success":False,
        }
    return jsonify(resp)

@app.route("/_idv-login/get-auto-close-state", methods=["GET"])
def _get_auto_close_state():
    """查询指定游戏的自动关闭状态"""
    try:
        game_id = request.args["game_id"]
        current_state = game_helper.get_auto_close_setting(game_id)
        return jsonify({
            "success": True,
            "state": current_state,
            "game_id": game_id
        })
    except Exception as e:
        logger.exception(f"查询游戏 {game_id} 的自动关闭状态失败")
        return jsonify({
            "success": False,
            "error": str(e)
        })

@app.route("/_idv-login/switch-auto-close-state", methods=["GET"])
def _switch_auto_close_state():
    """切换指定游戏的自动关闭状态"""
    try:
        game_id = request.args["game_id"]
        current_state = game_helper.get_auto_close_setting(game_id)
        new_state = not current_state
        game_helper.set_auto_close_setting(game_id, new_state)
        return jsonify({
            "success": True,
            "state": new_state,
            "game_id": game_id
        })
    except Exception as e:
        logger.exception(f"切换游戏 {game_id} 的自动关闭状态失败")
        return jsonify({
            "success": False,
            "error": str(e)
        })

@app.route("/_idv-login/get-game-auto-start", methods=["GET"])
def _get_game_auto_start():
    """查询指定游戏的自动启动状态和路径"""
    try:
        game_id = request.args["game_id"]
        auto_start_info = game_helper.get_game_auto_start(game_id)
        return jsonify({
            "success": True,
            "enabled": auto_start_info["enabled"],
            "path": auto_start_info["path"],
            "game_id": game_id
        })
    except Exception as e:
        logger.exception(f"查询游戏 {game_id} 的自动启动状态失败")
        return jsonify({
            "success": False,
            "error": str(e)
        })

@app.route("/_idv-login/set-game-auto-start", methods=["GET"])
def _set_game_auto_start():
    """设置指定游戏的自动启动状态和路径"""
    try:
        game_id = request.args["game_id"]
        enabled = request.args.get("enabled") == 'true'

        game_path = ""
 
        if enabled:
            # 使用Qt代替tkinter
            from PyQt5.QtWidgets import QApplication, QFileDialog
            import sys
            
            # 创建一个临时的QApplication实例
            app = QApplication.instance()
            if app is None:
                app = QApplication(sys.argv)
            
            # 导入Qt命名空间    
            from PyQt5.QtCore import Qt
                
            # 显示文件选择对话框
            desktop_path = os.path.join(os.path.expanduser('~'), 'Desktop')
            file_dialog = QFileDialog()
            file_dialog.setFileMode(QFileDialog.ExistingFile)
            file_dialog.setNameFilter("可执行文件 (*.exe);;快捷方式 (*.lnk);;所有文件 (*.*)")
            file_dialog.setWindowTitle("选择游戏启动程序或快捷方式")
            file_dialog.setDirectory(desktop_path)
            file_dialog.setWindowFlags(file_dialog.windowFlags() | Qt.WindowStaysOnTopHint)
            file_dialog.setWindowModality(Qt.ApplicationModal)
            file_dialog.setWindowState(Qt.WindowActive)
            file_dialog.setWindowFlag(Qt.WindowStaysOnTopHint)
            if file_dialog.exec_():
                selected_files = file_dialog.selectedFiles()
                if selected_files:
                    game_path = selected_files[0]
            
            # 如果用户没有选择任何文件，则返回错误
            if not game_path:
                return jsonify({
                    "success": False,
                    "error": "用户取消选择游戏路径"
                })
            #获取纯文件名，不含路径和后缀
            name=os.path.splitext(os.path.basename(game_path))[0]
            
            # 如果是快捷方式，解析目标路径
            if game_path.lower().endswith(".lnk"):
                import win32com.client
                shell = win32com.client.Dispatch("WScript.Shell")
                shortcut = shell.CreateShortcut(game_path)
                game_path = shortcut.Targetpath
        else:
            if game_helper.get_game(game_id):
                name=game_helper.get_game(game_id).name
            else:
                name=""
        game_helper.set_game_auto_start(game_id, enabled)
        game_helper.set_game_path(game_id, game_path)
        game_helper.rename_game(game_id,name)
        return jsonify({
            "success": True,
            "enabled": enabled,
            "path": game_path,
            "game_id": game_id
        })
    except Exception as e:
        logger.exception(f"设置游戏 {game_id} 的自动启动状态失败")
        return jsonify({
            "success": False,
            "error": str(e)
        })

@app.route("/_idv-login/start-game", methods=["GET"])
def _start_game():
    """启动指定游戏"""
    try:
        game_id = request.args["game_id"]

        game_path = game_helper.get_game_auto_start(game_id)["path"]

        if not game_path:
            return jsonify({
                "success": False,
                "error": "游戏路径未设置"
            })


        game: Game = game_helper.get_game(game_id)
        if game:
            game.start()
            game.last_used_time = int(time.time())
            game_helper._save_games()


        return jsonify({
            "success": True,
            "game_id": game_id
        })
    except Exception as e:
        logger.exception(f"启动游戏 {game_id} 失败")
        return jsonify({
            "success": False,
            "error": str(e)
        })

@app.route("/_idv-login/list-games", methods=["GET"])
def _list_games():
    """列出所有游戏"""
    try:
        games = game_helper.list_games()
        return jsonify({
            "success": True,
            "games": games
        })
    except Exception as e:
        logger.exception(f"列出游戏失败")
        return jsonify({
            "success": False,
            "error": str(e)
        })

@app.route("/_idv-login/defaultChannel", methods=["GET"])
def get_default():
    uuid=genv.get(f"auto-{request.args['game_id']}","")
    if uuid=="":
        return jsonify({"uuid":""})
    elif genv.get("CHANNELS_HELPER").query_channel(uuid)==None:
        genv.set(f"auto-{request.args['game_id']}","",True)
        return jsonify({"uuid":""})
    else:
        return jsonify({"uuid":uuid})

@app.route("/_idv-login/get-login-delay", methods=["GET"])
def get_login_delay():
    return jsonify({
        "delay": game_helper.get_login_delay(request.args["game_id"])
    })

@app.route("/_idv-login/set-login-delay", methods=["GET"])
def set_login_delay():
    try:
        game_helper.set_login_delay(request.args["game_id"], int(request.args["delay"]))
        return jsonify({
            "success": True
        })
    except Exception as e:
        logger.exception(f"设置游戏 {request.args['game_id']} 的登录延迟失败")
        return jsonify({
            "success": False,
            "error": str(e)
        })

@app.route("/_idv-login/index",methods=['GET'])
def _handle_switch_page():
    try:
        cloudRes = genv.get("CLOUD_RES")
        if cloudRes.get_login_page() == "":
            return Response(const.html)
        #logger.info(f"正在加载登录页面: {cloudRes.get_login_page()}")
        return Response(cloudRes.get_login_page())
    except Exception as e:
        return Response(const.html)

@app.route("/mpay/api/qrcode/query", methods=["GET"])
def handle_qrcode_query():
    if genv.get("CHANNEL_ACCOUNT_SELECTED"):
        return proxy(request)
    else:
        resp: Response = proxy(request)
        qrCodeStatus = resp.get_json()["qrcode"]["status"]
        if qrCodeStatus == 2 and genv.get("CHANNEL_ACCOUNT_SELECTED") == "":
            genv.set("pending_login_info", resp.get_json()["login_info"])
        return resp

@app.route("/mpay/api/users/login/qrcode/exchange_token", methods=['POST'])
def handle_token_exchange():
    if genv.get("CHANNEL_ACCOUNT_SELECTED"):
        logger.info(f"尝试登录{genv.get('CHANNEL_ACCOUNT_SELECTED')}")
        resp=  proxy(request)
        try:
            # 尝试读取 form 数据
            form_data = request.form.to_dict()
            logger.debug(f"数据上传内容: {form_data}")
        except Exception as e:
            logger.error(f"解析上传数据失败: {e}")
            return resp
        game_id = form_data.get("game_id", "")
        if resp.status_code==200 and game_helper.get_auto_close_setting(game_id):
            logger.info("检测到登录已完成请求，即将自动关闭程序...")
            # 使用 gevent 延迟退出，确保响应能够正常返回
            gevent.spawn_later(3, sys.exit, 0)
        return resp
    else:
        logger.info(f"捕获到渠道服登录Token.")
        resp: Response = proxy(request)
        if resp.status_code == 200:
            if genv.get("pending_login_info"):
                genv.get("CHANNELS_HELPER").import_from_scan(
                    genv.get("pending_login_info"), resp.get_json()
                )
        return resp

@app.route("/mpay/api/qrcode/<path>", methods=["POST"])
@app.route("/mpay/api/reverify/<path>")
@app.route("/mpay/api/qrcode/<path>", methods=["GET"])
def handle_qrcode(path):
    return proxy(request)

@app.route("/mpay/api/data/upload", methods=["POST"])
def handle_data_upload():
    """处理数据上传请求"""
    # 先正常转发请求
    resp = proxy(request)
    try:
        # 尝试读取 form 数据
        form_data = request.form.to_dict()
        logger.debug(f"数据上传内容: {form_data}")
    except Exception as e:
        logger.error(f"解析上传数据失败: {e}")
        return resp
    # 请求完成后检查是否需要自动关闭
    game_id = form_data.get("game_id", "")
    if game_helper.get_auto_close_setting(game_id):
        logger.info("检测到登录已完成请求，即将自动关闭程序...")
        # 使用 gevent 延迟退出，确保响应能够正常返回
        gevent.spawn_later(3, sys.exit, 0)
    
    return resp

@app.route("/<path:path>", methods=["GET", "POST"])
def globalProxy(path):
    if request.method == "GET":
        return requestGetAsCv(request, "i4.7.0")
    else:
        return requestPostAsCv(request, "i4.7.0")

@app.after_request
def after_request_func(response:Response):
    #只log出现错误的请求
    if response.status_code!=200 and response.status_code!=302 and response.status_code!=301 and response.status_code!=304:
        if response.status_code==404:
            if ".ico" in request.url:
                return response
        logger.error(f"请求 {request.url} {request.headers} {request.get_data().decode()}")
        logger.error(f"发送 {response.status} {response.headers} {response.get_data().decode()}")
    else:
        logger.debug(f"请求 {request.url} {response.status}")
    return response

class macProxyMgr:
    def __init__(self) -> None:
        genv.set("CHANNEL_ACCOUNT_SELECTED", "")
        genv.set("CACHED_QRCODE_DATA",{})
        genv.set("pending_login_info",None)
        

    def check_port(self):
        def is_port_in_use(port, host="127.0.0.1"):
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                try:
                    s.bind((host, port))
                    return False  # 端口未被占用
                except socket.error:
                    return True  # 端口被占用
        if is_port_in_use(443):
            with os.popen('netstat -ano | findstr ":443"') as netstat_output:
                netstat_output = netstat_output.read().split("\n")
            for cur in netstat_output:
                info = [i for i in cur.split(" ") if i != ""]
                if len(info) > 4:
                    if info[1].find(":443") != -1:
                        t_pid = info[4]
                        try:
                            readable_exe_name = psutil.Process(int(t_pid)).exe()
                        except psutil.AccessDenied:
                            readable_exe_name = "权限不足"
                            logger.warning(
                                f"读取进程{t_pid}的可执行文件名失败！权限不足。"
                            )
                            return
                        logger.warning(
                            f"警告 : {readable_exe_name} (pid={t_pid}) 已经占用了443端口，是否强行终止该程序？ 按回车继续。"
                        )
                        input()
                        if t_pid == "4":
                            subprocess.check_call(
                                ["net", "stop", "http", "/y"], shell=True
                            )
                        else:
                            subprocess.check_call(
                                ["taskkill", "/f", "/pid", t_pid], shell=True
                            )
                        gevent.sleep(3)
                        break

    def run(self):
        from dnsmgr import DNSResolver

        resolver = DNSResolver()
        target = resolver.gethostbyname(genv.get("DOMAIN_TARGET"))
        logger.info(target)
        
        # result check
        try:
            if (
                target == None
                or g_req.get(f"https://{target}", verify=False).status_code != 200
            ):
                logger.warning(
                    "警告 : DNS解析失败，将使用硬编码的IP地址！（如果你是海外/加速器/VPN用户，出现这条消息是正常的，您不必太在意）"
                )
                target = "42.186.193.21"
        except:
            logger.warning(
                "警告 : DNS解析失败，将使用硬编码的IP地址！（如果你是海外/加速器/VPN用户，出现这条消息是正常的，您不必太在意）"
            )
            target = "42.186.193.21"

        genv.set("URI_REMOTEIP", f"https://{target}")
        self.check_port()
        #创建一个空日志
        import logging
        web_logger=logging.getLogger("web")
        web_logger.setLevel(logging.WARN)
        server = pywsgi.WSGIServer(
                listener=("127.0.0.1", 443),
                certfile=genv.get("FP_WEBCERT"),
                keyfile=genv.get("FP_WEBKEY"),
                application=app,
                log=web_logger,
            )
        if socket.gethostbyname(genv.get("DOMAIN_TARGET")) == "127.0.0.1" or genv.get("USING_BACKUP_VER", False):
            logger.info("拦截成功! 您现在可以打开游戏了")
            logger.warning("如果您在之前已经打开了游戏，请关闭游戏后重新打开，否则工具不会生效！")
            logger.info("登入账号且已经··进入游戏··后，您可以关闭本工具。")
            if game_helper.list_auto_start_games():
                should_start_text="\n".join([i.name for i in game_helper.list_auto_start_games()])
                logger.info(f"检测到有游戏设置了自动启动，游戏列表{should_start_text}")
                for i in game_helper.list_auto_start_games():
                    i.start()
            server.serve_forever()
            return True
        else:
            logger.error("检测拦截目标域名失败！请将程序加入杀毒软件白名单后重试。")
            return False