diff --git a/app/core/config.py b/app/core/config.py index 2f846fd6..aa2233e3 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -1,4 +1,6 @@ import secrets +from urllib.parse import urlparse + import sys import threading from pathlib import Path @@ -226,6 +228,46 @@ class Settings(BaseSettings): } return None + @property + def PROXY_URLPARSE(self): + """ + 解析地址组成 + """ + if self.PROXY_HOST: + parsed_url = urlparse(self.PROXY_HOST) + protocol = parsed_url.scheme or "" # 协议 + username = parsed_url.username or "" # 用户名 + password = parsed_url.password or "" # 密码 + host = parsed_url.hostname or "" # 主机 + port = parsed_url.port or "" # 端口 + path = parsed_url.path or "" # 路径 + netloc = parsed_url.netloc or "" # 用户名:密码@主机:端口 + query = parsed_url.query or "" # 查询参数: ?key=value + params = parsed_url.params or "" # 使用;分割的参数 + fragment = parsed_url.fragment or "" # 片段: #fragment + + if not port: + if protocol == "https": + port = 443 + elif protocol == "http": + port = 80 + elif protocol in {"socks5", "socks5h", "socks4", "socks4a"}: + port = 1080 + + return { + "protocol": protocol, + "username": username, + "password": password, + "host": host, + "port": port, + "path": path, + "netloc": netloc, + "query": query, + "params": params, + "fragment": fragment + } + return None + @property def PROXY_SERVER(self): if self.PROXY_HOST: @@ -244,6 +286,28 @@ class Settings(BaseSettings): } return {} + @property + def PIP_OPTIONS(self): + """ + pip调用附加参数 + """ + protocol = host = port = "" + parsed_url = self.PROXY_URLPARSE + if parsed_url: + protocol = parsed_url.get("scheme", "").lower() + host = parsed_url.get("host", "").lower() + port = parsed_url.get("port", "") + # 优先级:镜像站 > 全局 > 不代理 + if settings.PIP_PROXY: + PIP_OPTIONS = f" -i {settings.PIP_PROXY} " + # 全局代理地址 + elif protocol in {"http", "https", "socks4", "socks4a", "socks5", "socks5h"} and host and port: + PIP_OPTIONS = f" --proxy={settings.PROXY_HOST} " + # 不使用代理 + else: + PIP_OPTIONS = "" + return PIP_OPTIONS + @property def VAPID(self): return { diff --git a/app/helper/plugin.py b/app/helper/plugin.py index 0e2700de..523ac1fe 100644 --- a/app/helper/plugin.py +++ b/app/helper/plugin.py @@ -222,8 +222,7 @@ class PluginHelper(metaclass=Singleton): # 插件目录下如有requirements.txt则安装依赖 requirements_file = plugin_dir / "requirements.txt" if requirements_file.exists(): - PIP_PROXY = f" -i {settings.PIP_PROXY} " if settings.PIP_PROXY else "" - SystemUtils.execute(f"pip install -r {requirements_file} {PIP_PROXY} > /dev/null 2>&1") + SystemUtils.execute(f"pip install -r {requirements_file} {settings.PIP_OPTIONS} > /dev/null 2>&1") # 安装成功后统计 self.install_reg(pid) diff --git a/update b/update index b0bd0af7..f0375e21 100644 --- a/update +++ b/update @@ -116,28 +116,56 @@ function install_backend_and_download_resources() { fi } +# 使用python进行URL解析,$1为PROXY_HOST +function parse_url() { + local result + result=$(python3 /app/parse_url.py ${1}) + # 解析结果并提取各项 + PROTOCOL=$(echo "$result" | grep "^SCHEME:" | awk '{print $2}') + HOST=$(echo "$result" | grep "^HOST:" | awk '{print $2}') + PORT=$(echo "$result" | grep "^PORT:" | awk '{print $2}') +} + if [[ "${MOVIEPILOT_AUTO_UPDATE}" = "true" ]] || [[ "${MOVIEPILOT_AUTO_UPDATE}" = "release" ]] || [[ "${MOVIEPILOT_AUTO_UPDATE}" = "dev" ]]; then - if [[ -n "${PIP_PROXY}" ]] || [[ -n "${GITHUB_PROXY}" ]]; then - CURL_OPTIONS="-sL" - PIP_OPTIONS=${PIP_PROXY:+-i ${PIP_PROXY}} - GITHUB_PROXY=${GITHUB_PROXY:-""} - # 判断不同的代理组合 - if [ -z "${PIP_OPTIONS}" ] && [ -n "${GITHUB_PROXY}" ]; then - INFO "不使用代理更新环境依赖,使用Github镜像代理更新程序" - elif [ -n "${PIP_OPTIONS}" ] && [ -z "${GITHUB_PROXY}" ]; then - INFO "使用Pip镜像代理更新环境依赖,不使用代理更新程序" + # 解析代理地址,判断代理合法性 + if [[ -n "${PROXY_HOST}" ]]; then + parse_url "${PROXY_HOST}" + INFO "检测到代理地址,开始解析..." + if [[ "${PROTOCOL}" =~ ^(http|https|socks4|socks4a|socks5|socks5h)$ ]] && [[ -n "${HOST}" && -n "${PORT}" ]]; then + PROXY_HOST_MODE="true" else - INFO "使用Pip镜像代理更新环境依赖,使用Github镜像代理更新程序" + PROXY_HOST_MODE="false" + WARN "【PROXY_HOST】代理地址不符合要求,无法使用全局代理环境,开始使用其他更新方式" fi - elif [ -n "${PROXY_HOST}" ]; then - CURL_OPTIONS="-sL -x ${PROXY_HOST}" + fi + # 初始化变量 + PIP_PROXY=${PIP_PROXY:-""} + GITHUB_PROXY=${GITHUB_PROXY:-""} + PIP_OPTIONS="" + CURL_OPTIONS="-sL" + # 优先级:镜像站 > 全局 > 不代理 + # pip + if [[ -n "${PIP_PROXY}" ]]; then + PIP_OPTIONS="-i ${PIP_PROXY}" + PIP_LOG="使用Pip镜像代理更新环境依赖" + elif [[ -n "${PROXY_HOST}" && "${PROXY_HOST_MODE}" = "true" ]]; then PIP_OPTIONS="--proxy=${PROXY_HOST}" - GITHUB_PROXY="" - INFO "使用全局代理更新程序与环境依赖" + PIP_LOG="使用全局代理更新环境依赖" + else + PIP_OPTIONS="" + PIP_LOG="不使用代理更新环境依赖" + fi + # GitHub + if [[ -n "${GITHUB_PROXY}" ]]; then + GITHUB_LOG="使用Github镜像代理更新程序" + elif [[ -n "${PROXY_HOST}" && "${PROXY_HOST_MODE}" = "true" ]]; then + CURL_OPTIONS="-sL -x ${PROXY_HOST}" + GITHUB_LOG="使用全局代理更新程序" else CURL_OPTIONS="-sL" - INFO "不使用任何代理更新程序与环境依赖" + GITHUB_LOG="不使用代理更新程序" fi + INFO "${PIP_LOG},${GITHUB_LOG}" if [ -n "${GITHUB_TOKEN}" ]; then CURL_HEADERS="--oauth2-bearer ${GITHUB_TOKEN}" else diff --git a/urlparse.py b/urlparse.py new file mode 100644 index 00000000..2bf277da --- /dev/null +++ b/urlparse.py @@ -0,0 +1,42 @@ +import sys +from urllib.parse import urlparse + + +def parse_url(url): + parsed_url = urlparse(url) + + # 提取各个部分 + protocol = parsed_url.scheme or "" + hostname = parsed_url.hostname or "" + port = parsed_url.port or "" + + if hostname: + hostname = hostname.lower() + + if not port: + if protocol == "https": + port = 443 + elif protocol == "http": + port = 80 + elif protocol in {"socks5", "socks5h", "socks4", "socks4a"}: + port = 1080 + + if protocol: + protocol = protocol.lower() + + # 打印提取的部分 + print(f"SCHEME:{protocol}") + print(f"HOST:{hostname}") + print(f"PORT:{port}") + + +if __name__ == "__main__": + # 参数不全,直接返回空解析结果 + if len(sys.argv) != 2: + print(f"SCHEME:''") + print(f"HOST:''") + print(f"PORT:''") + # 参数全,解析URL + else: + PROXY_HOST = sys.argv[1] + parse_url(url=PROXY_HOST)