diff --git a/README.md b/README.md index 6dbd261..b6d64b4 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ - [参数详解](#参数详解) - [举例](#举例) - [Alist](#alist) + - [Rclone](#rclone) + - [Calibre](#calibre) - [LianHuanHua](#lianhuanhua) - [Dev](#dev) @@ -257,6 +259,25 @@ wget https://woniuzfb.github.io/iptv/iptv.sh && bash iptv.sh ./debug ali ``` +## Rclone + +```bash +./debug rc +``` + +- remote +- mount +- serve + +## Calibre + +```bash +./debug cw +``` + +- calibre-web +- kcc + ## LianHuanHua ```bash diff --git a/build b/build index 6e012a2..e8fb388 100644 --- a/build +++ b/build @@ -11,7 +11,7 @@ ReplaceInclude() echo "${2:-}if [ \"\$self\" == \"tv\" ] || [ \"\$self\" == \"iptv\" ]" echo "${2:-}then" ReplaceInclude src/tv " ${2:-}" - bins=(v2 x nx or pve arm ibm cf cx ali lhh) + bins=(v2 x nx or pve arm ibm cf cx ali lhh rc cw) for bin in "${bins[@]}" do echo "${2:-}elif [ \"\$self\" == \"$bin\" ]" diff --git a/core b/core index 8ee0b0b..5c61de2 100644 --- a/core +++ b/core @@ -13,29 +13,37 @@ Trim() JoinByChar() { - local IFS="$1" - shift - echo "$*" + local IFS="$1" + shift + echo "$*" } JoinByString() { - local separator="$1" - shift - local first="$1" - shift - printf "%s" "$first" "${@/#/$separator}" + local separator="$1" + shift + local first="$1" + shift + printf "%s" "$first" "${@/#/$separator}" +} + +ToJsonArray() +{ + local var=("$1"[@]) + local arr=("${!var}") + local json_array=$(printf '%s\n' "${arr[@]}" | $JQ_FILE -R . | $JQ_FILE -s .) + echo $json_array } shopt -s extglob EleInArray() { - local ele="$1" - shift - local var=("$1"[@]) - local arr=("${!var}") - [[ "$ele" == @($(JoinByChar '|' "${arr[@]//|/\\|}")) ]] + local ele="$1" + shift + local var=("$1"[@]) + local arr=("${!var}") + [[ "$ele" == @($(JoinByChar '|' "${arr[@]//|/\\|}")) ]] } printf() @@ -197,6 +205,16 @@ GetRandomMac() echo $RANDOM|md5sum|sed 's/../&:/g'|cut -c 1-17 } +RemoveQuotes() +{ + local text="${!1}" + if [[ "$text" =~ ^\"(.*)\"$ ]] || [[ "$text" =~ ^\'(.*)\'$ ]] + then + text="${BASH_REMATCH[1]}" + read -r ${1} <<< "$text" + fi +} + PrepTerm() { unset term_child_pid diff --git a/docs/iptv.sh b/docs/iptv.sh index b85ec62..5467c1e 100755 --- a/docs/iptv.sh +++ b/docs/iptv.sh @@ -34,6 +34,7 @@ IP_DENY="$IPTV_ROOT/ip.deny" IP_LOG="$IPTV_ROOT/ip.log" FFMPEG_LOG_ROOT="$IPTV_ROOT/ffmpeg" # create your own mirror: tv ffmpeg +BACKUP_ROOT="$HOME"/iptv_sh_backup FFMPEG_MIRROR_LINK="http://pngquant.com/ffmpeg" V2_FILE="/usr/local/bin/v2" V2_LINK="https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh" @@ -41,6 +42,7 @@ V2_LINK_FALLBACK="$FFMPEG_MIRROR_LINK/v2ray_install-release.sh" V2CTL_FILE="/usr/local/bin/v2ctl" V2_CONFIG="/usr/local/etc/v2ray/config.json" X_FILE="/usr/local/bin/x" +X_CONFIG="/usr/local/etc/xray/config.json" FFMPEG_MIRROR_ROOT="$IPTV_ROOT/ffmpeg" LIVE_ROOT="$IPTV_ROOT/live" SERVICES_FILE="$IPTV_ROOT/services.json" @@ -136,10 +138,10 @@ ArchCheck() if grep -Eqi "x86_64|amd64" <<< "$arch" then arch="x86_64" - elif grep -Eqi "i386|i686" <<< "$arch" + elif grep -Eqi "i386|i686|x86" <<< "$arch" then arch="i386" - elif grep -Eqi "aarch64|armv8" <<< "$arch" + elif grep -Eqi "aarch64|armv8|arm64" <<< "$arch" then arch="arm64" elif grep -qi "armv7" <<< "$arch" @@ -17052,7 +17054,7 @@ Reg4gtvAcc() | $JQ_FILE -r '[.Success,.ErrMessage]|join(" ")' ) || true - if [ "$result" = true ] + if [ "$result" = true ] || [ "$msg" = "String was not recognized as a valid DateTime." ] then if [ ! -s "$SERVICES_FILE" ] then @@ -17281,7 +17283,7 @@ Login4gtvAcc() fi done Println "$info 账号验证成功" - Println "$info 开启 7 天豪华套餐" + Println "$info 开启 30 天豪华套餐" IFS="^" read -r result msg < <(CurlFake -s -Lm 20 \ -H 'Origin: https://www.4gtv.tv' \ @@ -17293,9 +17295,9 @@ Login4gtvAcc() if [ "$result" = true ] then - Println "$info 7 天豪华套餐开启成功\n" + Println "$info 30 天豪华套餐开启成功\n" else - Println "$error 开启 7 天豪华套餐发生错误, 请重试\n\n$msg\n" + Println "$error 开启 30 天豪华套餐发生错误, 请重试\n\n$msg\n" fi } @@ -17595,7 +17597,7 @@ _4gtvCron() fi done Println "$info 账号验证成功" - Println "$info 开启 7 天豪华套餐" + Println "$info 开启 30 天豪华套餐" IFS="^" read -r result msg < <(CurlFake -s -Lm 20 \ -H 'Origin: https://www.4gtv.tv' \ @@ -17607,9 +17609,9 @@ _4gtvCron() if [ "$result" = true ] then - Println "$info 7 天豪华套餐开启成功\n" + Println "$info 30 天豪华套餐开启成功\n" else - Println "$error 开启 7 天豪华套餐发生错误, 请重试\n\n$msg\n" + Println "$error 开启 30 天豪华套餐发生错误, 请重试\n\n$msg\n" fi } @@ -32287,7 +32289,7 @@ gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc if [[ $(ps --no-headers -o comm 1) == "systemd" ]] then sed -i "s/LimitNOFILE=.*/LimitNOFILE=$file_max/" /lib/systemd/system/mongod.service - sed -i '/TasksAccounting=/a RestartSec=5\nStartLimitIntervalSec=0\nRestart=on-failure' /lib/systemd/system/mongod.service + sed -i '/TasksAccounting=/a StartLimitInterval=60s\nStartLimitBurst=5\nRestartSec=5\nRestart=on-failure' /lib/systemd/system/mongod.service systemctl daemon-reload sed -i "s/destination: file/destination: syslog/" /etc/mongod.conf sed -i "s/ logAppend: true/ #logAppend: true/" /etc/mongod.conf @@ -48089,6 +48091,8 @@ Usage() `gettext \"pve 打开 Proxmox VE 管理面板\"` + `gettext \"tv backup 备份所有重要文件\"` + `gettext \"tv ed 选择默认编辑器\"` `gettext \"tv a 设置自定义命令\"` @@ -49117,8 +49121,9 @@ Wants=network-online.target [Service] ExecStart=$HOME/go/bin/go-mmproxy --allowed-subnets $HOME/allowed-subnets.txt -l $mmproxy_listen -4 $mmproxy_target_v4 -6 $mmproxy_target_v6 +StartLimitInterval=60s +StartLimitBurst=5 RestartSec=5 -StartLimitIntervalSec=0 Restart=on-failure [Install] @@ -49364,7 +49369,7 @@ then V2_LINK="https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh" V2_LINK_FALLBACK="$FFMPEG_MIRROR_LINK/xray_install-release.sh" V2CTL_FILE="/usr/local/bin/xray" - V2_CONFIG="/usr/local/etc/xray/config.json" + V2_CONFIG="$X_CONFIG" elif [ -d /etc/v2ray/ ] then systemctl disable v2ray --now > /dev/null 2> /dev/null || true @@ -52421,6 +52426,13 @@ then Println "$error jq.json 下载出错, 无法连接 github ?" fi + if curl -s -L "https://api.github.com/repos/alist-org/alist/releases/latest" -o "$FFMPEG_MIRROR_ROOT/alist.json_tmp" + then + mv "$FFMPEG_MIRROR_ROOT/alist.json_tmp" "$FFMPEG_MIRROR_ROOT/alist.json" + else + Println "$error alist.json 下载出错, 无法连接 github ?" + fi + if curl -s -L "https://api.github.com/repos/v2fly/v2ray-core/releases/latest" -o "$FFMPEG_MIRROR_ROOT/v2ray.json_tmp" then mv "$FFMPEG_MIRROR_ROOT/v2ray.json_tmp" "$FFMPEG_MIRROR_ROOT/v2ray.json" @@ -52840,6 +52852,176 @@ then fi exit 0 ;; + b|backup) + IPTV_ROOT="${IPTV_ROOT%/}" + FFMPEG_MIRROR_ROOT="${FFMPEG_MIRROR_ROOT%/}" + LIVE_ROOT="${LIVE_ROOT%/}" + NODE_ROOT="${NODE_ROOT%/}" + + iptv_source="$IPTV_ROOT" + + iptv_excludes=( + /ffmpeg-git-'*' + /vip + node_modules/ + ) + + ffmpeg_excludes=( + /Amlogic_s905-kernel-master.zip + /builds + /c + /dnscrypt + /fontforge-20190413.tar.gz + /imgcat.zip + /jq-'*' + /releases + /v2ray + /xray + '*'.ipk + '*'.err + '*'.log + '*'.pid + ) + + if [[ "$FFMPEG_MIRROR_ROOT" =~ "$iptv_source"(.*) ]] + then + relative_path="${BASH_REMATCH[1]:-}" + relative_path="${relative_path#/}" + if [ -n "$relative_path" ] + then + for i in "${!ffmpeg_excludes[@]}" + do + if [[ "${ffmpeg_excludes[i]}" == /* ]] + then + ffmpeg_excludes[i]="/${relative_path}${ffmpeg_excludes[i]}" + else + ffmpeg_excludes[i]="/$relative_path/${ffmpeg_excludes[i]}" + fi + done + fi + iptv_excludes+=("${ffmpeg_excludes[@]}") + else + ffmpeg_source="$FFMPEG_MIRROR_ROOT" + fi + + if [[ "$LIVE_ROOT" =~ "$IPTV_ROOT"(.+) ]] + then + iptv_excludes+=("${BASH_REMATCH[1]}") + fi + + node_excludes=( + node_modules/ + ) + + if ! [[ "$NODE_ROOT" =~ "$IPTV_ROOT"(.*) ]] + then + node_source="$NODE_ROOT" + fi + + nginx_source=/usr/local/nginx + + nginx_includes=( + /conf/'***' + /html/'***' + /logs/'***' + ) + + nginx_excludes=( + /logs/'*'.gz + node_modules/ + ) + + openresty_source=/usr/local/openresty + + openresty_includes=( + /nginx/ + /nginx/conf/'***' + /nginx/html/'***' + /nginx/logs/'***' + /nginx/lua/'***' + ) + + openresty_excludes=( + /nginx/logs/'*'.gz + node_modules/ + ) + + v2ray_source="${V2_CONFIG%/*}" + + xray_source="${X_CONFIG%/*}" + + DistCheck + + if [ "$dist" == "mac" ] + then + systemd_source="$HOME"/iptv_sh_systemd + else + systemd_source=/etc/systemd/system + fi + + systemd_includes=( + /alist.service + /aria2.service + /dnscrypt-proxy.service + /mmproxy-'*'.service + /nginx.service + /openresty.service + /v2ray.service + /xray.service + ) + + DepInstall rsync + + mkdir -p "$BACKUP_ROOT" + + for backup in iptv nginx openresty v2ray xray ffmpeg node systemd + do + rsync_commands=() + source="${backup}_source" + + if [[ -z "${!source:-}" ]] + then + continue + fi + + source="${!source}" + + if [ ! -d "$source" ] + then + continue + fi + + excludes=("${backup}_excludes"[@]) + + if [[ -n "${!excludes:-}" ]] + then + excludes=("${!excludes}") + for exclude in "${excludes[@]}" + do + rsync_commands+=( --exclude="$exclude" ) + done + fi + + includes=("${backup}_includes"[@]) + + if [[ -n "${!includes:-}" ]] + then + includes=("${!includes}") + for include in "${includes[@]}" + do + rsync_commands+=( --include="$include" ) + done + + rsync_commands+=( --exclude='*' ) + fi + + rsync -avP --safe-links --del ${rsync_commands[@]+"${rsync_commands[@]}"} "$source/" "$BACKUP_ROOT/$backup/" + done + + Println "$info 已创建备份 $BACKUP_ROOT\n" + + exit 0 + ;; *) ;; esac @@ -52855,7 +53037,7 @@ then Menu fi else - while getopts "i:l:P:o:p:S:t:s:c:v:a:f:d:q:b:r:k:K:m:n:z:H:T:L:CRe" flag + while getopts "i:l:P:o:p:S:t:s:c:v:a:f:d:q:b:r:k:K:m:n:z:H:T:L:CReh" flag do case "$flag" in i) stream_link="$OPTARG";; @@ -52885,7 +53067,7 @@ else H) flv_h265=true;; T) flv_push_link="$OPTARG";; L) flv_pull_link="$OPTARG";; - *) Usage; + h|*) Usage; esac done diff --git a/env b/env index c9d46f2..9a60849 100644 --- a/env +++ b/env @@ -32,6 +32,9 @@ FFMPEG_FILE=/usr/local/bin/ffmpeg FFPROBE_FILE=/usr/local/bin/ffprobe CURL_IMPERSONATE_FILE=/usr/local/bin/curl-impersonate +# backup +BACKUP_ROOT="$HOME"/iptv_sh_backup + # FFmpeg FFMPEG_ROOT="$HOME" @@ -54,7 +57,6 @@ XTREAM_CODES_EXAM="$IPTV_ROOT"/xtream_codes_exam IP_DENY="$IPTV_ROOT"/ip.deny IP_LOG="$IPTV_ROOT"/ip.log LIVE_ROOT="$IPTV_ROOT"/live -SERVICES_FILE="$IPTV_ROOT"/services.json VIP_FILE="$IPTV_ROOT"/vip.json VIP_CHANNELS_LINK="$FFMPEG_MIRROR_LINK"/vip_channels.json VIP_CHANNELS_FILE="$IPTV_ROOT"/vip_channels.json @@ -80,6 +82,7 @@ V2_CONFIG=/usr/local/etc/v2ray/config.json # xray X_FILE=/usr/local/bin/x +X_CONFIG=/usr/local/etc/xray/config.json # cloudflare CF_FILE=/usr/local/bin/cf @@ -98,8 +101,29 @@ IBM_FILE=/usr/local/bin/ibm IBM_APPS_ROOT="$HOME"/ibm_apps IBM_CONFIG="$HOME"/ibm.json +# Services +SERVICES_ROOT="$HOME"/iptv_sh_services +SERVICES_CONFIG="$SERVICES_ROOT"/config.json + # Alist ALIST_FILE=/usr/local/bin/ali +ALIST_ROOT="$SERVICES_ROOT"/alist +ALIST_LINK=https://github.com/alist-org/alist +ALIST_LINK_FALLBACK="$FFMPEG_MIRROR_LINK"/alist # LianHuanHua LIANHUANHUA_FILE=/usr/local/bin/lhh +LIANHUANHUA_ROOT="$SERVICES_ROOT"/lianhuanhua +LIANHUANHUA_CONFIG="$LIANHUANHUA_ROOT"/config.json + +# Rclone +RCLONE_FILE=/usr/local/bin/rc +RCLONE_ROOT="$SERVICES_ROOT"/rclone + +# Calibre +CALIBRE_FILE=/usr/local/bin/cw +CALIBRE_ROOT="$SERVICES_ROOT"/calibre + +# Kcc +KCC_ROOT="$CALIBRE_ROOT"/kcc +KCC_FILE="$KCC_ROOT"/kcc-c2e.py diff --git a/iptv.sh b/iptv.sh index b85ec62..5467c1e 100755 --- a/iptv.sh +++ b/iptv.sh @@ -34,6 +34,7 @@ IP_DENY="$IPTV_ROOT/ip.deny" IP_LOG="$IPTV_ROOT/ip.log" FFMPEG_LOG_ROOT="$IPTV_ROOT/ffmpeg" # create your own mirror: tv ffmpeg +BACKUP_ROOT="$HOME"/iptv_sh_backup FFMPEG_MIRROR_LINK="http://pngquant.com/ffmpeg" V2_FILE="/usr/local/bin/v2" V2_LINK="https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh" @@ -41,6 +42,7 @@ V2_LINK_FALLBACK="$FFMPEG_MIRROR_LINK/v2ray_install-release.sh" V2CTL_FILE="/usr/local/bin/v2ctl" V2_CONFIG="/usr/local/etc/v2ray/config.json" X_FILE="/usr/local/bin/x" +X_CONFIG="/usr/local/etc/xray/config.json" FFMPEG_MIRROR_ROOT="$IPTV_ROOT/ffmpeg" LIVE_ROOT="$IPTV_ROOT/live" SERVICES_FILE="$IPTV_ROOT/services.json" @@ -136,10 +138,10 @@ ArchCheck() if grep -Eqi "x86_64|amd64" <<< "$arch" then arch="x86_64" - elif grep -Eqi "i386|i686" <<< "$arch" + elif grep -Eqi "i386|i686|x86" <<< "$arch" then arch="i386" - elif grep -Eqi "aarch64|armv8" <<< "$arch" + elif grep -Eqi "aarch64|armv8|arm64" <<< "$arch" then arch="arm64" elif grep -qi "armv7" <<< "$arch" @@ -17052,7 +17054,7 @@ Reg4gtvAcc() | $JQ_FILE -r '[.Success,.ErrMessage]|join(" ")' ) || true - if [ "$result" = true ] + if [ "$result" = true ] || [ "$msg" = "String was not recognized as a valid DateTime." ] then if [ ! -s "$SERVICES_FILE" ] then @@ -17281,7 +17283,7 @@ Login4gtvAcc() fi done Println "$info 账号验证成功" - Println "$info 开启 7 天豪华套餐" + Println "$info 开启 30 天豪华套餐" IFS="^" read -r result msg < <(CurlFake -s -Lm 20 \ -H 'Origin: https://www.4gtv.tv' \ @@ -17293,9 +17295,9 @@ Login4gtvAcc() if [ "$result" = true ] then - Println "$info 7 天豪华套餐开启成功\n" + Println "$info 30 天豪华套餐开启成功\n" else - Println "$error 开启 7 天豪华套餐发生错误, 请重试\n\n$msg\n" + Println "$error 开启 30 天豪华套餐发生错误, 请重试\n\n$msg\n" fi } @@ -17595,7 +17597,7 @@ _4gtvCron() fi done Println "$info 账号验证成功" - Println "$info 开启 7 天豪华套餐" + Println "$info 开启 30 天豪华套餐" IFS="^" read -r result msg < <(CurlFake -s -Lm 20 \ -H 'Origin: https://www.4gtv.tv' \ @@ -17607,9 +17609,9 @@ _4gtvCron() if [ "$result" = true ] then - Println "$info 7 天豪华套餐开启成功\n" + Println "$info 30 天豪华套餐开启成功\n" else - Println "$error 开启 7 天豪华套餐发生错误, 请重试\n\n$msg\n" + Println "$error 开启 30 天豪华套餐发生错误, 请重试\n\n$msg\n" fi } @@ -32287,7 +32289,7 @@ gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc if [[ $(ps --no-headers -o comm 1) == "systemd" ]] then sed -i "s/LimitNOFILE=.*/LimitNOFILE=$file_max/" /lib/systemd/system/mongod.service - sed -i '/TasksAccounting=/a RestartSec=5\nStartLimitIntervalSec=0\nRestart=on-failure' /lib/systemd/system/mongod.service + sed -i '/TasksAccounting=/a StartLimitInterval=60s\nStartLimitBurst=5\nRestartSec=5\nRestart=on-failure' /lib/systemd/system/mongod.service systemctl daemon-reload sed -i "s/destination: file/destination: syslog/" /etc/mongod.conf sed -i "s/ logAppend: true/ #logAppend: true/" /etc/mongod.conf @@ -48089,6 +48091,8 @@ Usage() `gettext \"pve 打开 Proxmox VE 管理面板\"` + `gettext \"tv backup 备份所有重要文件\"` + `gettext \"tv ed 选择默认编辑器\"` `gettext \"tv a 设置自定义命令\"` @@ -49117,8 +49121,9 @@ Wants=network-online.target [Service] ExecStart=$HOME/go/bin/go-mmproxy --allowed-subnets $HOME/allowed-subnets.txt -l $mmproxy_listen -4 $mmproxy_target_v4 -6 $mmproxy_target_v6 +StartLimitInterval=60s +StartLimitBurst=5 RestartSec=5 -StartLimitIntervalSec=0 Restart=on-failure [Install] @@ -49364,7 +49369,7 @@ then V2_LINK="https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh" V2_LINK_FALLBACK="$FFMPEG_MIRROR_LINK/xray_install-release.sh" V2CTL_FILE="/usr/local/bin/xray" - V2_CONFIG="/usr/local/etc/xray/config.json" + V2_CONFIG="$X_CONFIG" elif [ -d /etc/v2ray/ ] then systemctl disable v2ray --now > /dev/null 2> /dev/null || true @@ -52421,6 +52426,13 @@ then Println "$error jq.json 下载出错, 无法连接 github ?" fi + if curl -s -L "https://api.github.com/repos/alist-org/alist/releases/latest" -o "$FFMPEG_MIRROR_ROOT/alist.json_tmp" + then + mv "$FFMPEG_MIRROR_ROOT/alist.json_tmp" "$FFMPEG_MIRROR_ROOT/alist.json" + else + Println "$error alist.json 下载出错, 无法连接 github ?" + fi + if curl -s -L "https://api.github.com/repos/v2fly/v2ray-core/releases/latest" -o "$FFMPEG_MIRROR_ROOT/v2ray.json_tmp" then mv "$FFMPEG_MIRROR_ROOT/v2ray.json_tmp" "$FFMPEG_MIRROR_ROOT/v2ray.json" @@ -52840,6 +52852,176 @@ then fi exit 0 ;; + b|backup) + IPTV_ROOT="${IPTV_ROOT%/}" + FFMPEG_MIRROR_ROOT="${FFMPEG_MIRROR_ROOT%/}" + LIVE_ROOT="${LIVE_ROOT%/}" + NODE_ROOT="${NODE_ROOT%/}" + + iptv_source="$IPTV_ROOT" + + iptv_excludes=( + /ffmpeg-git-'*' + /vip + node_modules/ + ) + + ffmpeg_excludes=( + /Amlogic_s905-kernel-master.zip + /builds + /c + /dnscrypt + /fontforge-20190413.tar.gz + /imgcat.zip + /jq-'*' + /releases + /v2ray + /xray + '*'.ipk + '*'.err + '*'.log + '*'.pid + ) + + if [[ "$FFMPEG_MIRROR_ROOT" =~ "$iptv_source"(.*) ]] + then + relative_path="${BASH_REMATCH[1]:-}" + relative_path="${relative_path#/}" + if [ -n "$relative_path" ] + then + for i in "${!ffmpeg_excludes[@]}" + do + if [[ "${ffmpeg_excludes[i]}" == /* ]] + then + ffmpeg_excludes[i]="/${relative_path}${ffmpeg_excludes[i]}" + else + ffmpeg_excludes[i]="/$relative_path/${ffmpeg_excludes[i]}" + fi + done + fi + iptv_excludes+=("${ffmpeg_excludes[@]}") + else + ffmpeg_source="$FFMPEG_MIRROR_ROOT" + fi + + if [[ "$LIVE_ROOT" =~ "$IPTV_ROOT"(.+) ]] + then + iptv_excludes+=("${BASH_REMATCH[1]}") + fi + + node_excludes=( + node_modules/ + ) + + if ! [[ "$NODE_ROOT" =~ "$IPTV_ROOT"(.*) ]] + then + node_source="$NODE_ROOT" + fi + + nginx_source=/usr/local/nginx + + nginx_includes=( + /conf/'***' + /html/'***' + /logs/'***' + ) + + nginx_excludes=( + /logs/'*'.gz + node_modules/ + ) + + openresty_source=/usr/local/openresty + + openresty_includes=( + /nginx/ + /nginx/conf/'***' + /nginx/html/'***' + /nginx/logs/'***' + /nginx/lua/'***' + ) + + openresty_excludes=( + /nginx/logs/'*'.gz + node_modules/ + ) + + v2ray_source="${V2_CONFIG%/*}" + + xray_source="${X_CONFIG%/*}" + + DistCheck + + if [ "$dist" == "mac" ] + then + systemd_source="$HOME"/iptv_sh_systemd + else + systemd_source=/etc/systemd/system + fi + + systemd_includes=( + /alist.service + /aria2.service + /dnscrypt-proxy.service + /mmproxy-'*'.service + /nginx.service + /openresty.service + /v2ray.service + /xray.service + ) + + DepInstall rsync + + mkdir -p "$BACKUP_ROOT" + + for backup in iptv nginx openresty v2ray xray ffmpeg node systemd + do + rsync_commands=() + source="${backup}_source" + + if [[ -z "${!source:-}" ]] + then + continue + fi + + source="${!source}" + + if [ ! -d "$source" ] + then + continue + fi + + excludes=("${backup}_excludes"[@]) + + if [[ -n "${!excludes:-}" ]] + then + excludes=("${!excludes}") + for exclude in "${excludes[@]}" + do + rsync_commands+=( --exclude="$exclude" ) + done + fi + + includes=("${backup}_includes"[@]) + + if [[ -n "${!includes:-}" ]] + then + includes=("${!includes}") + for include in "${includes[@]}" + do + rsync_commands+=( --include="$include" ) + done + + rsync_commands+=( --exclude='*' ) + fi + + rsync -avP --safe-links --del ${rsync_commands[@]+"${rsync_commands[@]}"} "$source/" "$BACKUP_ROOT/$backup/" + done + + Println "$info 已创建备份 $BACKUP_ROOT\n" + + exit 0 + ;; *) ;; esac @@ -52855,7 +53037,7 @@ then Menu fi else - while getopts "i:l:P:o:p:S:t:s:c:v:a:f:d:q:b:r:k:K:m:n:z:H:T:L:CRe" flag + while getopts "i:l:P:o:p:S:t:s:c:v:a:f:d:q:b:r:k:K:m:n:z:H:T:L:CReh" flag do case "$flag" in i) stream_link="$OPTARG";; @@ -52885,7 +53067,7 @@ else H) flv_h265=true;; T) flv_push_link="$OPTARG";; L) flv_pull_link="$OPTARG";; - *) Usage; + h|*) Usage; esac done diff --git a/make b/make index 25902b4..8caffc6 100755 --- a/make +++ b/make @@ -1,5 +1,5 @@ #!/bin/bash -# LianHuanHua / Alist / FFmpeg / Nginx / Openresty / V2ray / Xray / Cloudflare / IBM Cloud Foundry / Armbian / Proxmox VE / ... +# LianHuanHua / Rclone / Alist / Calibre / FFmpeg / Nginx / Openresty / V2ray / Xray / Cloudflare / IBM Cloud Foundry / Armbian / Proxmox VE / ... # Copyright (C) 2019-2024 # Released under GPL Version 3 License diff --git a/src/_4gtv/cron b/src/_4gtv/cron index cd320b6..168c57b 100644 --- a/src/_4gtv/cron +++ b/src/_4gtv/cron @@ -12,9 +12,9 @@ _4gtvCron() if [ "$result" = true ] then - if [ ! -s "$SERVICES_FILE" ] + if [ ! -s "$SERVICES_CONFIG" ] then - printf '{"%s":{"%s":[]}}' "4gtv" "accounts" > "$SERVICES_FILE" + printf '{"%s":{"%s":[]}}' "4gtv" "accounts" > "$SERVICES_CONFIG" fi new_acc=$( $JQ_FILE -n --arg email "$_4gtv_acc_email" --arg password "$_4gtv_acc_pass" \ @@ -24,7 +24,7 @@ _4gtvCron() }' ) jq_path='["4gtv","accounts"]' - JQ add "$SERVICES_FILE" "[$new_acc]" + JQ add "$SERVICES_CONFIG" "[$new_acc]" Println "$info 账号注册成功\n" else Println "$error 账号注册失败, 请重试\n\n$msg\n" @@ -79,7 +79,7 @@ _4gtvCron() map_string=true jq_path='["4gtv","accounts"]' jq_path2='["token"]' - JQ update "$SERVICES_FILE" email "$_4gtv_acc_email" "$token" + JQ update "$SERVICES_CONFIG" email "$_4gtv_acc_email" "$token" Println "$info 账号登录成功" Println "$info 验证账号..." @@ -102,7 +102,7 @@ _4gtvCron() fi done Println "$info 账号验证成功" - Println "$info 开启 7 天豪华套餐" + Println "$info 开启 30 天豪华套餐" IFS="^" read -r result msg < <(CurlFake -s -Lm 20 \ -H 'Origin: https://www.4gtv.tv' \ @@ -114,8 +114,8 @@ _4gtvCron() if [ "$result" = true ] then - Println "$info 7 天豪华套餐开启成功\n" + Println "$info 30 天豪华套餐开启成功\n" else - Println "$error 开启 7 天豪华套餐发生错误, 请重试\n\n$msg\n" + Println "$error 开启 30 天豪华套餐发生错误, 请重试\n\n$msg\n" fi } diff --git a/src/_4gtv/del_acc b/src/_4gtv/del_acc index 910c478..4b8c760 100644 --- a/src/_4gtv/del_acc +++ b/src/_4gtv/del_acc @@ -22,7 +22,7 @@ Del4gtvAcc() then _4gtv_accs_index=$((_4gtv_accs_num-1)) jq_path='["4gtv","accounts",'"$_4gtv_accs_index"']' - JQ delete "$SERVICES_FILE" + JQ delete "$SERVICES_CONFIG" Println "$info 账号删除成功\n" break else diff --git a/src/_4gtv/edit_acc b/src/_4gtv/edit_acc index a2fe6f8..6d639b3 100644 --- a/src/_4gtv/edit_acc +++ b/src/_4gtv/edit_acc @@ -32,7 +32,7 @@ Edit4gtvAcc() ) json=true jq_path='["4gtv","accounts",'"$_4gtv_accs_index"']' - JQ update "$SERVICES_FILE" "$new_acc" + JQ update "$SERVICES_CONFIG" "$new_acc" Println "$info 账号修改成功\n" break else diff --git a/src/_4gtv/list_accs b/src/_4gtv/list_accs index 92c246c..8827c0f 100644 --- a/src/_4gtv/list_accs +++ b/src/_4gtv/list_accs @@ -1,6 +1,6 @@ List4gtvAccs() { - GetServiceAccs 4gtv + ServiceGet 4gtv _4gtv_accs_list="" for((i=0;i<_4gtv_accs_count;i++)); diff --git a/src/_4gtv/login_acc b/src/_4gtv/login_acc index ba8cadd..d338ccf 100644 --- a/src/_4gtv/login_acc +++ b/src/_4gtv/login_acc @@ -32,7 +32,7 @@ Login4gtvAcc() }' ) jq_path='["4gtv","accounts"]' - JQ add "$SERVICES_FILE" "[$new_acc]" + JQ add "$SERVICES_CONFIG" "[$new_acc]" Println "$info 账号添加成功\n" break ;; @@ -95,7 +95,7 @@ Login4gtvAcc() done jq_path='["4gtv","accounts",'"$_4gtv_accs_index"',"token"]' - JQ update "$SERVICES_FILE" "$token" + JQ update "$SERVICES_CONFIG" "$token" Println "$info 账号登录成功" Println "$info 验证账号..." for((i=0;i<3;i++)); @@ -117,7 +117,7 @@ Login4gtvAcc() fi done Println "$info 账号验证成功" - Println "$info 开启 7 天豪华套餐" + Println "$info 开启 30 天豪华套餐" IFS="^" read -r result msg < <(CurlFake -s -Lm 20 \ -H 'Origin: https://www.4gtv.tv' \ @@ -129,8 +129,8 @@ Login4gtvAcc() if [ "$result" = true ] then - Println "$info 7 天豪华套餐开启成功\n" + Println "$info 30 天豪华套餐开启成功\n" else - Println "$error 开启 7 天豪华套餐发生错误, 请重试\n\n$msg\n" + Println "$error 开启 30 天豪华套餐发生错误, 请重试\n\n$msg\n" fi } diff --git a/src/_4gtv/reg_acc b/src/_4gtv/reg_acc index 14227f7..b3461e2 100644 --- a/src/_4gtv/reg_acc +++ b/src/_4gtv/reg_acc @@ -10,11 +10,11 @@ Reg4gtvAcc() | $JQ_FILE -r '[.Success,.ErrMessage]|join(" ")' ) || true - if [ "$result" = true ] + if [ "$result" = true ] || [ "$msg" = "String was not recognized as a valid DateTime." ] then - if [ ! -s "$SERVICES_FILE" ] + if [ ! -s "$SERVICES_CONFIG" ] then - printf '{"%s":{"%s":[]}}' "4gtv" "accounts" > "$SERVICES_FILE" + printf '{"%s":{"%s":[]}}' "4gtv" "accounts" > "$SERVICES_CONFIG" fi new_acc=$( $JQ_FILE -n --arg email "$_4gtv_acc_email" --arg password "$_4gtv_acc_pass" \ @@ -24,7 +24,7 @@ Reg4gtvAcc() }' ) jq_path='["4gtv","accounts"]' - JQ add "$SERVICES_FILE" "[$new_acc]" + JQ add "$SERVICES_CONFIG" "[$new_acc]" Println "$info 账号注册成功\n" else Println "$error 账号注册失败, 请重试\n\n$msg\n" diff --git a/src/ali b/src/ali index 9654010..9cdee74 100644 --- a/src/ali +++ b/src/ali @@ -1,9 +1,7 @@ -Include src/iptv/get_service -Include src/alist/add_app -Include src/alist/view_app -Include src/alist/add_acc -Include src/alist/view_acc -Include src/alist/login_acc +Include src/service/get +Include src/service/control +Include src/alist/app +Include src/alist/acc Include src/alist/api Include src/alist/act @@ -17,19 +15,19 @@ case $alist_options_index in ;; 1) echo - alist_app_options=( '查看' '添加' '安装' '修改' '删除' ) + alist_app_options=( '查看' '添加' '修改' '删除' '本地安装/升级' ) inquirer list_input_index "选择操作" alist_app_options alist_app_options_index case $alist_app_options_index in - 0) AlistViewApp + 0) AlistAppView ;; - 1) AlistAddApp + 1) AlistAppAdd ;; - 2) AlistInstallApp + 2) AlistAppEdit ;; - 3) AlistEditApp + 3) AlistAppDel ;; - 4) AlistDelApp + 4) AlistAppInstall ;; esac ;; @@ -39,15 +37,15 @@ case $alist_options_index in inquirer list_input_index "选择操作" alist_acc_options alist_acc_options_index case $alist_acc_options_index in - 0) AlistViewAcc + 0) AlistAccView ;; - 1) AlistAddAcc + 1) AlistAccAdd ;; - 2) AlistLoginAcc + 2) AlistAccLogin ;; - 3) AlistEditAcc + 3) AlistAccEdit ;; - 4) AlistDelAcc + 4) AlistAccDel ;; esac ;; diff --git a/src/alist/acc b/src/alist/acc new file mode 100644 index 0000000..777603d --- /dev/null +++ b/src/alist/acc @@ -0,0 +1,192 @@ +AlistAccAdd() +{ + ServiceGet alist + + if [ "$alists_count" -eq 0 ] + then + Println "$error 请先添加 Alist\n" + exit 1 + fi + + alists_options=() + for((i=0;i $alist_file_name\n" + Alist.fs.rename + done else echo alist_files_txt="" diff --git a/src/alist/add_acc b/src/alist/add_acc deleted file mode 100644 index 8d2effc..0000000 --- a/src/alist/add_acc +++ /dev/null @@ -1,70 +0,0 @@ -AlistAddAcc() -{ - GetServiceAccs alist - - if [ "$alists_count" -eq 0 ] - then - Println "$error 请先添加 Alist\n" - exit 1 - fi - - alists_options=() - for((i=0;i/dev/null || true + fi + + printf -v date '%(%m-%d-%H:%M:%S)T' -1 + alist_backup="$ALIST_ROOT-$date" + mv "$ALIST_ROOT" "$alist_backup" + else + echo + ExitOnText "设置 Alist admin 密码" alist_pass + fi + + if [ "$dist" == "mac" ] + then + alist_pack_name="alist-darwin" + else + alist_pack_name="alist-linux-musl" + fi + + ArchCheck + + if [ "$arch" == "x86_64" ] + then + alist_pack_name="${alist_pack_name}-amd64.tar.gz" + elif [ "$arch" == "s390x" ] + then + alist_pack_name="${alist_pack_name}-s390x.tar.gz" + else + alist_pack_name="${alist_pack_name}-arm64.tar.gz" + fi + + if ! TMP_DIR=$(mktemp -q -d) + then + printf -v TMP_DIR '%(%m-%d-%H:%M:%S)T' -1 + mkdir -p "$TMP_DIR" + fi + + trap ' + rm -rf "${TMP_DIR:-notfound}" + ' EXIT + + cd "$TMP_DIR" + + if ! curl -O -L "$ALIST_LINK/releases/latest/download/$alist_pack_name" && ! curl -O -L "$ALIST_LINK_FALLBACK/releases/latest/download/$alist_pack_name" + then + Println "$error 无法下载 Alist, 请稍后再试\n" + return 1 + fi + + mkdir "$ALIST_ROOT" + tar zxf "$TMP_DIR/$alist_pack_name" -C "$ALIST_ROOT"/ + + if [ -n "${alist_backup:-}" ] && [ -d "${alist_backup}/data" ] + then + cp -r "$alist_backup"/data "$ALIST_ROOT"/ + else + mkdir -p "$ALIST_ROOT"/data/log + alist_config=$( + $JQ_FILE -n --arg db_file "${ALIST_ROOT}/data/data.db" --arg bleve_dir "${ALIST_ROOT}/data/bleve" \ + --arg log "${ALIST_ROOT}/data/log/log.log" \ + '{ + "force": false, + "site_url": "", + "cdn": "", + "jwt_secret": "", + "token_expires_in": 48, + "database": { + "type": "sqlite3", + "host": "", + "port": 0, + "user": "", + "password": "", + "name": "", + "db_file": $db_file, + "table_prefix": "x_", + "ssl_mode": "", + "dsn": "" + }, + "meilisearch": { + "host": "http://localhost:7700", + "api_key": "", + "index_prefix": "" + }, + "scheme": { + "address": "127.0.0.1", + "http_port": 5244, + "https_port": -1, + "force_https": false, + "cert_file": "", + "key_file": "", + "unix_file": "", + "unix_file_perm": "" + }, + "temp_dir": "/tmp/alist", + "bleve_dir": $bleve_dir, + "dist_dir": "", + "log": { + "enable": true, + "name": $log, + "max_size": 10, + "max_backups": 5, + "max_age": 28, + "compress": false + }, + "delayed_start": 0, + "max_connections": 0, + "tls_insecure_skip_verify": true, + "tasks": { + "download": { + "workers": 5, + "max_retry": 1 + }, + "transfer": { + "workers": 5, + "max_retry": 2 + }, + "upload": { + "workers": 5, + "max_retry": 0 + }, + "copy": { + "workers": 5, + "max_retry": 2 + } + }, + "cors": { + "allow_origins": [ + "*" + ], + "allow_methods": [ + "*" + ], + "allow_headers": [ + "*" + ] + }, + "s3": { + "enable": false, + "port": 5246, + "ssl": false + } + }' + ) + + echo "$alist_config" > "$ALIST_ROOT"/data/config.json + cd "$ALIST_ROOT" + ./alist admin set "$alist_pass" + fi + + service_name="alist" + + service_commands=( "$ALIST_ROOT"/alist server --data "$ALIST_ROOT"/data ) + + if ! err_msg=$(ServiceControl start "$service_name" service_commands) + then + Println "$error $service_name 启动失败, $err_msg\n" + return 1 + fi + + rm -rf "${TMP_DIR:-notfound}" + trap - EXIT + + Println "$info Alist 安装成功\n" +} diff --git a/src/alist/login_acc b/src/alist/login_acc deleted file mode 100644 index 32ada05..0000000 --- a/src/alist/login_acc +++ /dev/null @@ -1,68 +0,0 @@ -AlistLoginAcc() -{ - DepInstall curl - - GetServiceAccs alist - - if [ "$alists_count" -eq 0 ] - then - Println "$error 请先添加 Alist\n" - exit 1 - fi - - alists_options=() - for((i=0;i "$SERVICES_FILE" - fi - - SetDelimiters - - if [ "$service_id" == "4gtv" ] - then - IFS=$'\003\t' read -r d_4gtv_proxy _4gtv_acc_email _4gtv_acc_pass _4gtv_acc_token < <(JQs flat "$SERVICES_FILE" '' ' - [(."'"$service_id"'".proxy // "") + "\u0003"] + ((."'"$service_id"'".accounts | if (.|type == "string") then {} else . end) as $accounts | - reduce ({email,password,token}|keys_unsorted[]) as $key ([]; - $accounts[$key] as $val | if $val then - . + [$val + "\u0002\u0003"] - else - . + ["\u0003"] - end - ))|@tsv' "${delimiters[@]}") - - IFS="${delimiters[1]}" read -r -a _4gtv_accs_email <<< "$_4gtv_acc_email" - IFS="${delimiters[1]}" read -r -a _4gtv_accs_pass <<< "$_4gtv_acc_pass" - IFS="${delimiters[1]}" read -r -a _4gtv_accs_token <<< "$_4gtv_acc_token" - - _4gtv_accs_count=${#_4gtv_accs_email[@]} - elif [ "$service_id" == "alist" ] - then - IFS=$'\004\t' read -r alist_name alist_url alist_acc_username \ - alist_acc_password alist_acc_token < <(JQs flat "$SERVICES_FILE" '' ' - (."'"$service_id"'" | if (.|type == "string") then {} else . end) as $alist | - ($alist.accs // {} | if (.|type) == "string" then {} else . end) as $accs | - reduce ({name,url}|keys_unsorted[]) as $key ([]; - $alist[$key] as $val | if $val then - . + [$val + "\u0002\u0004"] - else - . + ["\u0004"] - end - ) + reduce ({username,password,token}|keys_unsorted[]) as $key ([]; - $accs[$key] as $val | if $val then - . + [$val + "\u0003\u0004"] - else - . + ["\u0004"] - end - )|@tsv' "${delimiters[@]}") - - IFS="${delimiters[1]}" read -r -a alists_name <<< "$alist_name" - IFS="${delimiters[1]}" read -r -a alists_url <<< "$alist_url" - IFS="${delimiters[2]}" read -r -a alists_acc_username <<< "$alist_acc_username" - IFS="${delimiters[2]}" read -r -a alists_acc_password <<< "$alist_acc_password" - IFS="${delimiters[2]}" read -r -a alists_acc_token <<< "$alist_acc_token" - - alists_count=${#alists_name[@]} - else - IFS=$'\003\t' read -r m_user_name m_phone_number m_password m_access_token m_device_no m_device_id m_refresh < <(JQs flat "$SERVICES_FILE" '' ' - (."'"$service_id"'".accounts | if (.|type == "string") then {} else . end) as $accounts | - reduce ({user_name,phone_number,password,access_token,device_no,device_id,refresh}|keys_unsorted[]) as $key ([]; - $accounts[$key] as $val | if $val then - . + [$val + "\u0002\u0003"] - else - . + ["\u0003"] - end - )|@tsv' "${delimiters[@]}") - - if [ -z "$m_user_name" ] - then - ts_accs_count=0 - return 0 - fi - - IFS="${delimiters[1]}" read -r -a ts_accs_user_name <<< "$m_user_name" - - if [ -z "$m_phone_number" ] - then - ts_accs_phone_number=("${ts_accs_user_name[@]//*/}") - else - IFS="${delimiters[1]}" read -r -a ts_accs_phone_number <<< "$m_phone_number" - fi - - IFS="${delimiters[1]}" read -r -a ts_accs_password <<< "$m_password" - IFS="${delimiters[1]}" read -r -a ts_accs_access_token <<< "$m_access_token" - IFS="${delimiters[1]}" read -r -a ts_accs_device_no <<< "$m_device_no" - IFS="${delimiters[1]}" read -r -a ts_accs_device_id <<< "$m_device_id" - IFS="${delimiters[1]}" read -r -a ts_accs_refresh <<< "$m_refresh" - - ts_accs_count=${#ts_accs_user_name[@]} - fi -} diff --git a/src/iptv/menu_ts b/src/iptv/menu_ts index f613536..f5fa69e 100644 --- a/src/iptv/menu_ts +++ b/src/iptv/menu_ts @@ -229,7 +229,7 @@ do model="${ts_model[ts_index]}" app_version="${ts_app_version[ts_index]}" - GetServiceAccs "$id" + ServiceGet "$id" accs_options=() @@ -540,7 +540,7 @@ do if [ "$acc_options_index" -eq 1 ] then jq_path='["'"$id"'","accounts",'"$accs_options_index"']' - JQ delete "$SERVICES_FILE" + JQ delete "$SERVICES_CONFIG" Println "$info 账号删除成功" continue fi @@ -644,7 +644,7 @@ do merge=true jq_path='["'"$id"'","accounts",'"$accs_options_index"']' - JQ update "$SERVICES_FILE" "$update" + JQ update "$SERVICES_CONFIG" "$update" else if [ -n "$img_url" ] then @@ -696,15 +696,15 @@ do ) fi - if [[ $($JQ_FILE --argjson path '["'"$id"'","accounts"]' --arg user_name "$user_name" 'getpath($path) // []|map(select(.user_name==$user_name))' "$SERVICES_FILE") != "[]" ]] + if [[ $($JQ_FILE --argjson path '["'"$id"'","accounts"]' --arg user_name "$user_name" 'getpath($path) // []|map(select(.user_name==$user_name))' "$SERVICES_CONFIG") != "[]" ]] then merge=true map_string=true jq_path='["'"$id"'","accounts"]' - JQ update "$SERVICES_FILE" user_name "$user_name" "$new_acc" + JQ update "$SERVICES_CONFIG" user_name "$user_name" "$new_acc" else jq_path='["'"$id"'","accounts"]' - JQ add "$SERVICES_FILE" "[$new_acc]" + JQ add "$SERVICES_CONFIG" "[$new_acc]" fi fi diff --git a/src/iptv/parse_stream b/src/iptv/parse_stream index 1dcde12..e1a7d3c 100644 --- a/src/iptv/parse_stream +++ b/src/iptv/parse_stream @@ -274,7 +274,7 @@ ParseStream() if [ "$set_id" -eq 1 ] then - GetServiceAccs 4gtv + ServiceGet 4gtv for((s_i=0;s_i<_4gtv_accs_count;s_i++)); do if [ -n "${_4gtv_accs_token[s_i]:-}" ] diff --git a/src/iptv/start_channel b/src/iptv/start_channel index 5e8b5a8..85ebb66 100644 --- a/src/iptv/start_channel +++ b/src/iptv/start_channel @@ -223,7 +223,7 @@ StartChannel() if [ "$set_id" -eq 1 ] then - GetServiceAccs 4gtv + ServiceGet 4gtv for((i=0;i<_4gtv_accs_count;i++)); do if [ -n "${_4gtv_accs_token[i]:-}" ] diff --git a/src/iptv/usage b/src/iptv/usage index 3516d42..5979017 100644 --- a/src/iptv/usage +++ b/src/iptv/usage @@ -84,6 +84,7 @@ Usage() `gettext \"x e 手动修改 config.json\"` `gettext \"nx 打开 nginx 面板\"` + `gettext \"nx e 手动修改配置文件\"` `gettext \"or 打开 openresty 面板\"` @@ -98,6 +99,10 @@ Usage() `gettext \"pve 打开 Proxmox VE 管理面板\"` + `gettext \"tv b 备份所有重要文件\"` + + `gettext \"tv curl 安装 curl impersonate\"` + `gettext \"tv ed 选择默认编辑器\"` `gettext \"tv a 设置自定义命令\"` diff --git a/src/lhh b/src/lhh index f1bc26d..f030b9a 100644 --- a/src/lhh +++ b/src/lhh @@ -3,8 +3,11 @@ Include utils/ffmpeg "$@" Include utils/node "$@" Include utils/nodejs "$@" -ebooks_root="$HOME/ebooks" -ebooks_config="$ebooks_root/config.json" +if [ ! -f "$LIANHUANHUA_CONFIG" ] && [ -f "$HOME/ebooks/config.json" ] +then + mkdir -p "$LIANHUANHUA_ROOT" + cp "$HOME/ebooks/config.json" "$LIANHUANHUA_CONFIG" +fi LhhDownload() { @@ -138,17 +141,17 @@ ZhLhh() local search_keys=( a b c d e f a ) local search_means=( '书名' '原著' '改编' '绘画' '出版社' '颜色' '人物' ) libcode=A7CCFF874E0E58868FF7FA84BF94B4C94E9F781AEF6E50E0359E12099735745F2B943218D8F245B2BD8EFA919770D399 - COOKIE_FILE="$ebooks_root/cookie_zhlhh" + COOKIE_FILE="$LIANHUANHUA_ROOT/cookie_zhlhh" - if [ ! -s "$ebooks_config" ] + if [ ! -s "$LIANHUANHUA_CONFIG" ] then - mkdir -p "$ebooks_root/" - printf '{"%s":{"%s":[]}}' "books" "zhlhh" > "$ebooks_config" + mkdir -p "$LIANHUANHUA_ROOT/" + printf '{"%s":{"%s":[]}}' "books" "zhlhh" > "$LIANHUANHUA_CONFIG" fi SetDelimiters - jq_input=$($JQ_FILE -c 'del(.books.hdlz)' "$ebooks_config") + jq_input=$($JQ_FILE -c 'del(.books.hdlz)' "$LIANHUANHUA_CONFIG") IFS=$'\003\t' read -r default_save_dir m_adapter m_addtime m_bookname m_category_id m_cover m_drawing m_m \ m_muludir m_original m_p m_publish m_yd m_downloaded m_fav < <(JQs flat "$jq_input" '' \ @@ -216,6 +219,7 @@ reduce ({adapter,addtime,bookname,category_id,cover,drawing,m,muludir,original,p result_yd=("${books_yd[@]}") result_p=("${books_p[@]}") iframe_paths=($(CurlFake -s -L -b "$COOKIE_FILE" -H "Referer: http://www.zhlhh.com/" "http://www.zhlhh.com/web/js/main.js" | grep -oP 'url = "\K[^"]+')) + books_indices=("${!books_m[@]}") else if EleInArray $((${#search_means[@]}-1)) search_keys_indices then @@ -373,7 +377,7 @@ reduce ({adapter,addtime,bookname,category_id,cover,drawing,m,muludir,original,p if [ -n "${books:-}" ] then jq_path='["books","zhlhh"]' - JQ add "$ebooks_config" "[$books]" + JQ add "$LIANHUANHUA_CONFIG" "[$books]" fi fi @@ -390,6 +394,7 @@ reduce ({adapter,addtime,bookname,category_id,cover,drawing,m,muludir,original,p then echo inquirer text_input "输入存储文件夹目录" save_dir "${default_save_dir}" + RemoveQuotes save_dir if [ -z "$save_dir" ] then Println "已取消...\n" @@ -399,7 +404,7 @@ reduce ({adapter,addtime,bookname,category_id,cover,drawing,m,muludir,original,p if [ "$save_dir" != "$default_save_dir" ] then jq_path='["default","save_dir"]' - JQ update "$ebooks_config" "$save_dir" + JQ update "$LIANHUANHUA_CONFIG" "$save_dir" fi FFmpegInstall @@ -413,7 +418,7 @@ reduce ({adapter,addtime,bookname,category_id,cover,drawing,m,muludir,original,p then bool=true jq_path='["books","zhlhh",'"$books_index"',"downloaded"]' - JQ update "$ebooks_config" true + JQ update "$LIANHUANHUA_CONFIG" true fi done @@ -427,7 +432,7 @@ reduce ({adapter,addtime,bookname,category_id,cover,drawing,m,muludir,original,p then bool=true jq_path='["books","zhlhh",'"$books_index"',"fav"]' - JQ update "$ebooks_config" true + JQ update "$LIANHUANHUA_CONFIG" true fi done Println "$info 已添加到收藏\n" @@ -439,7 +444,7 @@ reduce ({adapter,addtime,bookname,category_id,cover,drawing,m,muludir,original,p then bool=true jq_path='["books","zhlhh",'"$books_index"',"fav"]' - JQ update "$ebooks_config" false + JQ update "$LIANHUANHUA_CONFIG" false fi done Println "$info 已取消收藏\n" @@ -631,15 +636,15 @@ HdlzGetTouTiaoCookies() HdlzLhh() { - if [ ! -s "$ebooks_config" ] + if [ ! -s "$LIANHUANHUA_CONFIG" ] then - mkdir -p "$ebooks_root/" - printf '{"%s":{"%s":[]}}' "books" "hdlz" > "$ebooks_config" + mkdir -p "$LIANHUANHUA_ROOT/" + printf '{"%s":{"%s":[]}}' "books" "hdlz" > "$LIANHUANHUA_CONFIG" fi SetDelimiters -IFS=$'\003\t' read -r default_save_dir m_source m_id m_title m_cover m_excerpt m_behot_time m_downloaded m_fav < <(JQs flat "$ebooks_config" '' \ +IFS=$'\003\t' read -r default_save_dir m_source m_id m_title m_cover m_excerpt m_behot_time m_downloaded m_fav < <(JQs flat "$LIANHUANHUA_CONFIG" '' \ '(.default // ""| if (.|type == "string") then {} else . end) as $default | (.books.hdlz | if . == "" then {} else . end) as $hdlz | reduce ({save_dir}|keys_unsorted[]) as $key ([]; @@ -676,7 +681,7 @@ reduce ({source,id,title,cover,excerpt,behot_time,downloaded,fav}|keys_unsorted[ inquirer list_input_index "是否重新查询" lookup_options lookup_options_index fi - COOKIE_FILE="$ebooks_root/cookie_hdlz" + COOKIE_FILE="$LIANHUANHUA_ROOT/cookie_hdlz" if [ "$books_total" -eq 0 ] || [ "$lookup_options_index" -eq 1 ] || [ "$lookup_options_index" -eq 3 ] then @@ -826,7 +831,7 @@ reduce ({excerpt,id,image_url,title}|keys_unsorted[]) as $key ([]; json=true jq_path='["books","hdlz"]' - JQ add "$ebooks_config" "[$books]" + JQ add "$LIANHUANHUA_CONFIG" "[$books]" done fi @@ -837,14 +842,14 @@ reduce ({excerpt,id,image_url,title}|keys_unsorted[]) as $key ([]; HdlzGetTouTiaoCookies - last_behot_time=$(date +%s) - for((i=0;i /etc/systemd/system/$nginx_name.service systemctl start "$nginx_name" fi +case $* in + "e") + if [ ! -d "$nginx_prefix" ] + then + Println "$error 尚未安装, 请检查 !\n" + exit 1 + fi + + shopt -s nullglob + nginx_confs=("$nginx_prefix"/conf/sites_available/*) + shopt -u nullglob + + if [ -z "${nginx_confs:-}" ] + then + Println "$error 请先添加域名 !\n" + exit 1 + fi + + echo + inquirer list_input_index "选择配置文件" nginx_confs nginx_confs_index + editor "${nginx_confs[nginx_confs_index]}" + exit 0 + ;; + *) + ;; +esac + Println " nginx 管理面板 ${normal}${red}[v$sh_ver]${normal} ${green}1.${normal} 安装 diff --git a/src/rc b/src/rc new file mode 100644 index 0000000..4c3e7ee --- /dev/null +++ b/src/rc @@ -0,0 +1,101 @@ +Include src/service/get "$@" +Include src/service/base64 "$@" +Include src/service/obscure "$@" +Include src/service/control "$@" +Include src/rclone/config "$@" +Include src/rclone/remote "$@" +Include src/rclone/mount "$@" +Include src/rclone/serve "$@" +Include utils/openssl "$@" +Include utils/htpasswd "$@" + +echo +rclone_options=( '远端' '挂载' '服务' '服务账号' '安装/更新' ) +inquirer list_input_index "请选择" rclone_options rclone_options_index + +case $rclone_options_index in + 0) + echo + rclone_remote_options=( '查看' '添加' '修改' '删除' ) + inquirer list_input_index "选择操作" rclone_remote_options rclone_remote_options_index + + case $rclone_remote_options_index in + 0) RcloneRemoteView + ;; + 1) RcloneRemoteAdd + ;; + 2) RcloneRemoteEdit + ;; + 3) RcloneRemoteDel + ;; + esac + ;; + 1) + echo + rclone_mount_options=( '查看' '添加' '修改' '删除' '执行挂载' '取消挂载' ) + inquirer list_input_index "选择操作" rclone_mount_options rclone_mount_options_index + + case $rclone_mount_options_index in + 0) RcloneMountView + ;; + 1) RcloneMountAdd + ;; + 2) RcloneMountEdit + ;; + 3) RcloneMountDel + ;; + 4) RcloneMountExc + ;; + 5) RcloneMountDeExc + ;; + esac + ;; + 2) + echo + rclone_serve_options=( '查看' '添加' '修改' '删除' '执行服务' '取消服务' ) + inquirer list_input_index "选择操作" rclone_serve_options rclone_serve_options_index + + case $rclone_serve_options_index in + 0) RcloneServeView + ;; + 1) RcloneServeAdd + ;; + 2) RcloneServeEdit + ;; + 3) RcloneServeDel + ;; + 4) RcloneServeExc + ;; + 5) RcloneServeDeExc + ;; + esac + ;; + 3) + echo + rclone_serve_acc_options=( '查看' '添加' '修改' '删除' ) + inquirer list_input_index "选择操作" rclone_serve_acc_options rclone_serve_acc_options_index + + case $rclone_serve_acc_options_index in + 0) RcloneServeAccView + ;; + 1) RcloneServeAccAdd + ;; + 2) RcloneServeAccEdit + ;; + 3) RcloneServeAccDel + ;; + esac + ;; + 4) + if [[ -x $(command -v rclone) ]] + then + rclone selfupdate + else + if [ "$dist" == "mac" ] + then + Println "$tip 可能需要输入密码继续安装" + fi + sudo -v ; curl https://rclone.org/install.sh | grep -v 0555 | sudo bash + fi + ;; +esac diff --git a/src/rclone/config b/src/rclone/config new file mode 100644 index 0000000..7537f62 --- /dev/null +++ b/src/rclone/config @@ -0,0 +1,17 @@ +RcloneConfigUpdate() +{ + if [ -z "${rclone_remotes_count:-}" ] + then + ServiceGet rclone remote + fi + + if [ "$rclone_remotes_count" -gt 0 ] + then + local i rclone_config="" + for((i=0;i "$HOME/.config/rclone/rclone.conf" + fi +} diff --git a/src/rclone/mount b/src/rclone/mount new file mode 100644 index 0000000..ecbb471 --- /dev/null +++ b/src/rclone/mount @@ -0,0 +1,191 @@ +RcloneMountView() +{ + RcloneRemoteView + + echo + inquirer list_input_index "选择远端" rclone_remotes_options rclone_remotes_index + + if [ -z "${rclone_remotes_path[rclone_remotes_index]:-}" ] + then + Println "$error 请先添加挂载\n" + return 1 + fi + + IFS="${delimiters[1]}" read -r -a rclone_remote_paths <<< "${rclone_remotes_path[rclone_remotes_index]}" + IFS="${delimiters[1]}" read -r -a rclone_remote_mount_paths <<< "${rclone_remotes_mount_path[rclone_remotes_index]}" + + rclone_remote_mount_count=${#rclone_remote_paths[@]} + + rclone_remote_mount_options=() + local i rclone_remote_mount_list="" + + for((i=0;i ${rclone_remote_mount_paths[i]} ${green}(已挂载)${normal}") + else + rclone_remote_mount_list="${rclone_remote_mount_list}${green}$((i+1)).${normal} 远端路径: ${rclone_remote_paths[i]}\n挂载点: ${rclone_remote_mount_paths[i]}\n\n" + rclone_remote_mount_options+=("${rclone_remotes_name[rclone_remotes_index]}:${rclone_remote_paths[i]} -> ${rclone_remote_mount_paths[i]}") + fi + done + + Println "$rclone_remote_mount_list" +} + +RcloneMountAdd() +{ + RcloneRemoteView + + echo + inquirer list_input_index "选择远端" rclone_remotes_options rclone_remotes_index + + echo + ExitOnText "输入远端地址" rclone_remote_path + + echo + ExitOnText "输入挂载点" rclone_remote_mount_path + RemoveQuotes rclone_remote_mount_path + + new_mount=$( + $JQ_FILE -n --arg path "$rclone_remote_path" --arg mount_path "$rclone_remote_mount_path" \ + '{ + path: $path, + mount_path: $mount_path + }' + ) + + jq_path='["rclone","remote",'"$rclone_remotes_index"',"mount"]' + JQ add "$SERVICES_CONFIG" "[$new_mount]" + + Println "$info 挂载添加成功\n" +} + +RcloneMountEdit() +{ + RcloneMountView + + inquirer checkbox_input_indices "选择修改的挂载" rclone_remote_mount_options rclone_remote_mount_indices + + rclone_remote_mount_edit_options=( '远端路径' '挂载点' ) + + for rclone_remote_mount_index in "${rclone_remote_mount_indices[@]}" + do + echo "${rclone_remote_mount_options[rclone_remote_mount_index]}" + + echo + inquirer list_input_index "选择修改" rclone_remote_mount_edit_options rclone_remote_mount_edit_options_index + + if [ "$rclone_remote_mount_edit_options_index" == "0" ] + then + echo + inquirer text_input "输入新远端地址" rclone_remote_path "${rclone_remote_paths[rclone_remote_mount_index]}" + + if [ "$rclone_remote_path" != "${rclone_remote_paths[rclone_remote_mount_index]}" ] + then + jq_path='["rclone","remote",'"$rclone_remotes_index"',"mount",'"$rclone_remote_mount_index"',"path"]' + JQ update "$SERVICES_CONFIG" "$rclone_remote_path" + Println "$info 远端路径修改成功\n" + fi + else + echo + inquirer text_input "输入新挂载点" rclone_remote_mount_path "${rclone_remote_mount_paths[rclone_remote_mount_index]}" + if [ "$rclone_remote_mount_path" != "${rclone_remote_mount_paths[rclone_remote_mount_index]}" ] + then + jq_path='["rclone","remote",'"$rclone_remotes_index"',"mount",'"$rclone_remote_mount_index"',"mount_path"]' + JQ update "$SERVICES_CONFIG" "$rclone_remote_mount_path" + Println "$info 挂载点修改成功\n" + fi + fi + done + + return 0 +} + +RcloneMountDel() +{ + RcloneMountView + + inquirer checkbox_input_indices "选择删除的挂载" rclone_remote_mount_options rclone_remote_mount_indices + + local rclone_remote_mount_index_offset=0 + + for rclone_remote_mount_index in "${rclone_remote_mount_indices[@]}" + do + jq_path='["rclone","remote",'"$rclone_remotes_index"',"mount",'"$((rclone_remote_mount_index-rclone_remote_mount_index_offset))"']' + JQ delete "$SERVICES_CONFIG" + ((rclone_remote_mount_index_offset++)) + done + + Println "$info 挂载删除成功\n" +} + +RcloneMountExc() +{ + RcloneMountView + + if [ "$dist" == "mac" ] && [ ! -f /usr/local/lib/libfuse.dylib ] + then + DepInstall macfuse + fi + + inquirer checkbox_input_indices "选择执行的挂载" rclone_remote_mount_options rclone_remote_mount_indices + + RcloneConfigUpdate + + for rclone_remote_mount_index in "${rclone_remote_mount_indices[@]}" + do + rclone_remote_path="${rclone_remote_paths[rclone_remote_mount_index]}" + rclone_remote_mount_path="${rclone_remote_mount_paths[rclone_remote_mount_index]}" + rclone_mount_list="${rclone_remotes_name[rclone_remotes_index]}:$rclone_remote_path -> $rclone_remote_mount_path" + service_name="rclone.mount.${rclone_remotes_name[rclone_remotes_index]}-$((rclone_remote_mount_index+1))" + + if ServiceControl is-active "$service_name" + then + Println "$error $rclone_mount_list 已挂载\n" + continue + fi + + service_commands=( $(command -v rclone) mount ${rclone_remotes_name[rclone_remotes_index]}:$rclone_remote_path "$rclone_remote_mount_path" --allow-non-empty ) + + if ! err_msg=$(ServiceControl start "$service_name" service_commands) + then + Println "$error 挂载 $rclone_mount_list 失败, $err_msg\n" + continue + fi + + Println "$info 挂载 $rclone_mount_list 成功\n" + done +} + +RcloneMountDeExc() +{ + RcloneMountView + + inquirer checkbox_input_indices "选择取消的挂载" rclone_remote_mount_options rclone_remote_mount_indices + + for rclone_remote_mount_index in "${rclone_remote_mount_indices[@]}" + do + rclone_remote_path="${rclone_remote_paths[rclone_remote_mount_index]}" + rclone_remote_mount_path="${rclone_remote_mount_paths[rclone_remote_mount_index]}" + rclone_mount_list="${rclone_remotes_name[rclone_remotes_index]}:$rclone_remote_path -> $rclone_remote_mount_path" + service_name="rclone.mount.${rclone_remotes_name[rclone_remotes_index]}-$((rclone_remote_mount_index+1))" + + if ! ServiceControl is-active "$service_name" + then + Println "$error $rclone_mount_list 未挂载\n" + continue + fi + + Println "$info 正在取消挂载 $rclone_mount_list" + + if ! err_msg=$(ServiceControl stop "$service_name") + then + Println "$error 取消挂载 $rclone_mount_list 失败, $err_msg\n" + continue + fi + + Println "$info 取消挂载 $rclone_mount_list 成功\n" + done +} diff --git a/src/rclone/remote b/src/rclone/remote new file mode 100644 index 0000000..c089876 --- /dev/null +++ b/src/rclone/remote @@ -0,0 +1,188 @@ +RcloneRemoteView() +{ + ServiceGet rclone remote + + if [ "$rclone_remotes_count" -eq 0 ] + then + Println "$error 请先添加 rclone 远端\n" + return 1 + fi + + rclone_remotes=() + rclone_remotes_options=() + + local i rclone_remotes_list="" rclone_remote_list="" + + for((i=0;i ${rclone_serve_addrs[*]}") + rclone_serves_list="${rclone_serves_list}${green}$((i+1)).${normal} 服务: ${rclone_serves_remote[i]}\n监听: ${rclone_serve_addrs[*]}\n\n" + done + + Println "$rclone_serves_list" +} + +RcloneServeAddRemoteValidator() +{ + if [ "$1" == "$i18n_cancel" ] || [ "${1:0:1}" == "/" ] + then + return 0 + fi + + return 1 +} + +RcloneServeAddAddrValidator() +{ + if [ "${1:0:1}" == "/" ] || [ "${1:0:8}" == "unix:///" ] || [[ "$1" =~ ^[0-9.]*:[0-9]+ ]] + then + return 0 + fi + + return 1 +} + +RcloneServeAdd() +{ + ServiceGet rclone serve + + rclone_serve_options=( '本地' '远端' ) + echo + inquirer list_input_index "选择服务内容" rclone_serve_options rclone_serve_options_index + + if [ "$rclone_serve_options_index" -eq 0 ] + then + echo + ExitOnText "输入本地服务路径" rclone_serve_remote RcloneServeAddRemoteValidator + else + RcloneRemoteView + echo + inquirer list_input_index "选择服务的远端" rclone_remotes_options rclone_remotes_index + rclone_serve_remote="${rclone_remotes_name[rclone_remotes_index]}" + fi + + rclone_serve_protocol_options=( webdav ) + echo + inquirer list_input "选择服务协议" rclone_serve_protocol_options rclone_serve_protocol + + rclone_serve_addrs=() + + while true + do + Println "$tip 比如 1.2.3.4:8000, :8080, :0(自动检测端口), unix:///path/to/socket. 如果使用 socket 或绝对路径, 连接验证将不可用" + inquirer text_input "输入监听地址 IP:PORT/socket/绝对路径" rclone_serve_addr :0 RcloneServeAddAddrValidator "地址格式错误" + + rclone_serve_addrs+=("$rclone_serve_addr") + + echo + inquirer list_input_index "是否继续添加监听地址" ny_options ny_index + + if [ "$ny_index" -eq 0 ] + then + break + fi + done + + while true + do + rclone_serve_htpasswd=$(RandStr) + if [ "$rclone_serves_count" -gt 0 ] && EleInArray "$rclone_serve_htpasswd" rclone_serves_htpasswd + then + continue + fi + break + done + + new_serve=$( + $JQ_FILE -n --arg remote "$rclone_serve_remote" --arg protocol "$rclone_serve_protocol" \ + --argjson addr "$(ToJsonArray rclone_serve_addrs)" --arg htpasswd "$rclone_serve_htpasswd" \ + '{ + remote: $remote, + protocol: $protocol, + addr: $addr, + htpasswd: $htpasswd + }' + ) + + jq_path='["rclone","serve"]' + JQ add "$SERVICES_CONFIG" "[$new_serve]" + + Println "$info 服务添加成功\n" +} + +RcloneServeEdit() +{ + RcloneServeView + + inquirer checkbox_input_indices "选择修改的服务" rclone_serves_options rclone_serves_indices + + rclone_serve_edit_options=( '服务内容' '监听地址' ) + rclone_serve_options=( '本地' '远端' ) + rclone_serve_addr_options=( '修改' '删除' ) + + for rclone_serves_index in "${rclone_serves_indices[@]}" + do + echo "${rclone_serves_options[rclone_serves_index]}" + + echo + inquirer checkbox_input_indices "选择修改" rclone_serve_edit_options rclone_serve_edit_options_indices + + for rclone_serve_edit_options_index in "${rclone_serve_edit_options_indices[@]}" + do + case $rclone_serve_edit_options_index in + 0) + echo + inquirer list_input_index "选择服务内容" rclone_serve_options rclone_serve_options_index + + if [ "$rclone_serve_options_index" -eq 0 ] + then + echo + ExitOnText "输入本地服务路径" rclone_serve_remote RcloneServeAddRemoteValidator + else + RcloneRemoteView + echo + inquirer list_input_index "选择服务的远端" rclone_remotes_options rclone_remotes_index + rclone_serve_remote="${rclone_remotes_name[rclone_remotes_index]}" + fi + + if [ "$rclone_serve_remote" != "${rclone_serves_remote[rclone_serves_index]}" ] + then + jq_path='["rclone","serve",'"$rclone_serves_index"',"remote"]' + JQ update "$SERVICES_CONFIG" "$rclone_serve_remote" + Println "$info 服务内容修改成功\n" + fi + ;; + 1) + rclone_serve_addr="${rclone_serves_addr[i]}" + IFS="${delimiters[0]}" read -r -a rclone_serve_addrs <<< "$rclone_serve_addr" + echo + inquirer checkbox_input_indices "选择监听地址" rclone_serve_addrs rclone_serve_addrs_indices + local rclone_serve_addrs_index_offset=0 + for rclone_serve_addrs_index in "${rclone_serve_addrs_indices[@]}" + do + echo + inquirer list_input_index "选择操作 ${rclone_serve_addrs[rclone_serve_addrs_index]}" rclone_serve_addr_options rclone_serve_addr_options_index + if [ "$rclone_serve_addr_options_index" -eq 0 ] + then + Println "$tip 比如 1.2.3.4:8000, :8080, :0(自动检测端口), unix:///path/to/socket. 如果使用 socket 或绝对路径, 连接验证将不可用" + inquirer text_input "输入新监听地址 IP:PORT/socket/绝对路径" rclone_serve_addr ${rclone_serve_addrs[rclone_serve_addrs_index]} RcloneServeAddAddrValidator "地址格式错误" + if [ "$rclone_serve_addr" != "${rclone_serve_addrs[rclone_serve_addrs_index]}" ] + then + jq_path='["rclone","serve",'"$rclone_serves_index"',"addr",'"$((rclone_serve_addrs_index-rclone_serve_addrs_index_offset))"']' + JQ update "$SERVICES_CONFIG" "$rclone_serve_addr" + Println "$info 监听地址修改成功\n" + fi + else + jq_path='["rclone","serve",'"$rclone_serves_index"',"addr",'"$((rclone_serve_addrs_index-rclone_serve_addrs_index_offset))"']' + JQ delete "$SERVICES_CONFIG" "$rclone_serve_addr" + ((rclone_serve_addrs_index_offset++)) + Println "$info 监听地址删除成功\n" + fi + done + ;; + esac + done + done + + return 0 +} + +RcloneServeDel() +{ + RcloneServeView + + inquirer checkbox_input_indices "选择删除的服务" rclone_serves_options rclone_serves_indices + + local rclone_serves_index_offset=0 + + for rclone_serves_index in "${rclone_serves_indices[@]}" + do + jq_path='["rclone","serve",'"$((rclone_serves_index-rclone_serves_index_offset))"']' + JQ delete "$SERVICES_CONFIG" + ((rclone_serves_index_offset++)) + done + + Println "$info 服务删除成功\n" +} + +RcloneServeExc() +{ + RcloneServeView + + inquirer checkbox_input_indices "选择执行的服务" rclone_serves_options rclone_serves_indices + + RcloneConfigUpdate + + for rclone_serves_index in "${rclone_serves_indices[@]}" + do + service_name="rclone.serve-$((rclone_serves_index+1))" + rclone_serve_addr="${rclone_serves_addr[rclone_serves_index]}" + IFS="${delimiters[0]}" read -r -a rclone_serve_addrs <<< "$rclone_serve_addr" + rclone_serve_list="${rclone_serves_remote[rclone_serves_index]} -> ${rclone_serve_addrs[*]}" + + if ServiceControl is-active "$service_name" + then + Println "$error $rclone_serve_list 已运行\n" + continue + fi + + rclone_serve_accs_count=0 + + if [ -n "${rclone_serves_user[rclone_serves_index]:-}" ] + then + IFS="${delimiters[1]}" read -r -a rclone_serve_users <<< "${rclone_serves_user[rclone_serves_index]}" + IFS="${delimiters[1]}" read -r -a rclone_serve_passwords <<< "${rclone_serves_pass[rclone_serves_index]}" + + rclone_serve_accs_count=${#rclone_serve_users[@]} + fi + + service_commands=( $(command -v rclone) serve ${rclone_serves_protocol[rclone_serves_index]} "${rclone_serves_remote[rclone_serves_index]}" ) + rclone_serve_auth=false + + for rclone_serve_addr in "${rclone_serve_addrs[@]}" + do + service_commands+=( --addr "$rclone_serve_addr" ) + + if [ "$rclone_serve_auth" = false ] && [[ "$rclone_serve_addr" =~ ^[0-9.]*:[0-9]+ ]] + then + rclone_serve_auth=true + fi + done + + if [ "$rclone_serve_auth" = true ] && [ "$rclone_serve_accs_count" -gt 0 ] + then + if [ ! -f "$RCLONE_ROOT/serve/htpasswd/${rclone_serves_htpasswd[rclone_serves_index]}" ] + then + mkdir -p "$RCLONE_ROOT/serve/htpasswd" + htpasswd -Bbc "$RCLONE_ROOT/serve/htpasswd/${rclone_serves_htpasswd[rclone_serves_index]}" "${rclone_serve_users[0]}" "${rclone_serve_passwords[0]}" + for((i=1;i /dev/null | grep -q "pid ="; } + then + return 1 + fi + else + if ! EleInArray "$service_label" exceptions + then + service_label="aios.$service_label" + fi + service_file="/etc/systemd/system/${service_label}.service" + if [ ! -f "$service_file" ] || ! systemctl is-active --quiet "$service_label" + then + return 1 + fi + fi + return 0 +} + +ServiceControlStart() +{ + if ServiceControlIsActive "$1" + then + echo "服务已启动" + return 1 + fi + + local var=("$2"[@]) + local args=("${!var}") arg arr + + if [[ ! -x "${args[0]}" ]] + then + echo "${args[0]} 不存在" + return 1 + fi + + if [ "$dist" == "mac" ] + then + if [ ! -f "$service_file" ] + then + arr="" + for arg in "${args[@]}" + do + arr="$arr\n $arg" + done + arr="$arr\n " + arr=$(echo -e "$arr") +echo ' + + + + Label + '"$service_label"' + ProgramArguments + '"$arr"' + RunAtLoad + + KeepAlive + + +' > "$service_file" + fi + launchctl load "$service_file" + else + if [ ! -f "$service_file" ] + then + echo "[Unit] +Description=${service_label} +After=syslog.target network-online.target nss-lookup.target +Wants=network-online.target + +[Service] +ExecStart=${args[*]} +WorkingDirectory=${args[0]%/*}/ +StartLimitInterval=60s +StartLimitBurst=5 +RestartSec=5 +Restart=on-failure + +[Install] +WantedBy=multi-user.target" > "$service_file" + fi + systemctl daemon-reload + systemctl enable "${service_label}.service" + systemctl start "${service_label}.service" + fi +} + +ServiceControlStop() +{ + if ! ServiceControlIsActive "$1" + then + echo "服务未启动" + return 1 + fi + + if [ "$dist" == "mac" ] + then + launchctl unload "$service_file" + else + systemctl stop "${service_label}.service" + fi +} + +ServiceControlRestart() +{ + if ServiceControlIsActive "$1" + then + ServiceControlStop + fi + + ServiceControlStart +} + +ServiceControlDisable() +{ + if ServiceControlIsActive "$1" + then + ServiceControlStop + fi + + if [ "$dist" == "mac" ] + then + rm -f "$service_file" + else + systemctl disable "${service_label}".service --now > /dev/null 2> /dev/null || true + rm -f /etc/systemd/system/"${service_label}".service + rm -f /lib/systemd/system/"${service_label}".service + rm -f /etc/init.d/"${service_label}" + fi +} + +ServiceControl() +{ + local cmd=$1 + shift + case $cmd in + is-active) + ServiceControlIsActive "$@" + ;; + start) + ServiceControlStart "$@" + ;; + stop) + ServiceControlStop "$@" + ;; + restart) + ServiceControlRestart "$@" + ;; + disable) + ServiceControlDisable "$@" + ;; + esac + return $? +} diff --git a/src/service/get b/src/service/get new file mode 100644 index 0000000..951e500 --- /dev/null +++ b/src/service/get @@ -0,0 +1,180 @@ +ServiceGet() +{ + JQInstall + + local service_id=$1 + + if [ ! -s "$SERVICES_CONFIG" ] + then + mkdir -p "$SERVICES_ROOT" + if [ -f "$IPTV_ROOT"/services.json ] + then + mv "$IPTV_ROOT"/services.json "$SERVICES_CONFIG" + else + printf '{"%s":{"%s":[]}}' "4gtv" "accounts" > "$SERVICES_CONFIG" + fi + fi + + SetDelimiters + + case $service_id in + 4gtv) + IFS=$'\003\t' read -r d_4gtv_proxy _4gtv_acc_email _4gtv_acc_pass _4gtv_acc_token < <(JQs flat "$SERVICES_CONFIG" '' ' + [(."'"$service_id"'".proxy // "") + "\u0003"] + ((."'"$service_id"'".accounts | if (.|type == "string") then {} else . end) as $accounts | + reduce ({email,password,token}|keys_unsorted[]) as $key ([]; + $accounts[$key] as $val | if $val then + . + [$val + "\u0002\u0003"] + else + . + ["\u0003"] + end + ))|@tsv' "${delimiters[@]}") + + IFS="${delimiters[1]}" read -r -a _4gtv_accs_email <<< "$_4gtv_acc_email" + IFS="${delimiters[1]}" read -r -a _4gtv_accs_pass <<< "$_4gtv_acc_pass" + IFS="${delimiters[1]}" read -r -a _4gtv_accs_token <<< "$_4gtv_acc_token" + + _4gtv_accs_count=${#_4gtv_accs_email[@]} + ;; + alist) + IFS=$'\004\t' read -r alist_name alist_url alist_acc_username \ + alist_acc_password alist_acc_token < <(JQs flat "$SERVICES_CONFIG" '' ' + (."'"$service_id"'" | if (.|type == "string") then {} else . end) as $alist | + ($alist.accs // {} | if (.|type) == "string" then {} else . end) as $accs | + reduce ({name,url}|keys_unsorted[]) as $key ([]; + $alist[$key] as $val | if $val then + . + [$val + "\u0002\u0004"] + else + . + ["\u0004"] + end + ) + reduce ({username,password,token}|keys_unsorted[]) as $key ([]; + $accs[$key] as $val | if $val then + . + [$val + "\u0003\u0004"] + else + . + ["\u0004"] + end + )|@tsv' "${delimiters[@]}") + + IFS="${delimiters[1]}" read -r -a alists_name <<< "$alist_name" + IFS="${delimiters[1]}" read -r -a alists_url <<< "$alist_url" + IFS="${delimiters[2]}" read -r -a alists_acc_username <<< "$alist_acc_username" + IFS="${delimiters[2]}" read -r -a alists_acc_password <<< "$alist_acc_password" + IFS="${delimiters[2]}" read -r -a alists_acc_token <<< "$alist_acc_token" + + alists_count=${#alists_name[@]} + ;; + rclone) + if [ "${2:-}" == "serve" ] + then + IFS=$'\004\t' read -r m_serves_remote m_serves_protocol m_serves_addr m_serves_htpasswd \ + m_serves_user m_serves_pass < <(JQs flat "$SERVICES_CONFIG" '.[0].rclone.serve' ' + (if (.|type == "string") then {} else . end) as $serve | + ($serve.accs // {} | if (.|type) == "string" then {} else . end) as $accs | + reduce ({remote,protocol,addr,htpasswd}|keys_unsorted[]) as $key ([]; + $serve[$key] as $val | if $val then + . + [$val + "\u0002\u0004"] + else + . + ["\u0004"] + end + ) + reduce ({user,pass}|keys_unsorted[]) as $key ([]; + $accs[$key] as $val | if $val then + . + [$val + "\u0003\u0004"] + else + . + ["\u0004"] + end + )|@tsv' "${delimiters[@]}") + + IFS="${delimiters[1]}" read -r -a rclone_serves_remote <<< "$m_serves_remote" + IFS="${delimiters[1]}" read -r -a rclone_serves_protocol <<< "$m_serves_protocol" + IFS="${delimiters[1]}" read -r -a rclone_serves_addr <<< "$m_serves_addr" + IFS="${delimiters[1]}" read -r -a rclone_serves_htpasswd <<< "$m_serves_htpasswd" + IFS="${delimiters[2]}" read -r -a rclone_serves_user <<< "$m_serves_user" + IFS="${delimiters[2]}" read -r -a rclone_serves_pass <<< "$m_serves_pass" + + rclone_serves_count=${#rclone_serves_remote[@]} + return 0 + fi + IFS=$'\004\t' read -r m_remotes_name m_remotes_type m_remotes_url \ + m_remotes_vendor m_remotes_user m_remotes_pass m_remotes_path m_remotes_mount_path < <(JQs flat "$SERVICES_CONFIG" '.[0].rclone.remote' ' + (if (.|type == "string") then {} else . end) as $remote | + ($remote.mount // {} | if (.|type) == "string" then {} else . end) as $mount | + reduce ({name,type,url,vendor,user,pass}|keys_unsorted[]) as $key ([]; + $remote[$key] as $val | if $val then + . + [$val + "\u0002\u0004"] + else + . + ["\u0004"] + end + ) + reduce ({path,mount_path}|keys_unsorted[]) as $key ([]; + $mount[$key] as $val | if $val then + . + [$val + "\u0003\u0004"] + else + . + ["\u0004"] + end + )|@tsv' "${delimiters[@]}") + + IFS="${delimiters[1]}" read -r -a rclone_remotes_name <<< "$m_remotes_name" + IFS="${delimiters[1]}" read -r -a rclone_remotes_type <<< "$m_remotes_type" + IFS="${delimiters[1]}" read -r -a rclone_remotes_url <<< "$m_remotes_url" + IFS="${delimiters[1]}" read -r -a rclone_remotes_vendor <<< "$m_remotes_vendor" + IFS="${delimiters[1]}" read -r -a rclone_remotes_user <<< "$m_remotes_user" + IFS="${delimiters[1]}" read -r -a rclone_remotes_pass <<< "$m_remotes_pass" + IFS="${delimiters[2]}" read -r -a rclone_remotes_path <<< "$m_remotes_path" + IFS="${delimiters[2]}" read -r -a rclone_remotes_mount_path <<< "$m_remotes_mount_path" + + rclone_remotes_count=${#rclone_remotes_name[@]} + ;; + kcc) + IFS="${delimiters[2]}"$'\t' read -r kcc_format kcc_process kcc_args kcc_output \ + m_source < <($JQ_FILE -r --arg delimiter "${delimiters[1]}" --arg delimiter2 "${delimiters[2]}" ' + (.kcc // {}) as $kcc | + reduce ({format,process,args,output,source}|keys_unsorted[]) as $key ([]; + $kcc[$key] as $val | ($val | type) as $type | if $val then + if ($type == "array") then + . + [($val|join($delimiter)) + $delimiter2] + else + . + [($val|tostring) + $delimiter2] + end + else + . + [$delimiter2] + end + )|@tsv' "$SERVICES_CONFIG") + + IFS="${delimiters[1]}" read -r -a kcc_sources <<< "$m_source" + ;; + *) + IFS=$'\003\t' read -r m_user_name m_phone_number m_password m_access_token m_device_no m_device_id m_refresh < <(JQs flat "$SERVICES_CONFIG" '' ' + (."'"$service_id"'".accounts | if (.|type == "string") then {} else . end) as $accounts | + reduce ({user_name,phone_number,password,access_token,device_no,device_id,refresh}|keys_unsorted[]) as $key ([]; + $accounts[$key] as $val | if $val then + . + [$val + "\u0002\u0003"] + else + . + ["\u0003"] + end + )|@tsv' "${delimiters[@]}") + + if [ -z "$m_user_name" ] + then + ts_accs_count=0 + return 0 + fi + + IFS="${delimiters[1]}" read -r -a ts_accs_user_name <<< "$m_user_name" + + if [ -z "$m_phone_number" ] + then + ts_accs_phone_number=("${ts_accs_user_name[@]//*/}") + else + IFS="${delimiters[1]}" read -r -a ts_accs_phone_number <<< "$m_phone_number" + fi + + IFS="${delimiters[1]}" read -r -a ts_accs_password <<< "$m_password" + IFS="${delimiters[1]}" read -r -a ts_accs_access_token <<< "$m_access_token" + IFS="${delimiters[1]}" read -r -a ts_accs_device_no <<< "$m_device_no" + IFS="${delimiters[1]}" read -r -a ts_accs_device_id <<< "$m_device_id" + IFS="${delimiters[1]}" read -r -a ts_accs_refresh <<< "$m_refresh" + + ts_accs_count=${#ts_accs_user_name[@]} + ;; + esac + + return 0 +} diff --git a/src/service/obscure b/src/service/obscure new file mode 100644 index 0000000..46feabf --- /dev/null +++ b/src/service/obscure @@ -0,0 +1,25 @@ +Obscure() +{ + OpensslInstall + + local hexkey="9c935b48730a554d6bfd7c63c886a92bd390198eb8128afbf4de162b8b95f638" + local hexiv=$(openssl rand -hex 16) + local buff=$(echo "$1" | openssl enc -aes-256-ctr -K "$hexkey" -iv "$hexiv") + hexiv=$(echo -n "$hexiv" | xxd -r -p) + local encrypted=$(echo -n "$hexiv$buff" | Base64urlEncode) + + echo "$encrypted" +} + +Deobscure() +{ + OpensslInstall + + local hexkey="9c935b48730a554d6bfd7c63c886a92bd390198eb8128afbf4de162b8b95f638" + local decoded=$(echo -n "$1" | Base64urlDecode) + local hexiv=$(echo -n "$decoded" | head -c 16 | hexdump -v -e '/1 "%02x"') # xxd -p + local buff=$(echo -n "$decoded" | tail -c +17) + local decrypted=$(echo -n "$buff" | openssl enc -aes-256-ctr -d -K "$hexkey" -iv "$hexiv" -nopad) + + echo "$decrypted" +} diff --git a/src/tv b/src/tv index 9466134..8c3c5e8 100644 --- a/src/tv +++ b/src/tv @@ -1,6 +1,3 @@ -JQ_FILE="$IPTV_ROOT"/jq -FFMPEG_ROOT="$IPTV_ROOT" - Include utils/python "$@" Include utils/ffmpeg "$@" @@ -99,7 +96,7 @@ Include src/iptv/menu_monitor "$@" Include src/iptv/menu_edit_default "$@" -Include src/iptv/get_service "$@" +Include src/service/get "$@" Include src/_4gtv/set_acc "$@" @@ -541,7 +538,7 @@ then curl) Include src/iptv/cmd_curl "$@" ;; - b) + b|backup) Include src/iptv/cmd_backup "$@" ;; *) diff --git a/src/v2 b/src/v2 index 9022546..70c4fc4 100644 --- a/src/v2 +++ b/src/v2 @@ -1,318 +1,54 @@ Include utils/imagemagick "$@" - Include utils/imgcat "$@" - Include src/v2ray/get_free_tag "$@" - Include src/v2ray/view_staus "$@" - Include src/v2ray/set_bound "$@" - Include src/v2ray/add_inbound "$@" - Include src/v2ray/get_inbounds "$@" - Include src/v2ray/list_inbounds "$@" - Include src/v2ray/select_inbound "$@" - Include src/v2ray/select_account "$@" - Include src/v2ray/delete_inbound "$@" - Include src/v2ray/add_inbound_account "$@" - Include src/v2ray/list_inbound_accounts "$@" - Include src/v2ray/list_inbound_share "$@" - Include src/v2ray/delete_inbound_account "$@" - Include src/v2ray/add_outbound "$@" - Include src/v2ray/get_outbounds "$@" - Include src/v2ray/list_outbounds "$@" - Include src/v2ray/select_outbound "$@" - Include src/v2ray/delete_outbound "$@" - Include src/v2ray/add_outbound_account "$@" - Include src/v2ray/list_outbound_accounts "$@" - Include src/v2ray/delete_outbound_account "$@" - Include src/v2ray/get_routing "$@" - Include src/v2ray/list_routing "$@" - Include src/v2ray/set_routing "$@" - Include src/v2ray/get_policy "$@" - Include src/v2ray/list_policy "$@" - Include src/v2ray/set_policy "$@" - Include src/v2ray/get_reverse "$@" - Include src/v2ray/list_reverse "$@" - Include src/v2ray/set_reverse "$@" - Include src/v2ray/get_dns "$@" - Include src/v2ray/list_dns "$@" - Include src/v2ray/set_dns "$@" - Include src/v2ray/get_stats "$@" - Include src/v2ray/get_traffic "$@" - Include src/v2ray/list_stats "$@" - Include src/v2ray/reset_stats "$@" - Include src/v2ray/list_inbound_domains "$@" - Include src/v2ray/update_cert "$@" - Include src/v2ray/list_nginx_domains "$@" - Include src/v2ray/select_nginx_domain "$@" - Include src/v2ray/select_nginx_server "$@" - Include src/v2ray/update_nginx_cert "$@" - Include src/v2ray/add_nginx_proxy "$@" - Include src/v2ray/select_nginx_proxy "$@" - Include src/v2ray/list_nginx_domain "$@" - Include src/v2ray/config_domain "$@" - -V2rayInstall() -{ - if [ -s "$V2_CONFIG" ] - then - Println "$error $v2ray_name 已存在...\n" - ExitOnList n "`gettext \"是否覆盖原安装\"`" - fi - - DepsCheck - JQInstall - - if ! grep -q "$v2ray_name:" < "/etc/passwd" - then - if grep -q '\--group ' < <(adduser --help) - then - adduser $v2ray_name --system --group --no-create-home > /dev/null - else - adduser $v2ray_name --system --no-create-home > /dev/null - fi - usermod -s /usr/sbin/nologin $v2ray_name - fi - - Println "$info 安装 $v2ray_name..." - - if [ "$v2ray_name" == "v2ray" ] - then - { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ - | sed "s+nobody+$v2ray_name+g" \ - | sed "s+ 'sha1'++g" \ - | sed "s+ 'sha256'++g" \ - | sed "s+ 'sha512'++g" \ - | sed "s+https://api.github.com/repos/v2fly/v2ray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ - | sed "s+https://github.com/v2fly/v2ray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash - else - { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ - | sed "s+nobody+$v2ray_name+g" \ - | sed "s+ 'sha1'++g" \ - | sed "s+ 'sha256'++g" \ - | sed "s+ 'sha512'++g" \ - | sed "s+https://api.github.com/repos/XTLS/Xray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ - | sed "s+https://github.com/XTLS/Xray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash - fi - - sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name.service" - sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name@.service" - - mkdir -p /var/log/$v2ray_name/ - [ ! -e "/var/log/$v2ray_name/error.log" ] && printf '%s' "" > /var/log/$v2ray_name/error.log - chown -R $v2ray_name:$v2ray_name /var/log/$v2ray_name/ - chown -R $v2ray_name:$v2ray_name /usr/local/share/$v2ray_name/ - - V2rayConfigUpdate - - systemctl daemon-reload - systemctl enable $v2ray_name - systemctl start $v2ray_name - - Println "$info $v2ray_name 安装完成\n" -} - -V2rayUpdate() -{ - DepsCheck - JQInstall - ShFileUpdate $v2ray_name - - if ! grep -q "$v2ray_name:" < "/etc/passwd" - then - if grep -q '\--group ' < <(adduser --help) - then - adduser $v2ray_name --system --group --no-create-home > /dev/null - else - adduser $v2ray_name --system --no-create-home > /dev/null - fi - usermod -s /usr/sbin/nologin $v2ray_name - fi - - if [ "$v2ray_name" == "v2ray" ] - then - { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ - | sed "s+nobody+$v2ray_name+g" \ - | sed "s+ 'sha1'++g" \ - | sed "s+ 'sha256'++g" \ - | sed "s+ 'sha512'++g" \ - | sed "s+https://api.github.com/repos/v2fly/v2ray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ - | sed "s+https://github.com/v2fly/v2ray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash - else - { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ - | sed "s+nobody+$v2ray_name+g" \ - | sed "s+ 'sha1'++g" \ - | sed "s+ 'sha256'++g" \ - | sed "s+ 'sha512'++g" \ - | sed "s+https://api.github.com/repos/XTLS/Xray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ - | sed "s+https://github.com/XTLS/Xray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash - fi - - sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name.service" - sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name@.service" - - mkdir -p /var/log/$v2ray_name/ - [ ! -e "/var/log/$v2ray_name/error.log" ] && printf '%s' "" > /var/log/$v2ray_name/error.log - chown -R $v2ray_name:$v2ray_name /var/log/$v2ray_name/ - chown -R $v2ray_name:$v2ray_name /usr/local/share/$v2ray_name/ - - V2rayConfigUpdate - - systemctl daemon-reload - systemctl restart $v2ray_name - - Println "$info $v2ray_name 升级完成\n" -} - -V2rayConfigUpdate() -{ - if [ ! -e "$V2_CONFIG" ] - then - Println "$error $v2ray_name 未安装...\n" - exit 1 - fi - - if ! outbounds=$($JQ_FILE '.outbounds' "$V2_CONFIG" 2> /dev/null) || [ "$outbounds" == "null" ] - then - if grep -q '"path": "' < "$V2_CONFIG" - then - while IFS= read -r line - do - if [[ $line == *"path"* ]] - then - path=${line#*: \"} - path=${path%\"*} - break - fi - done < "$V2_CONFIG" - fi - - printf -v update_date '%(%m-%d-%H:%M:%S)T' -1 - cp -f "$V2_CONFIG" "${V2_CONFIG}_$update_date" - while IFS= read -r line - do - if [[ $line == *"port"* ]] - then - port=${line#*: } - port=${port%,*} - elif [[ $line == *"id"* ]] - then - id=${line#*: \"} - id=${id%\"*} - break - fi - done < "$V2_CONFIG" - - $JQ_FILE -n --arg port "${port:-$(GetFreePort)}" --arg id "${id:-$($V2CTL_FILE uuid)}" --arg path "${path:-/$(RandStr)}" \ - --arg error "/var/log/$v2ray_name/error.log" \ - '{ - "log": { - "access": "none", - "error": $error, - "loglevel": "error" - }, - "inbounds": [ - { - "listen": "127.0.0.1", - "port": $port | tonumber, - "protocol": "vmess", - "settings": { - "clients": [ - { - "id": $id, - "level": 0, - "alterId": 64, - "email": "name@localhost" - } - ] - }, - "streamSettings": { - "network": "ws", - "wsSettings": { - "path": $path - } - }, - "tag": "nginx-1" - } - ], - "outbounds": [ - { - "protocol": "freedom", - "tag": "direct" - }, - { - "protocol": "blackhole", - "tag": "block" - } - ], - "policy": { - "levels": { - "0": { - "handshake": 4, - "connIdle": 300, - "uplinkOnly": 2, - "downlinkOnly": 5, - "statsUserUplink": false, - "statsUserDownlink": false, - "bufferSize": 512 - } - }, - "system": { - "statsInboundUplink": false, - "statsInboundDownlink": false, - "statsOutboundUplink": false, - "statsOutboundDownlink": false - } - } - }' > "$V2_CONFIG" - - Println "$info $v2ray_name 配置文件已更新\n" - fi -} +Include src/v2ray/install "$@" +Include src/service/control "$@" ShFileCheck @@ -322,11 +58,8 @@ tls_name="TLS" if [ -d /etc/v2ray/ ] && [ ! -d /usr/local/etc/v2ray/ ] then - systemctl disable v2ray --now > /dev/null 2> /dev/null || true + ServiceControlDisable disable v2ray rm -rf /usr/bin/v2ray/ - rm -f /etc/systemd/system/v2ray.service - rm -f /lib/systemd/system/v2ray.service - rm -f /etc/init.d/v2ray mv /etc/v2ray/ /usr/local/etc/ if ! grep -q "v2ray:" < "/etc/passwd" then @@ -343,8 +76,6 @@ then chown -R v2ray:v2ray /var/log/v2ray/ chown -R v2ray:v2ray /usr/local/share/v2ray/ V2rayUpdate - systemctl enable v2ray - systemctl start v2ray fi Include src/v2ray/menu "$@" diff --git a/src/v2ray/install b/src/v2ray/install new file mode 100644 index 0000000..a8ed916 --- /dev/null +++ b/src/v2ray/install @@ -0,0 +1,214 @@ +V2rayInstall() +{ + if [ -s "$V2_CONFIG" ] + then + Println "$error $v2ray_name 已存在...\n" + ExitOnList n "`gettext \"是否覆盖原安装\"`" + fi + + DepsCheck + JQInstall + + if ! grep -q "$v2ray_name:" < "/etc/passwd" + then + if grep -q '\--group ' < <(adduser --help) + then + adduser $v2ray_name --system --group --no-create-home > /dev/null + else + adduser $v2ray_name --system --no-create-home > /dev/null + fi + usermod -s /usr/sbin/nologin $v2ray_name + fi + + Println "$info 安装 $v2ray_name..." + + if [ "$v2ray_name" == "v2ray" ] + then + { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ + | sed "s+nobody+$v2ray_name+g" \ + | sed "s+ 'sha1'++g" \ + | sed "s+ 'sha256'++g" \ + | sed "s+ 'sha512'++g" \ + | sed "s+https://api.github.com/repos/v2fly/v2ray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ + | sed "s+https://github.com/v2fly/v2ray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash + else + { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ + | sed "s+nobody+$v2ray_name+g" \ + | sed "s+ 'sha1'++g" \ + | sed "s+ 'sha256'++g" \ + | sed "s+ 'sha512'++g" \ + | sed "s+https://api.github.com/repos/XTLS/Xray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ + | sed "s+https://github.com/XTLS/Xray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash + fi + + sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name.service" + sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name@.service" + + mkdir -p /var/log/$v2ray_name/ + [ ! -e "/var/log/$v2ray_name/error.log" ] && printf '%s' "" > /var/log/$v2ray_name/error.log + chown -R $v2ray_name:$v2ray_name /var/log/$v2ray_name/ + chown -R $v2ray_name:$v2ray_name /usr/local/share/$v2ray_name/ + + V2rayConfigUpdate + + ServiceControl start $v2ray_name + + Println "$info $v2ray_name 安装完成\n" +} + +V2rayUpdate() +{ + DepsCheck + JQInstall + ShFileUpdate $v2ray_name + + if ! grep -q "$v2ray_name:" < "/etc/passwd" + then + if grep -q '\--group ' < <(adduser --help) + then + adduser $v2ray_name --system --group --no-create-home > /dev/null + else + adduser $v2ray_name --system --no-create-home > /dev/null + fi + usermod -s /usr/sbin/nologin $v2ray_name + fi + + if [ "$v2ray_name" == "v2ray" ] + then + { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ + | sed "s+nobody+$v2ray_name+g" \ + | sed "s+ 'sha1'++g" \ + | sed "s+ 'sha256'++g" \ + | sed "s+ 'sha512'++g" \ + | sed "s+https://api.github.com/repos/v2fly/v2ray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ + | sed "s+https://github.com/v2fly/v2ray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash + else + { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ + | sed "s+nobody+$v2ray_name+g" \ + | sed "s+ 'sha1'++g" \ + | sed "s+ 'sha256'++g" \ + | sed "s+ 'sha512'++g" \ + | sed "s+https://api.github.com/repos/XTLS/Xray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ + | sed "s+https://github.com/XTLS/Xray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash + fi + + sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name.service" + sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name@.service" + + mkdir -p /var/log/$v2ray_name/ + [ ! -e "/var/log/$v2ray_name/error.log" ] && printf '%s' "" > /var/log/$v2ray_name/error.log + chown -R $v2ray_name:$v2ray_name /var/log/$v2ray_name/ + chown -R $v2ray_name:$v2ray_name /usr/local/share/$v2ray_name/ + + V2rayConfigUpdate + + ServiceControl restart $v2ray_name + + Println "$info $v2ray_name 升级完成\n" +} + +V2rayConfigUpdate() +{ + if [ ! -e "$V2_CONFIG" ] + then + Println "$error $v2ray_name 未安装...\n" + exit 1 + fi + + if ! outbounds=$($JQ_FILE '.outbounds' "$V2_CONFIG" 2> /dev/null) || [ "$outbounds" == "null" ] + then + if grep -q '"path": "' < "$V2_CONFIG" + then + while IFS= read -r line + do + if [[ $line == *"path"* ]] + then + path=${line#*: \"} + path=${path%\"*} + break + fi + done < "$V2_CONFIG" + fi + + printf -v update_date '%(%m-%d-%H:%M:%S)T' -1 + cp -f "$V2_CONFIG" "${V2_CONFIG}_$update_date" + while IFS= read -r line + do + if [[ $line == *"port"* ]] + then + port=${line#*: } + port=${port%,*} + elif [[ $line == *"id"* ]] + then + id=${line#*: \"} + id=${id%\"*} + break + fi + done < "$V2_CONFIG" + + $JQ_FILE -n --arg port "${port:-$(GetFreePort)}" --arg id "${id:-$($V2CTL_FILE uuid)}" --arg path "${path:-/$(RandStr)}" \ + --arg error "/var/log/$v2ray_name/error.log" \ + '{ + "log": { + "access": "none", + "error": $error, + "loglevel": "error" + }, + "inbounds": [ + { + "listen": "127.0.0.1", + "port": $port | tonumber, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": $id, + "level": 0, + "alterId": 64, + "email": "name@localhost" + } + ] + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": $path + } + }, + "tag": "nginx-1" + } + ], + "outbounds": [ + { + "protocol": "freedom", + "tag": "direct" + }, + { + "protocol": "blackhole", + "tag": "block" + } + ], + "policy": { + "levels": { + "0": { + "handshake": 4, + "connIdle": 300, + "uplinkOnly": 2, + "downlinkOnly": 5, + "statsUserUplink": false, + "statsUserDownlink": false, + "bufferSize": 512 + } + }, + "system": { + "statsInboundUplink": false, + "statsInboundDownlink": false, + "statsOutboundUplink": false, + "statsOutboundDownlink": false + } + } + }' > "$V2_CONFIG" + + Println "$info $v2ray_name 配置文件已更新\n" + fi +} diff --git a/src/v2ray/menu b/src/v2ray/menu index 7932ab0..56a4740 100644 --- a/src/v2ray/menu +++ b/src/v2ray/menu @@ -72,7 +72,6 @@ case $v2ray_num in ;; 2) V2rayUpdate - systemctl restart $v2ray_name ;; 3) V2rayConfigUpdate diff --git a/src/x b/src/x index 49fba56..6805e1b 100644 --- a/src/x +++ b/src/x @@ -1,318 +1,54 @@ Include utils/imagemagick "$@" - Include utils/imgcat "$@" - Include src/v2ray/get_free_tag "$@" - Include src/v2ray/view_staus "$@" - Include src/v2ray/set_bound "$@" - Include src/v2ray/add_inbound "$@" - Include src/v2ray/get_inbounds "$@" - Include src/v2ray/list_inbounds "$@" - Include src/v2ray/select_inbound "$@" - Include src/v2ray/select_account "$@" - Include src/v2ray/delete_inbound "$@" - Include src/v2ray/add_inbound_account "$@" - Include src/v2ray/list_inbound_accounts "$@" - Include src/v2ray/list_inbound_share "$@" - Include src/v2ray/delete_inbound_account "$@" - Include src/v2ray/add_outbound "$@" - Include src/v2ray/get_outbounds "$@" - Include src/v2ray/list_outbounds "$@" - Include src/v2ray/select_outbound "$@" - Include src/v2ray/delete_outbound "$@" - Include src/v2ray/add_outbound_account "$@" - Include src/v2ray/list_outbound_accounts "$@" - Include src/v2ray/delete_outbound_account "$@" - Include src/v2ray/get_routing "$@" - Include src/v2ray/list_routing "$@" - Include src/v2ray/set_routing "$@" - Include src/v2ray/get_policy "$@" - Include src/v2ray/list_policy "$@" - Include src/v2ray/set_policy "$@" - Include src/v2ray/get_reverse "$@" - Include src/v2ray/list_reverse "$@" - Include src/v2ray/set_reverse "$@" - Include src/v2ray/get_dns "$@" - Include src/v2ray/list_dns "$@" - Include src/v2ray/set_dns "$@" - Include src/v2ray/get_stats "$@" - Include src/v2ray/get_traffic "$@" - Include src/v2ray/list_stats "$@" - Include src/v2ray/reset_stats "$@" - Include src/v2ray/list_inbound_domains "$@" - Include src/v2ray/update_cert "$@" - Include src/v2ray/list_nginx_domains "$@" - Include src/v2ray/select_nginx_domain "$@" - Include src/v2ray/select_nginx_server "$@" - Include src/v2ray/update_nginx_cert "$@" - Include src/v2ray/add_nginx_proxy "$@" - Include src/v2ray/select_nginx_proxy "$@" - Include src/v2ray/list_nginx_domain "$@" - Include src/v2ray/config_domain "$@" - -V2rayInstall() -{ - if [ -s "$V2_CONFIG" ] - then - Println "$error $v2ray_name 已存在...\n" - ExitOnList n "`gettext \"是否覆盖原安装\"`" - fi - - DepsCheck - JQInstall - - if ! grep -q "$v2ray_name:" < "/etc/passwd" - then - if grep -q '\--group ' < <(adduser --help) - then - adduser $v2ray_name --system --group --no-create-home > /dev/null - else - adduser $v2ray_name --system --no-create-home > /dev/null - fi - usermod -s /usr/sbin/nologin $v2ray_name - fi - - Println "$info 安装 $v2ray_name..." - - if [ "$v2ray_name" == "v2ray" ] - then - { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ - | sed "s+nobody+$v2ray_name+g" \ - | sed "s+ 'sha1'++g" \ - | sed "s+ 'sha256'++g" \ - | sed "s+ 'sha512'++g" \ - | sed "s+https://api.github.com/repos/v2fly/v2ray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ - | sed "s+https://github.com/v2fly/v2ray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash - else - { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ - | sed "s+nobody+$v2ray_name+g" \ - | sed "s+ 'sha1'++g" \ - | sed "s+ 'sha256'++g" \ - | sed "s+ 'sha512'++g" \ - | sed "s+https://api.github.com/repos/XTLS/Xray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ - | sed "s+https://github.com/XTLS/Xray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash - fi - - sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name.service" - sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name@.service" - - mkdir -p /var/log/$v2ray_name/ - [ ! -e "/var/log/$v2ray_name/error.log" ] && printf '%s' "" > /var/log/$v2ray_name/error.log - chown -R $v2ray_name:$v2ray_name /var/log/$v2ray_name/ - chown -R $v2ray_name:$v2ray_name /usr/local/share/$v2ray_name/ - - V2rayConfigUpdate - - systemctl daemon-reload - systemctl enable $v2ray_name - systemctl start $v2ray_name - - Println "$info $v2ray_name 安装完成\n" -} - -V2rayUpdate() -{ - DepsCheck - JQInstall - ShFileUpdate $v2ray_name - - if ! grep -q "$v2ray_name:" < "/etc/passwd" - then - if grep -q '\--group ' < <(adduser --help) - then - adduser $v2ray_name --system --group --no-create-home > /dev/null - else - adduser $v2ray_name --system --no-create-home > /dev/null - fi - usermod -s /usr/sbin/nologin $v2ray_name - fi - - if [ "$v2ray_name" == "v2ray" ] - then - { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ - | sed "s+nobody+$v2ray_name+g" \ - | sed "s+ 'sha1'++g" \ - | sed "s+ 'sha256'++g" \ - | sed "s+ 'sha512'++g" \ - | sed "s+https://api.github.com/repos/v2fly/v2ray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ - | sed "s+https://github.com/v2fly/v2ray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash - else - { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ - | sed "s+nobody+$v2ray_name+g" \ - | sed "s+ 'sha1'++g" \ - | sed "s+ 'sha256'++g" \ - | sed "s+ 'sha512'++g" \ - | sed "s+https://api.github.com/repos/XTLS/Xray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ - | sed "s+https://github.com/XTLS/Xray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash - fi - - sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name.service" - sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name@.service" - - mkdir -p /var/log/$v2ray_name/ - [ ! -e "/var/log/$v2ray_name/error.log" ] && printf '%s' "" > /var/log/$v2ray_name/error.log - chown -R $v2ray_name:$v2ray_name /var/log/$v2ray_name/ - chown -R $v2ray_name:$v2ray_name /usr/local/share/$v2ray_name/ - - V2rayConfigUpdate - - systemctl daemon-reload - systemctl restart $v2ray_name - - Println "$info $v2ray_name 升级完成\n" -} - -V2rayConfigUpdate() -{ - if [ ! -e "$V2_CONFIG" ] - then - Println "$error $v2ray_name 未安装...\n" - exit 1 - fi - - if ! outbounds=$($JQ_FILE '.outbounds' "$V2_CONFIG" 2> /dev/null) || [ "$outbounds" == "null" ] - then - if grep -q '"path": "' < "$V2_CONFIG" - then - while IFS= read -r line - do - if [[ $line == *"path"* ]] - then - path=${line#*: \"} - path=${path%\"*} - break - fi - done < "$V2_CONFIG" - fi - - printf -v update_date '%(%m-%d-%H:%M:%S)T' -1 - cp -f "$V2_CONFIG" "${V2_CONFIG}_$update_date" - while IFS= read -r line - do - if [[ $line == *"port"* ]] - then - port=${line#*: } - port=${port%,*} - elif [[ $line == *"id"* ]] - then - id=${line#*: \"} - id=${id%\"*} - break - fi - done < "$V2_CONFIG" - - $JQ_FILE -n --arg port "${port:-$(GetFreePort)}" --arg id "${id:-$($V2CTL_FILE uuid)}" --arg path "${path:-/$(RandStr)}" \ - --arg error "/var/log/$v2ray_name/error.log" \ - '{ - "log": { - "access": "none", - "error": $error, - "loglevel": "error" - }, - "inbounds": [ - { - "listen": "127.0.0.1", - "port": $port | tonumber, - "protocol": "vmess", - "settings": { - "clients": [ - { - "id": $id, - "level": 0, - "alterId": 64, - "email": "name@localhost" - } - ] - }, - "streamSettings": { - "network": "ws", - "wsSettings": { - "path": $path - } - }, - "tag": "nginx-1" - } - ], - "outbounds": [ - { - "protocol": "freedom", - "tag": "direct" - }, - { - "protocol": "blackhole", - "tag": "block" - } - ], - "policy": { - "levels": { - "0": { - "handshake": 4, - "connIdle": 300, - "uplinkOnly": 2, - "downlinkOnly": 5, - "statsUserUplink": false, - "statsUserDownlink": false, - "bufferSize": 512 - } - }, - "system": { - "statsInboundUplink": false, - "statsInboundDownlink": false, - "statsOutboundUplink": false, - "statsOutboundDownlink": false - } - } - }' > "$V2_CONFIG" - - Println "$info $v2ray_name 配置文件已更新\n" - fi -} +Include src/xray/install "$@" +Include src/service/control "$@" ShFileCheck @@ -323,6 +59,6 @@ V2_FILE="/usr/local/bin/x" V2_LINK="https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh" V2_LINK_FALLBACK="$FFMPEG_MIRROR_LINK/xray_install-release.sh" V2CTL_FILE="/usr/local/bin/xray" -V2_CONFIG="/usr/local/etc/xray/config.json" +V2_CONFIG="$X_CONFIG" Include src/v2ray/menu "$@" diff --git a/src/xray/install b/src/xray/install new file mode 100644 index 0000000..a8ed916 --- /dev/null +++ b/src/xray/install @@ -0,0 +1,214 @@ +V2rayInstall() +{ + if [ -s "$V2_CONFIG" ] + then + Println "$error $v2ray_name 已存在...\n" + ExitOnList n "`gettext \"是否覆盖原安装\"`" + fi + + DepsCheck + JQInstall + + if ! grep -q "$v2ray_name:" < "/etc/passwd" + then + if grep -q '\--group ' < <(adduser --help) + then + adduser $v2ray_name --system --group --no-create-home > /dev/null + else + adduser $v2ray_name --system --no-create-home > /dev/null + fi + usermod -s /usr/sbin/nologin $v2ray_name + fi + + Println "$info 安装 $v2ray_name..." + + if [ "$v2ray_name" == "v2ray" ] + then + { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ + | sed "s+nobody+$v2ray_name+g" \ + | sed "s+ 'sha1'++g" \ + | sed "s+ 'sha256'++g" \ + | sed "s+ 'sha512'++g" \ + | sed "s+https://api.github.com/repos/v2fly/v2ray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ + | sed "s+https://github.com/v2fly/v2ray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash + else + { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ + | sed "s+nobody+$v2ray_name+g" \ + | sed "s+ 'sha1'++g" \ + | sed "s+ 'sha256'++g" \ + | sed "s+ 'sha512'++g" \ + | sed "s+https://api.github.com/repos/XTLS/Xray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ + | sed "s+https://github.com/XTLS/Xray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash + fi + + sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name.service" + sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name@.service" + + mkdir -p /var/log/$v2ray_name/ + [ ! -e "/var/log/$v2ray_name/error.log" ] && printf '%s' "" > /var/log/$v2ray_name/error.log + chown -R $v2ray_name:$v2ray_name /var/log/$v2ray_name/ + chown -R $v2ray_name:$v2ray_name /usr/local/share/$v2ray_name/ + + V2rayConfigUpdate + + ServiceControl start $v2ray_name + + Println "$info $v2ray_name 安装完成\n" +} + +V2rayUpdate() +{ + DepsCheck + JQInstall + ShFileUpdate $v2ray_name + + if ! grep -q "$v2ray_name:" < "/etc/passwd" + then + if grep -q '\--group ' < <(adduser --help) + then + adduser $v2ray_name --system --group --no-create-home > /dev/null + else + adduser $v2ray_name --system --no-create-home > /dev/null + fi + usermod -s /usr/sbin/nologin $v2ray_name + fi + + if [ "$v2ray_name" == "v2ray" ] + then + { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ + | sed "s+nobody+$v2ray_name+g" \ + | sed "s+ 'sha1'++g" \ + | sed "s+ 'sha256'++g" \ + | sed "s+ 'sha512'++g" \ + | sed "s+https://api.github.com/repos/v2fly/v2ray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ + | sed "s+https://github.com/v2fly/v2ray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash + else + { curl -s -m 10 "$V2_LINK" || curl -s -m 30 "$V2_LINK_FALLBACK"; } \ + | sed "s+nobody+$v2ray_name+g" \ + | sed "s+ 'sha1'++g" \ + | sed "s+ 'sha256'++g" \ + | sed "s+ 'sha512'++g" \ + | sed "s+https://api.github.com/repos/XTLS/Xray-core/releases/latest+$FFMPEG_MIRROR_LINK/$v2ray_name.json+g" \ + | sed "s+https://github.com/XTLS/Xray-core/releases/download+$FFMPEG_MIRROR_LINK/$v2ray_name+g" | bash + fi + + sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name.service" + sed -i "s+nobody+$v2ray_name+g" "/etc/systemd/system/$v2ray_name@.service" + + mkdir -p /var/log/$v2ray_name/ + [ ! -e "/var/log/$v2ray_name/error.log" ] && printf '%s' "" > /var/log/$v2ray_name/error.log + chown -R $v2ray_name:$v2ray_name /var/log/$v2ray_name/ + chown -R $v2ray_name:$v2ray_name /usr/local/share/$v2ray_name/ + + V2rayConfigUpdate + + ServiceControl restart $v2ray_name + + Println "$info $v2ray_name 升级完成\n" +} + +V2rayConfigUpdate() +{ + if [ ! -e "$V2_CONFIG" ] + then + Println "$error $v2ray_name 未安装...\n" + exit 1 + fi + + if ! outbounds=$($JQ_FILE '.outbounds' "$V2_CONFIG" 2> /dev/null) || [ "$outbounds" == "null" ] + then + if grep -q '"path": "' < "$V2_CONFIG" + then + while IFS= read -r line + do + if [[ $line == *"path"* ]] + then + path=${line#*: \"} + path=${path%\"*} + break + fi + done < "$V2_CONFIG" + fi + + printf -v update_date '%(%m-%d-%H:%M:%S)T' -1 + cp -f "$V2_CONFIG" "${V2_CONFIG}_$update_date" + while IFS= read -r line + do + if [[ $line == *"port"* ]] + then + port=${line#*: } + port=${port%,*} + elif [[ $line == *"id"* ]] + then + id=${line#*: \"} + id=${id%\"*} + break + fi + done < "$V2_CONFIG" + + $JQ_FILE -n --arg port "${port:-$(GetFreePort)}" --arg id "${id:-$($V2CTL_FILE uuid)}" --arg path "${path:-/$(RandStr)}" \ + --arg error "/var/log/$v2ray_name/error.log" \ + '{ + "log": { + "access": "none", + "error": $error, + "loglevel": "error" + }, + "inbounds": [ + { + "listen": "127.0.0.1", + "port": $port | tonumber, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": $id, + "level": 0, + "alterId": 64, + "email": "name@localhost" + } + ] + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": $path + } + }, + "tag": "nginx-1" + } + ], + "outbounds": [ + { + "protocol": "freedom", + "tag": "direct" + }, + { + "protocol": "blackhole", + "tag": "block" + } + ], + "policy": { + "levels": { + "0": { + "handshake": 4, + "connIdle": 300, + "uplinkOnly": 2, + "downlinkOnly": 5, + "statsUserUplink": false, + "statsUserDownlink": false, + "bufferSize": 512 + } + }, + "system": { + "statsInboundUplink": false, + "statsInboundDownlink": false, + "statsOutboundUplink": false, + "statsOutboundDownlink": false + } + } + }' > "$V2_CONFIG" + + Println "$info $v2ray_name 配置文件已更新\n" + fi +} diff --git a/utils/ffmpeg b/utils/ffmpeg index 809af84..f728a22 100644 --- a/utils/ffmpeg +++ b/utils/ffmpeg @@ -4,9 +4,9 @@ FFmpegInstall() then FFMPEG_FILE="$FFMPEG_FILE_ROOT/ffmpeg" FFPROBE_FILE="$FFMPEG_FILE_ROOT/ffprobe" - elif [ "$FFMPEG_ROOT" != "$HOME" ] && FFMPEG_FILE_ROOT=$(find "$HOME"/ffmpeg-git-* -type d 2> /dev/null | head -1) + elif FFMPEG_FILE_ROOT=$(find "$IPTV_ROOT"/ffmpeg-git-* -type d 2> /dev/null | head -1) then - FFMPEG_ROOT="$HOME" + FFMPEG_ROOT="$IPTV_ROOT" FFMPEG_FILE="$FFMPEG_FILE_ROOT/ffmpeg" FFPROBE_FILE="$FFMPEG_FILE_ROOT/ffprobe" fi diff --git a/utils/htpasswd b/utils/htpasswd new file mode 100644 index 0000000..e8f0a84 --- /dev/null +++ b/utils/htpasswd @@ -0,0 +1,17 @@ +HtpasswdInstall() +{ + if [[ -x $(command -v htpasswd) ]] + then + return 0 + fi + + if [ "$dist" == "mac" ] + then + BrewInstall httpd + elif [ "$dist" == "rpm" ] + then + DepInstall httpd-tools + else + DepInstall apache2-utils + fi +} diff --git a/utils/i18n b/utils/i18n index 620c8de..9d2fe50 100644 --- a/utils/i18n +++ b/utils/i18n @@ -261,6 +261,11 @@ grep() ggrep "$@" } +base64() +{ + gbase64 "$@" +} + else TEXTDOMAINDIR=/usr/share/locale fi diff --git a/utils/inquirer b/utils/inquirer index d74e1da..c7b2d25 100644 --- a/utils/inquirer +++ b/utils/inquirer @@ -1196,6 +1196,7 @@ inquirer() if [ "${#list_options[@]}" -eq 1 ] then + inquirer:print "${green}?${normal} ${bold}${bg_black}${white}${prompt} ${bg_black}${cyan}${list_options[current_index]}${normal}\n" return fi @@ -1274,13 +1275,14 @@ inquirer() } inquirer:on_text_input_enter() { + local validate_failed_msg text_input=${text_input:-$text_default} tput civis tput cub "$(tput cols)" tput el - if $text_input_validator "$text_input" + if validate_failed_msg=$($text_input_validator "$text_input") then tput sc tput cuu $((1+failed_count*3)) @@ -1293,7 +1295,7 @@ inquirer() else failed_count=$((failed_count+1)) tput cud1 - inquirer:print "${bg_black}${red}${text_input_regex_failed_msg}${normal}\n" + inquirer:print "${bg_black}${red}${validate_failed_msg:-$text_input_validate_failed_msg}${normal}\n" tput cud1 if [ "$text_input" == "$text_default" ] then @@ -1420,7 +1422,7 @@ inquirer() fi text_input_validator=${4:-inquirer:text_input_default_validator} - text_input_regex_failed_msg=${5:-$(gettext "输入验证错误")} + text_input_validate_failed_msg=${5:-$(gettext "输入验证错误")} inquirer:print "${green}?${normal} ${bold}${bg_black}${white}${prompt}${text_default_tip}\n" @@ -1580,7 +1582,7 @@ inquirer() else failed_count=$((failed_count+1)) tput cud1 - inquirer:print "${bg_black}${red}${date_pick_regex_failed_msg}${normal}\n" + inquirer:print "${bg_black}${red}${date_pick_validate_failed_msg}${normal}\n" tput cud1 inquirer:print "${date_pick}" tput cub $((19-current_pos)) @@ -1592,7 +1594,7 @@ inquirer() inquirer:date_pick() { var_name=$2 date_pick_validator=${3:-inquirer:date_pick_default_validator} - date_pick_regex_failed_msg=${4:-$(gettext "时间验证错误")} + date_pick_validate_failed_msg=${4:-$(gettext "时间验证错误")} date_pick=$(printf '%(%Y-%m-%d %H:%M:%S)T' "${!var_name:--1}") current_pos=12 failed_count=0 @@ -1774,10 +1776,10 @@ inquirer() failed_count \ text_default \ text_input \ - text_input_regex_failed_msg \ + text_input_validate_failed_msg \ text_input_validator \ date_pick \ - date_pick_regex_failed_msg \ + date_pick_validate_failed_msg \ date_pick_validator \ colors=() \ bg_colors=() \ diff --git a/utils/jq b/utils/jq index 95b6aa8..770b474 100644 --- a/utils/jq +++ b/utils/jq @@ -2,7 +2,11 @@ JQInstall() { if [[ -x "$JQ_FILE" ]] then - return 0 + return + elif [[ -x "$IPTV_ROOT"/jq ]] + then + JQ_FILE="$IPTV_ROOT"/jq + return fi DepsCheck @@ -440,7 +444,7 @@ JQs() $JQ_FILE --arg d1 "$5" --arg d2 "${6:-$5}" --arg d3 "${7:-$5}" --arg d4 "${8:-$5}" --arg d5 "${9:-$5}" --arg d6 "${10:-$5}" -r -c -s ' def flat(a;b;c;d;e;f;g): - a as $a | (a[0]| type) as $type | if ($type == "object") then + (a // [{}]) as $a | (a[0]| type) as $type | if ($type == "object") then ([a[] | keys_unsorted[]] | unique) as $keys | reduce a[] as $item ({}; reduce($keys[]) as $key (.; $item[$key] as $val | ($val | type) as $type | (.[$key]) as $val2 | ($val2 | type) as $type2 | .[$key] = @@ -501,6 +505,8 @@ JQs() flat([flat(a[];b;c;d;e;f;g)];b;c;d;e;f;g) elif ($a == [""]) then "\"\"" + elif ($a == [{}]) then + {} else a|join(b) end; diff --git a/utils/mirror b/utils/mirror index 1919bb2..b789896 100644 --- a/utils/mirror +++ b/utils/mirror @@ -308,6 +308,13 @@ else Println "$error jq.json 下载出错, 无法连接 github ?" fi +if curl -s -L "https://api.github.com/repos/alist-org/alist/releases/latest" -o "$FFMPEG_MIRROR_ROOT/alist.json_tmp" +then + mv "$FFMPEG_MIRROR_ROOT/alist.json_tmp" "$FFMPEG_MIRROR_ROOT/alist.json" +else + Println "$error alist.json 下载出错, 无法连接 github ?" +fi + if curl -s -L "https://api.github.com/repos/v2fly/v2ray-core/releases/latest" -o "$FFMPEG_MIRROR_ROOT/v2ray.json_tmp" then mv "$FFMPEG_MIRROR_ROOT/v2ray.json_tmp" "$FFMPEG_MIRROR_ROOT/v2ray.json" diff --git a/utils/mongodb b/utils/mongodb index 2e1eb4d..690d6dc 100644 --- a/utils/mongodb +++ b/utils/mongodb @@ -66,7 +66,7 @@ gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc if [[ $(ps --no-headers -o comm 1) == "systemd" ]] then sed -i "s/LimitNOFILE=.*/LimitNOFILE=$file_max/" /lib/systemd/system/mongod.service - sed -i '/TasksAccounting=/a RestartSec=5\nStartLimitIntervalSec=0\nRestart=on-failure' /lib/systemd/system/mongod.service + sed -i '/TasksAccounting=/a StartLimitInterval=60s\nStartLimitBurst=5\nRestartSec=5\nRestart=on-failure' /lib/systemd/system/mongod.service systemctl daemon-reload sed -i "s/destination: file/destination: syslog/" /etc/mongod.conf sed -i "s/ logAppend: true/ #logAppend: true/" /etc/mongod.conf diff --git a/utils/openssl b/utils/openssl index 575d3e5..3dba914 100644 --- a/utils/openssl +++ b/utils/openssl @@ -5,24 +5,13 @@ OpensslInstall() return 0 fi - echo - ExitOnList y "`gettext \"是否安装 openssl\"`" - - Progress & - progress_pid=$! - trap ' - kill $progress_pid - wait $progress_pid 2> /dev/null - ' EXIT + DepInstall openssl if [ "$dist" == "rpm" ] then - yum -y install openssl openssl-devel >/dev/null 2>&1 - else - apt-get -y install openssl libssl-dev >/dev/null 2>&1 + DepInstall openssl-devel + elif [ "$dist" != "mac" ] + then + DepInstall libssl-dev fi - kill $progress_pid - wait $progress_pid 2> /dev/null || true - trap - EXIT - echo -n "...100%" && Println "`eval_gettext \"\\\$info openssl 安装完成\"`" } diff --git a/utils/python b/utils/python index 5245585..00d8f41 100644 --- a/utils/python +++ b/utils/python @@ -26,9 +26,9 @@ PythonInstall() yum install -y gcc openssl-devel bzip2-devel libffi-devel >/dev/null 2>&1 echo -n "...50%..." cd ~ - wget --timeout=10 --tries=3 --no-check-certificate https://www.python.org/ftp/python/3.8.9/Python-3.8.9.tgz -qO Python-3.8.9.tgz - tar xzf Python-3.8.9.tgz - cd Python-3.8.9 + wget --timeout=10 --tries=3 --no-check-certificate https://www.python.org/ftp/python/3.12.2/Python-3.12.2.tgz -qO Python-3.12.2.tgz + tar xzf Python-3.12.2.tgz + cd Python-3.12.2 ./configure >/dev/null 2>&1 make >/dev/null 2>&1 make install >/dev/null 2>&1 diff --git a/utils/shfile b/utils/shfile index 30aa976..67cc323 100644 --- a/utils/shfile +++ b/utils/shfile @@ -107,6 +107,8 @@ ShFileCheck() [ ! -e "$PVE_FILE" ] && ln -s "$SH_FILE" "$PVE_FILE" [ ! -e "$ALIST_FILE" ] && ln -s "$SH_FILE" "$ALIST_FILE" [ ! -e "$LIANHUANHUA_FILE" ] && ln -s "$SH_FILE" "$LIANHUANHUA_FILE" + [ ! -e "$RCLONE_FILE" ] && ln -s "$SH_FILE" "$RCLONE_FILE" + [ ! -e "$CALIBRE_FILE" ] && ln -s "$SH_FILE" "$CALIBRE_FILE" return 0 } diff --git a/utils/system b/utils/system index 766d70a..2e4b37e 100644 --- a/utils/system +++ b/utils/system @@ -48,10 +48,10 @@ ArchCheck() if grep -Eqi "x86_64|amd64" <<< "$arch" then arch="x86_64" - elif grep -Eqi "i386|i686" <<< "$arch" + elif grep -Eqi "i386|i686|x86" <<< "$arch" then arch="i386" - elif grep -Eqi "aarch64|armv8" <<< "$arch" + elif grep -Eqi "aarch64|armv8|arm64" <<< "$arch" then arch="arm64" elif grep -qi "armv7" <<< "$arch"