mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-02-03 02:25:32 +08:00
320 lines
10 KiB
Bash
320 lines
10 KiB
Bash
#!/bin/bash
|
||
# shellcheck shell=bash
|
||
# shellcheck disable=SC2086
|
||
# shellcheck disable=SC2144
|
||
|
||
Green="\033[32m"
|
||
Red="\033[31m"
|
||
Yellow='\033[33m'
|
||
Font="\033[0m"
|
||
INFO="[${Green}INFO${Font}]"
|
||
ERROR="[${Red}ERROR${Font}]"
|
||
WARN="[${Yellow}WARN${Font}]"
|
||
function INFO() {
|
||
echo -e "${INFO} ${1}"
|
||
}
|
||
function ERROR() {
|
||
echo -e "${ERROR} ${1}"
|
||
}
|
||
function WARN() {
|
||
echo -e "${WARN} ${1}"
|
||
}
|
||
|
||
# 下载及解压
|
||
function download_and_unzip() {
|
||
local retries=0
|
||
local max_retries=3
|
||
local url="$1"
|
||
local target_dir="$2"
|
||
INFO "正在下载 ${url}..."
|
||
while [ $retries -lt $max_retries ]; do
|
||
if curl ${CURL_OPTIONS} "${url}" ${CURL_HEADERS} | busybox unzip -d /tmp - > /dev/null; then
|
||
if [ -e /tmp/MoviePilot-* ]; then
|
||
mv /tmp/MoviePilot-* /tmp/"${target_dir}"
|
||
fi
|
||
break
|
||
else
|
||
WARN "下载 ${url} 失败,正在进行第 $((retries + 1)) 次重试..."
|
||
retries=$((retries + 1))
|
||
fi
|
||
done
|
||
if [ $retries -eq $max_retries ]; then
|
||
ERROR "下载 ${url} 失败,已达到最大重试次数!"
|
||
return 1
|
||
else
|
||
return 0
|
||
fi
|
||
}
|
||
|
||
# 下载程序资源,$1: 后端版本路径
|
||
function install_backend_and_download_resources() {
|
||
# 清理临时目录,上次安装失败可能有残留
|
||
rm -rf /tmp/*
|
||
if ! download_and_unzip "${GITHUB_PROXY}https://github.com/jxxghp/MoviePilot/archive/refs/${1}" "App"; then
|
||
WARN "后端程序下载失败,继续使用旧的程序来启动..."
|
||
return 1
|
||
fi
|
||
INFO "后端程序下载成功"
|
||
INFO "依赖安装中..."
|
||
if ! pip install ${PIP_OPTIONS} --upgrade --root-user-action=ignore pip > /dev/null; then
|
||
ERROR "pip 更新失败,请重新拉取镜像"
|
||
return 1
|
||
fi
|
||
if ! pip install ${PIP_OPTIONS} --root-user-action=ignore -r /tmp/App/requirements.txt > /dev/null; then
|
||
ERROR "安装依赖失败,请重新拉取镜像"
|
||
return 1
|
||
fi
|
||
INFO "安装依赖成功"
|
||
# 从后端文件中读取前端版本号
|
||
frontend_version=$(grep -oP "(?<=FRONTEND_VERSION\s*=\s*')[^']+" /tm/App/version.py)
|
||
if [[ "${frontend_version}" != *v* ]]; then
|
||
WARN "前端最新版本号获取失败,继续启动..."
|
||
return 1
|
||
fi
|
||
if ! download_and_unzip "${GITHUB_PROXY}https://github.com/jxxghp/MoviePilot-Frontend/releases/download/${frontend_version}/dist.zip" "dist"; then
|
||
WARN "前端程序下载失败,继续使用旧的程序来启动..."
|
||
return 1
|
||
fi
|
||
INFO "前端程序下载成功"
|
||
# 提前备份插件目录
|
||
INFO "备份插件目录中..."
|
||
rm -rf /plugins
|
||
mkdir -p /plugins
|
||
cp -a /app/app/plugins/* /plugins/
|
||
# 不备份__init__.py
|
||
rm -f /plugins/__init__.py
|
||
# 提前备份旧 resources 资源
|
||
INFO "备份 resources 资源中..."
|
||
rm -rf /resources_bakcup
|
||
mkdir /resources_bakcup
|
||
cp -a /app/app/helper/* /resources_bakcup
|
||
# 清空目录
|
||
rm -rf /app
|
||
mkdir -p /app
|
||
# 后端程序
|
||
cp -a /tmp/App/* /app/
|
||
# 前端程序
|
||
rm -rf /public
|
||
mkdir -p /public
|
||
cp -a /tmp/dist/* /public/
|
||
# 清理临时目录
|
||
rm -rf /tmp/*
|
||
INFO "程序部分更新成功,前端版本:${frontend_version},后端版本:${1}"
|
||
INFO "开始更新插件..."
|
||
if ! download_and_unzip "${GITHUB_PROXY}https://github.com/jxxghp/MoviePilot-Plugins/archive/refs/heads/main.zip" "Plugins"; then
|
||
cp -a /plugins/* /app/app/plugins/
|
||
rm -rf /plugins
|
||
WARN "插件下载失败,继续使用旧的插件来启动..."
|
||
return 1
|
||
fi
|
||
INFO "插件下载成功"
|
||
# 恢复插件目录
|
||
cp -a /plugins/* /app/app/plugins/
|
||
# 插件仓库
|
||
rsync -av --remove-source-files /tmp/Plugins/plugins/* /app/app/plugins/ > /dev/null
|
||
# 提前安装插件依赖
|
||
find /app/app/plugins -name requirements.txt -exec pip install --root-user-action=ignore ${PIP_OPTIONS} -r {} \; > /dev/null
|
||
# 清理临时目录
|
||
rm -rf /tmp/*
|
||
INFO "插件更新成功"
|
||
INFO "开始更新资源包..."
|
||
if ! download_and_unzip "${GITHUB_PROXY}https://github.com/jxxghp/MoviePilot-Resources/archive/refs/heads/main.zip" "Resources"; then
|
||
cp -a /resources_bakcup/* /app/app/helper/
|
||
rm -rf /resources_bakcup
|
||
WARN "资源包下载失败,继续使用旧的资源包来启动..."
|
||
return 1
|
||
fi
|
||
INFO "资源包下载成功"
|
||
# 资源包
|
||
cp -a /tmp/Resources/resources/* /app/app/helper/
|
||
# 清理临时目录
|
||
rm -rf /tmp/*
|
||
INFO "资源包更新成功"
|
||
return 0
|
||
}
|
||
|
||
function test_connectivity_pip() {
|
||
pip uninstall -y pip-hello-world > /dev/null 2>&1
|
||
case "$1" in
|
||
0)
|
||
if [[ -n "${PIP_PROXY}" ]]; then
|
||
if pip install -i ${PIP_PROXY} pip-hello-world > /dev/null 2>&1; then
|
||
PIP_OPTIONS="-i ${PIP_PROXY}"
|
||
PIP_LOG="镜像代理模式"
|
||
return 0
|
||
fi
|
||
fi
|
||
return 1
|
||
;;
|
||
1)
|
||
if [[ -n "${PROXY_HOST}" ]]; then
|
||
if pip install --proxy=${PROXY_HOST} pip-hello-world > /dev/null 2>&1; then
|
||
PIP_OPTIONS="--proxy=${PROXY_HOST}"
|
||
PIP_LOG="全局代理模式"
|
||
return 0
|
||
fi
|
||
fi
|
||
return 1
|
||
;;
|
||
2)
|
||
PIP_OPTIONS=""
|
||
PIP_LOG="不使用代理"
|
||
return 0
|
||
;;
|
||
esac
|
||
}
|
||
|
||
function test_connectivity_github() {
|
||
case "$1" in
|
||
0)
|
||
if [[ -n "${GITHUB_PROXY}" ]]; then
|
||
if curl -sL "${GITHUB_PROXY}https://raw.githubusercontent.com/jxxghp/MoviePilot/main/README.md" > /dev/null 2>&1; then
|
||
GITHUB_LOG="镜像代理模式"
|
||
return 0
|
||
fi
|
||
fi
|
||
return 1
|
||
;;
|
||
1)
|
||
if [[ -n "${PROXY_HOST}" ]]; then
|
||
if curl -sL -x ${PROXY_HOST} https://raw.githubusercontent.com/jxxghp/MoviePilot/main/README.md > /dev/null 2>&1; then
|
||
CURL_OPTIONS="-sL -x ${PROXY_HOST}"
|
||
GITHUB_LOG="全局代理模式"
|
||
return 0
|
||
fi
|
||
fi
|
||
return 1
|
||
;;
|
||
2)
|
||
CURL_OPTIONS="-sL"
|
||
GITHUB_LOG="不使用代理"
|
||
return 0
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# 版本号比较
|
||
function compare_versions() {
|
||
local v1="$1"
|
||
local v2="$2"
|
||
# 去掉开头的 v 或 V
|
||
v1="${v1#[vV]}"
|
||
v2="${v2#[vV]}"
|
||
local current_ver_parts=()
|
||
local release_ver_parts=()
|
||
IFS='.-' read -ra current_ver_parts <<< "$v1"
|
||
IFS='.-' read -ra release_ver_parts <<< "$v2"
|
||
local i
|
||
local current_ver
|
||
local release_ver
|
||
|
||
for ((i = 0; i < ${#current_ver_parts[@]} || i < ${#release_ver_parts[@]}; i++)); do
|
||
# 版本号不足位补 0
|
||
local current_ver_part="${current_ver_parts[i]:-0}"
|
||
local release_ver_part="${release_ver_parts[i]:-0}"
|
||
current_ver=$(get_priority "$current_ver_part")
|
||
release_ver=$(get_priority "$release_ver_part")
|
||
|
||
# 任意一个为-5,不在合法版本号内,无法比较
|
||
if (( current_ver == -5 || release_ver == -5 )); then
|
||
ERROR "存在不合法版本号,无法判断,跳过更新步骤..."
|
||
return 1
|
||
else
|
||
if (( current_ver > release_ver )); then
|
||
WARN "当前版本高于远程版本,跳过更新步骤..."
|
||
return 1
|
||
elif (( current_ver < release_ver )); then
|
||
INFO "发现新版本,开始自动升级..."
|
||
install_backend_and_download_resources "tags/${release_ver}.zip"
|
||
return 0
|
||
else
|
||
WARN "当前版本已是最新版本,跳过更新步骤..."
|
||
return 1
|
||
fi
|
||
fi
|
||
done
|
||
}
|
||
|
||
# 优先级转换
|
||
function get_priority() {
|
||
local version="$1"
|
||
if [[ $version =~ ^[0-9]+$ ]]; then
|
||
echo $version
|
||
else
|
||
case $version in
|
||
"stable")
|
||
echo -1
|
||
;;
|
||
"rc")
|
||
echo -2
|
||
;;
|
||
"beta")
|
||
echo -3
|
||
;;
|
||
"alpha")
|
||
echo -4
|
||
;;
|
||
# 非数字的不合法版本号
|
||
*)
|
||
echo -5
|
||
;;
|
||
esac
|
||
fi
|
||
}
|
||
|
||
if [[ "${MOVIEPILOT_AUTO_UPDATE}" = "true" ]] || [[ "${MOVIEPILOT_AUTO_UPDATE}" = "release" ]] || [[ "${MOVIEPILOT_AUTO_UPDATE}" = "dev" ]]; then
|
||
# 优先级:镜像站 > 全局 > 不代理
|
||
# pip
|
||
retries=0
|
||
while true; do
|
||
if test_connectivity_pip ${retries}; then
|
||
break
|
||
else
|
||
retries=$((retries + 1))
|
||
fi
|
||
done
|
||
# Github
|
||
retries=0
|
||
while true; do
|
||
if test_connectivity_github ${retries}; then
|
||
break
|
||
else
|
||
retries=$((retries + 1))
|
||
fi
|
||
done
|
||
INFO "PIP:${PIP_LOG},Github:${GITHUB_LOG}"
|
||
if [ -n "${GITHUB_TOKEN}" ]; then
|
||
CURL_HEADERS="--oauth2-bearer ${GITHUB_TOKEN}"
|
||
else
|
||
CURL_HEADERS=""
|
||
fi
|
||
if [ "${MOVIEPILOT_AUTO_UPDATE}" = "dev" ]; then
|
||
INFO "Dev 更新模式"
|
||
install_backend_and_download_resources "heads/v2.zip"
|
||
else
|
||
INFO "Release 更新模式"
|
||
old_version=$(grep -m -1 "^\s*APP_VERSION\s*=\s*" /app/version.py | tr -d '\r\n' | awk -F'#' '{print $1}' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
|
||
if [[ "${old_version}" == *APP_VERSION* ]]; then
|
||
current_version=$(echo "${old_version}" | sed -rn "s/APP_VERSION\s*=\s*['\"](.*)['\"]/\1/gp")
|
||
INFO "当前版本号:${current_version}"
|
||
# 获取所有发布的版本列表,并筛选出以v2开头的版本号
|
||
releases=$(curl ${CURL_OPTIONS} "https://api.github.com/repos/jxxghp/MoviePilot/releases" ${CURL_HEADERS} | jq -r '.[].tag_name' | grep "^v2\.")
|
||
if [ -z "$releases" ]; then
|
||
WARN "未找到任何v2.x版本,继续启动..."
|
||
else
|
||
# 找到最新的v2版本
|
||
latest_v2=$(echo "$releases" | sort -V | tail -n 1)
|
||
INFO "最新的v2.x版本号:${latest_v2}"
|
||
# 使用版本号比较函数进行比较,并下载最新版本
|
||
compare_versions "${current_version}" "${latest_v2}"
|
||
fi
|
||
else
|
||
WARN "当前版本号获取失败,继续启动..."
|
||
fi
|
||
fi
|
||
elif [[ "${MOVIEPILOT_AUTO_UPDATE}" = "false" ]]; then
|
||
INFO "程序自动升级已关闭,如需自动升级请在创建容器时设置环境变量:MOVIEPILOT_AUTO_UPDATE=release"
|
||
else
|
||
INFO "MOVIEPILOT_AUTO_UPDATE 变量设置错误"
|
||
fi
|