1
0
Fork 0
1Panel-Appstore/update_local_appstore.sh

359 lines
12 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
check_command() {
command -v "$1" > /dev/null 2>&1 || {
echo >&2 "未找到 $1 命令"
exit 1
}
}
check_command "cp"
check_command "cut"
check_command "git"
check_command "grep"
check_command "mktemp"
check_command "printf"
check_command "rm"
check_command "which"
check_command "xargs"
USE_ZH=false
if command -v curl >/dev/null 2>&1; then
COUNTRY=$(curl -s --connect-timeout 5 https://myip.ipip.net/json | grep -o '"location":\["[^"]*"' | cut -d '"' -f 4 2>/dev/null)
if [[ "$COUNTRY" == "中国" ]]; then
USE_ZH=true
fi
fi
if $USE_ZH; then
MSG_INTRO=" ###########################################
# 注意 #
# 如果你想复制特定的应用, 请使用参数 #
# --app <应用名> #
# #
# 如果你想指定1Panel的安装路径, 请使用参数#
# --1panel-path <路径> #
# #
# 例如, 如果你的1Panel安装在/opt, 请使用: #
# bash update_local_appstore.sh \\ #
# --app app_name_1 \\ #
# --app app_name_2 \\ #
# --1panel-path /opt #
###########################################"
MSG_CLEANUP_TEMP="克隆中断, 已删除临时文件夹 %s"
MSG_CLONE_SUCCESS="从源 %s 克隆成功"
MSG_CLONE_FAIL="所有源都已尝试, 但克隆失败"
MSG_COPY_NOTE="仅复制: %s"
MSG_COPY_SUCCESS="复制成功: %s"
MSG_ERR_APP_REQUIRE="错误: --app 参数需要指定应用名"
MSG_ERR_PATH_INVALID="错误: 指定的路径 '%s' 不存在或不是目录"
MSG_ERR_PATH_REQUIRE="错误: --1panel-path 参数需要指定路径"
MSG_ERR_MULTI_PATH="错误: 只能指定一个 --1panel-path 参数"
MSG_ERR_NO_1PANEL="未找到1Panel的安装路径, 使用 --1panel-path 设置1Panel的安装路径, 例如 --1panel-path /opt"
MSG_LATEST_COMMIT="本地仓库的最新提交: "
MSG_NOTE_UNKNOWN="注意: 未知参数 %s 被忽略"
MSG_WARN_APP_MISSING="警告: 应用 '%s' 在仓库中不存在"
MSG_TRY_CLONE="正在尝试克隆 %s"
MSG_ERR_CLONE_SOURCE_REQUIRE="错误: --clone-source 参数需要指定源名称"
MSG_ERR_UNKNOWN_SOURCE="错误: 未知的源 '%s'"
MSG_DRY_RUN_MODE="试运行模式已启用,不会执行任何实际更改"
MSG_DRY_RUN_URL_HEADER="将按以下顺序克隆 URL"
MSG_DRY_RUN_URL="将克隆: %s"
MSG_DRY_RUN_TARGET_DIR_EXISTS="目标目录 %s 存在"
MSG_DRY_RUN_TARGET_DIR_NOT_EXISTS="目标目录 %s 不存在"
MSG_DRY_RUN_COPY="将复制应用 '%s' 到 %s"
MSG_DRY_RUN_COPY_ALL="将复制所有应用到 %s"
else
MSG_INTRO=" ###########################################
# Note #
# If you want to copy specific apps, use #
# --app <app_name> parameter #
# #
# If you want to specify the installation #
# path of 1Panel, use the #
# --1panel-path <path> parameter #
# #
# For example, if you 1panel is installed #
# in /opt, use: #
# bash update_local_appstore.sh \\ #
# --app app_name_1 \\ #
# --app app_name_2 \\ #
# --1panel-path /opt #
###########################################"
MSG_CLEANUP_TEMP="Clone interrupted, temporary directory %s deleted"
MSG_CLONE_SUCCESS="Successfully cloned from source %s"
MSG_CLONE_FAIL="All sources have been attempted, but cloning Failed"
MSG_COPY_NOTE="Only copy: %s"
MSG_COPY_SUCCESS="Copied success: %s"
MSG_ERR_APP_REQUIRE="Error: --app parameter requires an app name"
MSG_ERR_PATH_INVALID="Error: Specified path '%s' does not exist or is not a directory"
MSG_ERR_PATH_REQUIRE="Error: --1panel-path parameter requires a path"
MSG_ERR_MULTI_PATH="Error: Only one --1panel-path parameter can be specified"
MSG_ERR_NO_1PANEL="No installation path found for 1panel, use --1panel-path to specify the installation path, e.g., --1panel-path /opt"
MSG_LATEST_COMMIT="Latest commit in the local repository:"
MSG_NOTE_UNKNOWN="Note: Unknown parameter %s ignored"
MSG_WARN_APP_MISSING="WARNING: App '%s' does not exist in repository"
MSG_TRY_CLONE="Trying to clone %s"
MSG_ERR_CLONE_SOURCE_REQUIRE="Error: --clone-source parameter requires a source name"
MSG_ERR_UNKNOWN_SOURCE="Error: Unknown source '%s'"
MSG_DRY_RUN_MODE="Dry run mode enabled, no changes will be made"
MSG_DRY_RUN_URL_HEADER="URLs to be cloned (in order):"
MSG_DRY_RUN_URL="Would clone: %s"
MSG_DRY_RUN_TARGET_DIR_EXISTS="Target directory %s exists"
MSG_DRY_RUN_TARGET_DIR_NOT_EXISTS="Target directory %s does not exist"
MSG_DRY_RUN_COPY="Would copy app '%s' to %s"
MSG_DRY_RUN_COPY_ALL="Would copy all apps to %s"
fi
apps_to_copy=()
custom_base_dir=""
clone_sources=()
dry_run=false
while [[ $# -gt 0 ]]; do
case $1 in
--app)
if [[ -n "$2" && "$2" != --* ]]; then
apps_to_copy+=("$2")
shift 2
else
echo "$MSG_ERR_APP_REQUIRE"
exit 1
fi
;;
--1panel-path)
if [[ -n "$2" && "$2" != --* ]]; then
if [[ -n "$custom_base_dir" ]]; then
echo "$MSG_ERR_MULTI_PATH"
exit 1
fi
custom_base_dir="$2"
if [ ! -d "$custom_base_dir" ]; then
printf "$MSG_ERR_PATH_INVALID\n" "$custom_base_dir"
exit 1
fi
shift 2
else
echo "$MSG_ERR_PATH_REQUIRE"
exit 1
fi
;;
--clone-source)
if [[ -n "$2" && "$2" != --* ]]; then
clone_sources+=("$2")
shift 2
else
echo "$MSG_ERR_CLONE_SOURCE_REQUIRE"
exit 1
fi
;;
--dry-run)
dry_run=true
shift
;;
*)
printf "$MSG_NOTE_UNKNOWN\n" "$1"
shift
;;
esac
done
echo "$MSG_INTRO"
if [[ -n "$custom_base_dir" ]]; then
BASE_DIR="$custom_base_dir"
else
BASE_DIR=$(which 1pctl | xargs grep '^BASE_DIR=' | cut -d'=' -f2)
if [ -z "$BASE_DIR" ]; then
echo "$MSG_ERR_NO_1PANEL"
exit 1
fi
fi
repo_prefixs=(
'https://github.com'
'https://gh-proxy.com/https://github.com'
'https://edgeone.gh-proxy.com/https://github.com'
'https://gh-proxy.net/github.com'
'https://kkgithub.com'
'https://wget.la/https://github.com'
'https://ghfast.top/https://github.com'
'https://githubfast.com'
'https://ghproxy.net/https://github.com'
)
declare -A mirror_sites=(
[codeberg]='https://codeberg.org/pooneyy/1Panel-Appstore.git'
[forgejo]='https://code.forgejo.org/pooneyy/1Panel-Appstore.git'
[gitea]='https://gitea.com/pooneyy/1Panel-Appstore.git'
[gitlab]='https://gitlab.com/pooneyy1/1panel-appstore.git'
[nixnet]='https://git.nixnet.services/pooneyy/1Panel-Appstore.git'
[bitnet]='https://git.bitnet.fun/pooneyy/1Panel-Appstore.git'
[smartscf]='https://repo.smartscf.cn/pooneyy/1Panel-Appstore.git'
[touchacme]='https://git.touchacme.cn/pooneyy/1Panel-Appstore.git'
)
mirror_names=("${!mirror_sites[@]}")
repo_suffix="/pooneyy/1Panel-Appstore.git"
if [ ${#clone_sources[@]} -eq 0 ]; then
clone_sources=("all")
fi
declare -A source_map
unique_sources=()
for src in "${clone_sources[@]}"; do
if [[ -z "${source_map[$src]}" ]]; then
source_map[$src]=1
unique_sources+=("$src")
fi
done
if [[ " ${unique_sources[@]} " =~ " all " ]]; then
final_sources=("all")
else
has_mirror=false
for src in "${unique_sources[@]}"; do
if [[ "$src" == "mirror" ]]; then
has_mirror=true
break
fi
done
if $has_mirror; then
final_sources=()
for src in "${unique_sources[@]}"; do
if [[ "$src" == "mirror" ]] || [[ "$src" == "github" ]]; then
final_sources+=("$src")
else
if [[ -n "${mirror_sites[$src]}" ]]; then
:
else
printf "$MSG_ERR_UNKNOWN_SOURCE\n" "$src"
exit 1
fi
fi
done
else
final_sources=()
for src in "${unique_sources[@]}"; do
if [[ "$src" == "github" ]] || [[ "$src" == "mirror" ]]; then
final_sources+=("$src")
elif [[ -n "${mirror_sites[$src]}" ]]; then
final_sources+=("$src")
else
printf "$MSG_ERR_UNKNOWN_SOURCE\n" "$src"
exit 1
fi
done
fi
fi
all_urls=()
shuffle_array() {
local arr=("$@")
local len=${#arr[@]}
for ((i=0; i<len; i++)); do
j=$((RANDOM % (len - i) + i))
tmp=${arr[i]}
arr[i]=${arr[j]}
arr[j]=$tmp
done
echo "${arr[@]}"
}
if [[ " ${final_sources[@]} " =~ " all " ]]; then
for prefix in "${repo_prefixs[@]}"; do
all_urls+=("${prefix}${repo_suffix}")
done
all_indep_urls=("${mirror_sites[@]}")
shuffled_indep=($(shuffle_array "${all_indep_urls[@]}"))
all_urls+=("${shuffled_indep[@]}")
else
if [[ " ${final_sources[@]} " =~ " github " ]]; then
for prefix in "${repo_prefixs[@]}"; do
all_urls+=("${prefix}${repo_suffix}")
done
fi
indep_urls_to_add=()
for src in "${final_sources[@]}"; do
if [[ "$src" == "mirror" ]]; then
indep_urls_to_add=("${mirror_sites[@]}")
break
elif [[ -n "${mirror_sites[$src]}" ]]; then
indep_urls_to_add+=("${mirror_sites[$src]}")
fi
done
if [ ${#indep_urls_to_add[@]} -gt 0 ]; then
shuffled_indep=($(shuffle_array "${indep_urls_to_add[@]}"))
all_urls+=("${shuffled_indep[@]}")
fi
fi
if $dry_run; then
echo "$MSG_DRY_RUN_MODE"
echo ""
echo "$MSG_DRY_RUN_URL_HEADER"
for url in "${all_urls[@]}"; do
printf "$MSG_DRY_RUN_URL\n" "$url"
done
echo ""
target_dir="$BASE_DIR/1panel/resource/apps/local/"
if [ ${#apps_to_copy[@]} -gt 0 ]; then
for app in "${apps_to_copy[@]}"; do
printf "$MSG_DRY_RUN_COPY\n" "$app" "$target_dir"
done
else
printf "$MSG_DRY_RUN_COPY_ALL\n" "$target_dir"
fi
if [ -d "$target_dir" ]; then
printf "$MSG_DRY_RUN_TARGET_DIR_EXISTS\n" "$target_dir"
else
printf "$MSG_DRY_RUN_TARGET_DIR_NOT_EXISTS\n" "$target_dir"
fi
exit 0
fi
TEMP_DIR=$(mktemp -d)
mkdir -p $BASE_DIR/1panel/resource/apps/local/
cleanup_temp_dir() {
rm -rf $TEMP_DIR
printf "$MSG_CLEANUP_TEMP\n" "$TEMP_DIR"
exit 1
}
trap cleanup_temp_dir INT TERM
counter=0
for full_url in "${all_urls[@]}"; do
printf "$MSG_TRY_CLONE\n" "$full_url"
git clone --depth 1 -b localApps $full_url $TEMP_DIR > /dev/null 2>&1 && break
counter=$((counter + 1))
done
if [ $counter -eq ${#all_urls[@]} ]; then
echo "$MSG_CLONE_FAIL"
else
printf "$MSG_CLONE_SUCCESS\n" "$full_url"
echo "$MSG_LATEST_COMMIT"
git -C $TEMP_DIR log --pretty=format:"%s - %h - %cr(%ci)" -n 1
if [ ${#apps_to_copy[@]} -gt 0 ]; then
echo ""
printf "$MSG_COPY_NOTE\n" "${apps_to_copy[*]}"
for app in "${apps_to_copy[@]}"; do
if [ -d "$TEMP_DIR/apps/$app" ]; then
cp -rf "$TEMP_DIR/apps/$app" "$BASE_DIR/1panel/resource/apps/local/"
printf "$MSG_COPY_SUCCESS\n" "$app"
else
printf "$MSG_WARN_APP_MISSING\n" "$app"
fi
done
else
cp -rf $TEMP_DIR/apps/* $BASE_DIR/1panel/resource/apps/local/
fi
fi
rm -rf $TEMP_DIR