Files
2026-10-16 08:41:14 +00:00

6620 lines
256 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# shellcheck shell=bash
# shellcheck disable=SC2086
# shellcheck source=/dev/null
PATH=${PATH}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#
# ——————————————————————————————————————————————————————————————————————————————————
# __ ___ _ _ _
# \ \ / (_) /\ | (_) | |
# \ V / _ __ _ ___ _ _ __ _ / \ | |_ ___| |_
# > < | |/ _` |/ _ \| | | |/ _` | / /\ \ | | / __| __|
# / . \| | (_| | (_) | |_| | (_| | / ____ \| | \__ \ |_
# /_/ \_\_|\__,_|\___/ \__, |\__,_| /_/ \_\_|_|___/\__|
# __/ |
# |___/
#
# Copyright (c) 2024 DDSRem <https://blog.ddsrem.com>
#
# This is free software, licensed under the GNU General Public License v3.0.
#
# ——————————————————————————————————————————————————————————————————————————————————
#
DATE_VERSION="v1.8.4-2025_06_14_19_04"
#
# ——————————————————————————————————————————————————————————————————————————————————
amilys_embyserver_latest_version=4.10.1.0
emby_embyserver_latest_version=4.10.1.0
amilys_embyserver_beta_version=4.10.0.22
emby_embyserver_beta_version=4.11.0.8
# ——————————————————————————————————————————————————————————————————————————————————
Sky_Blue="\033[36m"
Blue="\033[34m"
Green="\033[32m"
Red="\033[31m"
Yellow='\033[33m'
Font="\033[0m"
INFO="[${Green}INFO${Font}]"
ERROR="[${Red}ERROR${Font}]"
WARN="[${Yellow}WARN${Font}]"
DEBUG="[${Sky_Blue}DEBUG${Font}]"
function INFO() {
echo -e "${INFO} ${1}"
}
function ERROR() {
echo -e "${ERROR} ${1}"
}
function WARN() {
echo -e "${WARN} ${1}"
}
function DEBUG() {
echo -e "${DEBUG} ${1}"
}
function __unzip_metadata_debug() {
DEBUG "${OSNAME} $(uname -a)"
# if [ -f "${CONFIG_DIR}/ali2115.txt" ]; then
# DEBUG "ali2115 配置情况:已开启!"
# else
# DEBUG "ali2115 配置情况:未配置!"
# fi
# DEBUG "$(pull_run_glue xxd -g 1 -l 256 "/media/temp/${1}")"
# DEBUG "$(pull_run_glue xxd -g 1 -s -256 "/media/temp/${1}")"
ERROR "解压元数据失败!"
exit 1
}
# shellcheck disable=SC2034
mirrors=(
"docker.io"
"hub.rat.dev"
"dockerhub.ggbox.us.kg"
"docker.fxxk.dedyn.io"
"docker.jsdelivr.fyi"
"dockerhub.anzu.vip"
"freeno.xyz"
"docker.anyhub.us.kg"
"dockerhub.icu"
"dk.nastool.de"
"func.ink"
"proxy.1panel.live"
"docker-0.unsee.tech"
"docker.zhai.cm"
"a.ussh.net"
"docker.1ms.run"
"lispy.org"
"docker.kejilion.pro"
)
pan115share_list_base64="NEtSZW11eCBzdzZwdzc5M3dmcCAyNjI4NDc4MjA5Nzg3MjY0MzE1IHc4MTYK55S15b2xMTA4MFAgc3c2OGZ1dTNubncgMTkyNjk2ODEwNTcyMjgyMzAzMSBwYjU3CueUteW9seaMiea8lOWRmOWvvOa8lOWIhuexuyBzd3owNHByM3poOSAyOTY2MzAyMDA0NDE5NDM4ODA2IHozODEK5ZCI6ZuGMSBzd3p5aXd3M3duOSAyNTI0ODExNTU3NTAwODUyMjc0IHcxZTAK5ZCI6ZuGMiBzd3p5aXdxM3duOSAyNjM3ODkwMjU4Mzc4OTIyNzc3IHg3MTYK5ZCI6ZuGMyBzd3p5aXdiM3duOSAyNjM3ODk2MzYwMjI3MjE1NzQ5IHFmZTgK5Yqo55S755S15b2xIHN3ejZnbWwzZndvIDI3ODM3NTM1OTgxNjc2NzgxNzYgODg4OArmrKfnvo7nlLXlvbEgc3c2OHd6OTNuY2IgMjY1NjIzMjA2MDQwMDM2NTc2OCA2NjY2CueUteinhuWJpy/nvo7liacgc3c2cGx0MjNuY2IgMjYyOTgzMDE4NTMyOTU1Mzc5NiA2NjY2CuWNg+mDqOaKlumfs+efreWJp+WQiOmbhiBzd3pxaDY3M2g0eSAyODQ0Mzg4NTQ1NDg3OTYxMjExIDUyOTYK5oqW6Z+z55+t5Ymn5ZCI6ZuGMS43N1Qgc3d6eDc2ZjN3ZmEgMjk1NTIyMDU3NjczNzAwOTk1OCBuNzI0CueUteinhuWJpy/mrKfnvo7liacgc3d6bm0zNzN3MXAgMjc3NTU2NzExNjY5NjI0NTQxMiBwZTM1Cumfs+S5kDIy5LiH6aaWIHN3em1xY3IzZnM2ICAyNzgzMzA0NDAzNTg1NTk2NTY2IHhkNjcK6Z+z5LmQMjLkuIfpppYvRERTK0hpUmVzIHN3NjU4dXEzNngyIDI1NjU2NzI0MDM3NjYwMDE0MzUgbWQ5OArpn7PkuZAyMuS4h+mmli/mr43luKbns7vliJcgc3c2NTh1cTM2eDIgMjU2NTQxNjQ3OTcwOTExNzg0MyBtZDk4Cumfs+S5kDIy5LiH6aaWL+e0ouWwvOeyvumAiSBzdzY1OHVxMzZ4MiAyNTY1OTE3Mzc5NTE1MDM5MTc2IG1kOTgK6Z+z5LmQMjLkuIfpppYv5ZCE57G76aOO5qC8IHN3NjU4dXEzNngyIDI1NjU0NjY1ODY5NTM0NjQ4NTcgbWQ5OArpn7PkuZAyMuS4h+mmli/ljY7or60yNzAwMOmmluaXoOaNnyBzdzY1OHViMzZ4MiAyNTY1Mjc0MDU1NzgzMzk4NzM0IHE3ZTAK6Z+z5LmQMjLkuIfpppYv5oyJ5q2M5omL5YiG57G7IHN3aGdldHMzemg5IDI5NjQ1OTI2MjY0OTQ1NDg1NTAgbjZlNgrnlLXop4bliacv5pel6Z+p5YmnIHN3emp4Y3Azd2ZhIDI5NTE4NzA2NjMxOTgzNTE2ODYgb2Y4OSAK55S16KeG5YmnL+WbveS6p+WJpyBzd3owb2ZsM3poOSAyOTU2ODE4MDgwOTY2MzIyMjAzIHE1ZjgK55S15b2xL+WOn+ebmCBzd3pldzRtM25jNiAyOTIwNjE5NTc4NzUwOTI1OTQ2IGkwZDcK55S15b2xL+mfqeWbveWOn+ebmCBzd2hpZDV4M3dmYSAzMDQyOTM2NTE2NzE0NTM3MTA1IHhkZjkK55S15b2xL+WPsOa5vuWOn+ebmCBzd2gzcmloM3dmYSAyOTgxNTAzMjEwMTQ0MjQ0NDg2IGc1MTIK55S15b2xL+mmmea4r+WOn+ebmCBzd2hiZnkzM3dmYSAzMDI1MTI0NTg1MTY5NTkyNTcyIGEzNzIK55S15b2xL1VIROWOn+ebmCBzd2hiczRyM3poOSAzMDIzMzMyMDQxNzgxNjE4NzYzIGVjMzgK5ryU5ZSx5LyaL+WOn+ebmCBzd3oxOHduM3poOSAyOTU5NzI0NzQ5NTI2MzQ1OTAwIHlmNjEK5ryU5ZSx5LyaL+WQiOmbhiBzd3oxODA3M3poOSAyOTU2ODk5ODkwOTA3Nzg2MTMwIHM1OTcK5ryU5ZSx5LyaL+iTneWFieWOn+ebmO+8iOW3suWIruWJiu+8iSBzd2h0bDBhM3dmYSAzMTExNDA3Nzg4OTQzMDU3MTIxIHpkNTIK55S16KeG5YmnL+aXpeWJpzEgc3d3M3lqMzN3ZmEgMzE0Mjg5NTgyMTY4OTAzNzY4MSB1YjQ2CueUteinhuWJpy/ml6XliacyIHN3dzZxNzYzd2ZhIDMxNDg2NTk2NDQ0Mjk2MDc1MDEgczIyNwrnlLXop4bliacv5pel5Ymn5bGLIHN3aDkyaTAzd2ZhIDMxMjkxNjA1ODE1OTAxMzExNzUgemRlOArnlLXlvbEvMjAyNSBzd3d6NG1nM3dmYSAzMTU5OTgxODkwMTM3ODU4ODI0IHcxMjgKCg=="
quarkshare_list_base64="5Yqo5ryrL+WbveWGheWklue7j+WFuOWKqOeUu+WKqOa8q+Wkp+WFqCA2Yjc5NTIxODM0MmQgMjNkOTUxMjcxZDQ2NDY5N2JlMjMyZGJiNzQ2YjIyN2UK5Yqo5ryrL+W3suWujOe7k+Wbvea8qyA2Yjc5NTIxODM0MmQgZjZhYjZkYzAyMTBhNDJiZWEyZGMyYmZlYTM4YzJiZTQK5Yqo5ryrL+W3suWujOe7k+aXpea8qyA2Yjc5NTIxODM0MmQgZDI2NTk1NmUyNDFlNDlkYmJiN2JmNWU3MTYzMGIxOTMK5Yqo5ryrL+W3suWujOe7k+e+jua8qyA2Yjc5NTIxODM0MmQgYzRkNDI5ZGZjNjQ0NDczNzg2YmRiMjJhYTY3NDIxOTAK5bCP5ZOB55u45aOwLzIwMjTlvrfkupHnpL4gZWNlNTJkNjNiNjk4IGRhZTJmMzZkMzZkMDQ3M2I4OWZmODRkYWE4MWI4MzAzCuWwj+WTgeebuOWjsC/lsI/lk4HlpKflkIjpm4YgZTgyNzI2NGVhNDUzIDYwOWM1ZWI4YjMyNDRkYzI5NThiYzEzZjE2ZDQ1NGVkCuWwj+WTgeebuOWjsC/lsI/lk4Hnuq/kuqvlkIjpm4YgZDhiNGE1ODRmZDFhIGE1Mjk5MzQ5ZDM2OTQyMDY4YWRjODhiOTUyYzdjNDYxCueUteW9sS/lkIjpm4Yv5LulQUJDROW8gOWktOWQiOmbhiBhNjMyOTY3NzYwY2YgN2RhNGZkMmRjMDhmNGZhNTg1MmY5OTcyMTU1OTI1MTcK55S15b2xL+WQiOmbhi/ku6VFRkdI5byA5aS05ZCI6ZuGIDJmNTliYjVkOTZiOSA3YjcxNzM3ZTNjZDg0M2M1YTkzN2FjOTdhNTM1NDJkZArnlLXlvbEv5ZCI6ZuGL+S7pUlKS0zlvIDlpLTlkIjpm4YgNTA4MjhjMzY4ZGVmIDA5Njk1MGUzZDEwMjQyYjE5NjZiNzc3ODExMTVhMDdhCueUteW9sS/lkIjpm4Yv5LulTU5PUOW8gOWktOWQiOmbhiBlMDdlMjZhZWNjMDggYTJiMzA1MzE2MzFjNDZkY2IzOWYzMjA2OTc4OTgyOTUK55S15b2xL+WQiOmbhi/ku6VRUlNU5byA5aS05ZCI6ZuGIDA1MzZhMzhhMzU2ZSAxZDE3NWRiMzBlYWE0NTRlOWRiYzVlYWEwOWUxZTQ1NArnlLXlvbEv5ZCI6ZuGL+S7pVVWV1jlvIDlpLTlkIjpm4YgZTI3M2VmNjk3NDAzIDZkYmRhNmU4MTdlYjQxNDViYTJkZDY4MWU1N2FhNjc1CueUteW9sS/lkIjpm4Yv5LulWVrlvIDlpLTlkIjpm4YgYzhhYzZjODhlNWQ4IDQ4YzQ3OWUyNGJhZTRlYzNhNGE5ZDU2ZmNiMDZmY2Y0CueUteW9sS/lkIjpm4Yv5Lul5pWw5a2X5byA5aS05ZCI6ZuGIDQ5YWI3NWQ1MmUwMCBjZWMwNzAyZGIyNmI0N2M1YWJkNDJjYTc5YWJiNjVlMQrnlLXlvbEv5a+85ryUL+WMl+mHjuatpiBmYWIxZWRiOWU1ZWIgZDdiYmZmYzQ1ZWY2NDEwODhmZTRiMjAyOTEwOGJjYWMK55S15b2xL+WvvOa8lC/mtKrph5Hlrp0gYmUyNjFjOGE3ZWI4IGUxZGI5ZDc4NDgyMjQyYzI5NzNkMWNjMjMwNjBjYzFlCueUteW9sS/mvJTlkZgv5YiY5b635Y2OIDE3NjRjMmM4MTYwMyBhYmFlMmY3ZTYxZjU0OTgwODUxNjdlMDdlZjhkZWMzNArnlLXlvbEv5ryU5ZGYL+WRqOaYn+mpsCA2MGRjYTU4MDA5YWYgN2RhNTAyZDI0ZjQ3NGI2MGFmY2MzNDJmZDVhYzBkZTMK55S15b2xL+a8lOWRmC/lkajmtqblj5EgZTU4M2ZhYzQ1NTkyIDgyYzA0OWMxNDA1MDRkNGFhMzFjYmZlMTY0NWNiOWQ4CueUteW9sS/mvJTlkZgv5byg5Zu96I2jIGQzMDAwZjE0OTQyZSA4YzM1ZmNiYjRlODU0ZTUwYjM4NWRmNzAyNjA0ZDM4MgrnlLXlvbEv5ryU5ZGYL+aIkOm+mSBlNWI2NGRmYjFjODMgNjA3Yjg3OWRhMjVjNDQ2NDgzYmM3Zjg5NTBjZDczM2YK55S15b2xL+a8lOWRmC/mnY7kuL3nj40gNDczMzcwZTY1N2MwIGMzOWE1NjYwMDkyZTRiYmFhYzdjYWQzY2YwNjRlMjNjCueUteW9sS/mvJTlkZgv5p2O6L+e5p2wIGJmYzBhNjE1MGFmYyA2ZWViMDM2YzdkN2E0NTgwYWI5NWMxNjViYmVlNzRjMwrnlLXlvbEv5ryU5ZGYL+iIkua3hyA4NGU1M2RkMzc4ZjIgYzU5Yzc4MzU4NGU3NGQ3MDk0Yjk4YTY0OTg0OTI4NzYK55S15b2xL+a8lOWRmC/pgrHmt5HotJ4gYzRiMDQwM2MwZGZhIGE5MjBlMDY1NTVmYjRkNTA5NzU3MGNhMWI0MTBiZDAyCueUteW9sS/nsr7pgInpq5jnlLvotKjpq5jliIbnlLXlvbEgOGYxYjRiN2RjNjllIGQyZTVlOTE2NzRmOTQzNTJiMzMxMGFiODZiOGMyMzhlCueUteW9sS/pn6nlm71S57qnIDU0MzJiZWFlNGYxYSA1MTI0ZjQ3ODlkYWY0NTAwOWJkMTMzYWY1MDk5ODEwMgrnlLXop4bliacvVFZC44CBQVRW5Lqa6KeGIDA4NTIxMmRmMzg1ZCAxNzJiN2VjY2MzODQ0YWU0YTExNDUxZDZhMTQ1ZmZlMArnlLXop4bliacv5bey5a6M57uTL+aVsOWtl+W8gOWktCBjZDRjNWFjN2U4MzAgZGZhMDFjYjE4OTU4NDA4Y2EwZGE3MmIxMzkzMTlhZjMK55S16KeG5YmnL+W3suWujOe7ky/osYbnk6Por4TliIY5LjDku6XkuIrlm73kuqfliacgZDE5YzRlYmUxZmY3IDdiNDI5NDNkNGYyMDQyYWJiOTA3Yzk5ZGRiYjM1NDBkCueUteinhuWJpy/lt7Llroznu5Mv6aaW5a2X5q+NQUJDRCBlMWIyYmE4YjZkNmMgYzg5MjQ2N2IwY2MyNGFhYmFjYmVjNzFhMGI2ZjRkM2MK55S16KeG5YmnL+W3suWujOe7ky/pppblrZfmr41FRkdIIDE2NmZhMGE3Y2E2ZiBmZjU3MDgzZDg5MjM0ZWQzODkzMmRjMDYwOTdkMTE1ZArnlLXop4bliacv5bey5a6M57uTL+mmluWtl+avjUlKS0wgMzdhOTJjMGI3ZjEwIDU4NTkwN2FiYTBlZjQ2NGJhMDBhMGYyMGI0N2ZhMTE2CueUteinhuWJpy/lt7Llroznu5Mv6aaW5a2X5q+NTk1PUCBmYjMzODZlNDJhZjIgMzZlMmY4MWZmNDE0NGE5YzhjMTQ5ODhlZDg5YTg2MGQK55S16KeG5YmnL+W3suWujOe7ky/pppblrZfmr41RUlNUIDQ2Y2UyMTRmNGVkNyAzYjRmOWUwYzY3NTk0OWM5OTI2OTQ3NmU1ZjljMDdhOArnlLXop4bliacv5bey5a6M57uTL+mmluWtl+avjVVWV1ggZmU0NjgxZDdmYjQzIGJjYmNmZDM4ZDI1NDRmNWY5NTFlY2ZlNDMwNDgzMjAzCueUteinhuWJpy/lt7Llroznu5Mv6aaW5a2X5q+NWVogOGQ2NWU4ODViMDU5IDAzNmZkOTg5NWM0YjRhNDdhNTliMTcwNDY3MTU4MTZmCumfs+S5kC/kuabpppnpn7PkuZDkuJbnuqrlhbjol48gZDJkZmEzMjY0N2Y2IDE2N2FlOWVkZDNmZTQ2NjJhMmNlMzc3NTU5ZTM1ZjU4Cumfs+S5kC/lj6Tlhbjpn7PkuZDnsr7pgInlkIjpm4YgMmI0OTc4MjEzYjI5IDY5MDM4ZmYwOTAwNTRhMWViODgwMzEyYmU0Nzc1MzkyCumfs+S5kC/lpKfoh6rnhLbpn7PkuZDns7vliJflkIjpm4YgNjUxZTVmYTkzMDU3IDljOWYzMzM2NzgzZTQ4YWY5ZjQ3YzVlY2Q5OThlOTE0Cumfs+S5kC/nuq/pn7PkuZDlkIjpm4YgMTI4NDgzODFkY2UxIGFlMmNhZWI3ODQ2ZDRmODU4NDY3ZDJiNjI2ZDc4Y2EzCumfs+S5kC/ovabovb3ml6DmjZ/njq/nu5Xpn7PmlYjpn7PkuZDlkIjpm4YgODA1ZDc2YTA4MDYzIDU5M2Y5ODEwNGYxOTQzMDJhMjdhZTkxYmE3Y2QxOGRiCumfs+S5kC/pnIfmkrzlv4PngbXnmoTlj7Lor5fpn7PkuZDlkIjpm4YgZDFhMGI3MDQ2YjIwIDI5NGE1M2EzYzllODRlZjBhMGFjYzA0MTk1YzAyNWQ4Cgo="
GLOBAL_UA="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" # MacOS
GLOBAL_UA_2="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" # Windows
QUARK_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch"
UC_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) uc-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch"
ALL_METADATA_FILES=("all.mp4" "config.mp4" "115.mp4")
function get_default_network() {
_default_network=$(cat "${DDSREM_CONFIG_DIR}/default_network.txt")
if [ "${_default_network}" == "host" ]; then
echo '--net=host'
else
case "${1}" in
qrcode)
echo '-p 34256:34256'
;;
xiaoya-proxy)
echo '-p 9988:9988'
;;
xiaoya-aliyuntvtoken_connector)
echo '-p 34278:34278'
;;
esac
fi
}
function get_path() {
case "${OSNAME}" in
synology)
path_lib=/volume1/docker
;;
unraid)
path_lib=/mnt/user/appdata
;;
fnos)
if [ -d "/vol1/1000" ]; then
path_lib=/vol1/1000
fi
;;
macos)
if [ -n "${RUN_USER}" ]; then
path_lib="/Users/${RUN_USER}/Documents"
fi
;;
*)
if auto_path="$(df -h | awk '$2 ~ /G/ && $2+0 > 200 {print $6}' | grep -E -v "Avail|loop|boot|overlay|tmpfs|proc" | head -n 1)" > /dev/null 2>&1; then
if check_path "${auto_path}"; then
path_lib="${auto_path}"
fi
fi
;;
esac
if [ -z "${path_lib}" ]; then
case "${1}" in
xiaoya_alist_config_dir)
echo '/etc/xiaoya'
;;
xiaoya_alist_media_dir)
echo '/opt/media'
;;
esac
else
case "${1}" in
xiaoya_alist_config_dir)
echo "${path_lib}/xiaoya"
;;
xiaoya_alist_media_dir)
echo "${path_lib}/xiaoya_emby"
;;
esac
fi
}
function wait_emby_start() {
local CONTAINER_NAME TARGET_LOG_LINE_SUCCESS start_time
start_time=$(date +%s)
CONTAINER_NAME="$(cat "${DDSREM_CONFIG_DIR}"/container_name/xiaoya_emby_name.txt)"
TARGET_LOG_LINE_SUCCESS="All entry points have started"
while true; do
line=$(docker logs "$CONTAINER_NAME" 2>&1 | tail -n 10)
echo -e "$line"
current_time=$(date +%s)
elapsed_time=$((current_time - start_time))
if [[ "$line" == *"$TARGET_LOG_LINE_SUCCESS"* ]] && [ "$elapsed_time" -gt 60 ]; then
break
fi
if [ "$elapsed_time" -gt 900 ]; then
WARN "Emby 未正常启动超时 15 分钟!"
break
fi
sleep 8
done
}
function wait_xiaoya_start() {
local TARGET_LOG_LINE_SUCCESS start_time
start_time=$(date +%s)
TARGET_LOG_LINE_SUCCESS="success load storage: [/©️"
while true; do
line=$(docker logs "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" 2>&1 | tail -n 10)
echo -e "$line"
current_time=$(date +%s)
elapsed_time=$((current_time - start_time))
if [[ "$line" == *"$TARGET_LOG_LINE_SUCCESS"* ]] && [ "$elapsed_time" -gt 60 ]; then
break
fi
if [ "$elapsed_time" -gt 600 ]; then
WARN "小雅alist 未正常启动超时 10 分钟!"
break
fi
sleep 8
done
}
function check_quark_cookie() {
if [[ ! -f "${1}/quark_cookie.txt" ]] && [[ ! -s "${1}/quark_cookie.txt" ]]; then
return 1
fi
local cookie url headers response status url2 response2 member member_type vip_88
cookie=$(head -n1 "${1}/quark_cookie.txt")
url="https://drive-pc.quark.cn/1/clouddrive/config?pr=ucpro&fr=pc&uc_param_str="
headers="Cookie: $cookie; User-Agent: $QUARK_UA; Referer: https://pan.quark.cn"
response=$(curl -s -D - -H "$headers" "$url")
status=$(echo "$response" | grep -i status | cut -f2 -d: | cut -f1 -d,)
if [ "$status" == "401" ] || grep -qv "__puus" "${1}/quark_cookie.txt"; then
ERROR "无效夸克 Cookie"
return 1
elif [ "$status" == "200" ]; then
url2="https://drive-pc.quark.cn/1/clouddrive/member?pr=ucpro&fr=pc&uc_param_str=&fetch_subscribe=true&_ch=home&fetch_identity=true"
response2=$(curl -s -H "$headers" "$url2")
member=$(echo $response2 | grep -o '"member_type":"[^"]*"' | sed 's/"member_type":"\(.*\)"/\1/')
if [ $member == 'EXP_SVIP' ] || [ $member == 'SVIP' ]; then
vip_88=$(echo $response2 | grep -o '"vip88_new":[t|f]' | cut -f2 -d:)
if [ $vip_88 == 't' ]; then
member_type="88VIP会员"
else
member_type="SVIP会员"
fi
elif [ $member == 'NORMAL' ]; then
member_type="普通用户"
else
member_type="${member//\"/}会员"
fi
INFO "有效 夸克 Cookie,${member_type}"
return 0
else
ERROR "请求失败,请检查 Cookie 或网络连接是否正确。"
return 1
fi
}
function check_uc_cookie() {
if [[ ! -f "${1}/uc_cookie.txt" ]] && [[ ! -s "${1}/uc_cookie.txt" ]]; then
return 1
fi
local cookie url headers response status referer set_cookie
cookie=$(head -n1 "${1}/uc_cookie.txt")
referer="https://drive.uc.cn"
url="https://pc-api.uc.cn/1/clouddrive/file/sort?pr=UCBrowser&fr=pc&pdir_fid=0&_page=1&_size=50&_fetch_total=1&_fetch_sub_dirs=0&_sort=file_type:asc,updated_at:desc"
headers="Cookie: $cookie; User-Agent: $UC_UA; Referer: $referer"
response=$(curl -s -D - -H "$headers" "$url")
set_cookie=$(echo "$response" | grep -i "^Set-Cookie:" | sed 's/Set-Cookie: //')
status=$(echo "$response" | grep -i status | cut -f2 -d: | cut -f1 -d,)
if [ "$status" == "401" ] || grep -qv "__puus" "${1}/uc_cookie.txt"; then
ERROR "无效 UC Cookie"
return 1
elif [ -n "${set_cookie}" ]; then
local new_puus new_cookie
new_puus=$(echo "$set_cookie" | cut -f2 -d: | cut -f1 -d\;)
new_cookie=${cookie//__puus=[^;]*/$new_puus}
echo "$new_cookie" > ${1}/uc_cookie.txt
INFO "有效 UC Cookie 并更新"
return 0
elif [ -z "${set_cookie}" ] && [ "${status}" == "200" ]; then
INFO "有效 UC Cookie"
return 0
else
ERROR "请求失败,请检查 Cookie 或网络连接是否正确。"
return 1
fi
}
function check_115_cookie() {
if [[ ! -f "${1}/115_cookie.txt" ]] && [[ ! -s "${1}/115_cookie.txt" ]]; then
return 1
fi
local cookie url headers response vip
cookie=$(head -n1 "${1}/115_cookie.txt")
url="https://my.115.com/?ct=ajax&ac=nav"
headers="Cookie: $cookie; User-Agent: $GLOBAL_UA_2; Referer: https://115.com/"
response=$(curl -s -D - -H "$headers" "$url")
vip=$(echo -e "$response" | grep -o '"vip":[^,]*' | sed 's/"vip"://')
if echo -e "${response}" | grep -q "user_id"; then
if [ $vip == "0" ]; then
INFO "有效 115 Cookie,普通用户"
else
INFO "有效 115 Cookie,VIP用户"
fi
return 0
else
ERROR "请求失败,请检查 Cookie 或网络连接是否正确。"
return 1
fi
}
function check_aliyunpan_tvtoken() {
local token url response refresh_token data_dir
data_dir="${1}"
if [ -n "${2}" ]; then
token="${2}"
else
token=$(head -n1 "${data_dir}/myopentoken.txt")
fi
url=$(head -n1 "${data_dir}/open_tv_token_url.txt")
if ! response=$(curl -s "${url}" -X POST -H "User-Agent: $GLOBAL_UA" -H "Rererer: https://www.aliyundrive.com/" -H "Content-Type: application/json" -d '{"refresh_token":"'$token'", "grant_type": "refresh_token"}'); then
WARN "网络问题,无法检测 阿里云盘 TV Token 有效性"
return 0
fi
refresh_token=$(echo "$response" | sed 's/:\s*/:/g' | sed -n 's/.*"refresh_token":"\([^"]*\).*/\1/p')
if [ -n "${refresh_token}" ]; then
echo "${refresh_token}" > "${data_dir}/myopentoken.txt"
INFO "有效 阿里云盘 TV Token"
return 0
else
ERROR "无效 阿里云盘 TV Token"
return 1
fi
}
function check_aliyunpan_refreshtoken() {
local token referer response refresh_token data_dir
data_dir="${1}"
if [ -n "${2}" ]; then
token="${2}"
else
token=$(head -n1 "${data_dir}/mytoken.txt")
fi
referer=https://www.aliyundrive.com/
if ! response=$(curl -s https://auth.aliyundrive.com/v2/account/token -X POST -H "User-Agent: $GLOBAL_UA_2" -H "Content-Type:application/json" -H "Referer: $referer" -d '{"refresh_token":"'$token'", "grant_type": "refresh_token"}'); then
WARN "网络问题,无法检测 阿里云盘 Refresh Token 有效性"
return 0
fi
refresh_token=$(echo "$response" | sed 's/:\s*/:/g' | sed -n 's/.*"refresh_token":"\([^"]*\).*/\1/p')
if [ -n "${refresh_token}" ]; then
echo "${refresh_token}" > "${data_dir}/mytoken.txt"
INFO "有效 阿里云盘 Refresh Token"
return 0
else
ERROR "无效 阿里云盘 Refresh Token"
return 1
fi
}
function check_aliyunpan_opentoken() {
function cache_result() {
local file_path cache_path last_modified current_time difference current_hash
file_path="${1}"
cache_path="${2}"
if command -v md5sum > /dev/null 2>&1; then
current_hash=$(md5sum "$file_path" | awk '{ print $1 }')
else
current_hash=$(head -n 1 "$file_path")
fi
if [ -f "$cache_path" ] && [ "$(head -n 1 "$cache_path")" == "$current_hash" ]; then
if [[ "${OSNAME}" = "macos" ]]; then
last_modified=$(stat -f %m "$cache_path")
else
last_modified=$(date -r "$cache_path" +%s)
fi
current_time=$(date +%s)
difference=$(((current_time - last_modified) / 60))
if [ "$difference" -lt 60 ]; then
# 文件未更改且操作在60分钟内已执行,跳过此次执行
return 1
fi
fi
echo "$current_hash" > "$cache_path"
return 0
}
function cache_update() {
if [ "${3}" == true ]; then
if command -v md5sum > /dev/null 2>&1; then
md5sum "${1}" | awk '{ print $1 }' > "${2}"
else
head -n 1 "${1}" > "${2}"
fi
else
rm -f "${2}"
fi
}
local token response refresh_token data_dir
data_dir="${1}"
if [ -n "${2}" ]; then
token="${2}"
else
token=$(head -n1 "${data_dir}/myopentoken.txt")
fi
if cache_result "${data_dir}/myopentoken.txt" "${DDSREM_CONFIG_DIR}/cache_data/check_aliyunpan_opentoken.txt"; then
if ! response=$(curl -s "http://auth.xiaoya.pro/api/ali_open/refresh" -X POST -H "User-Agent: $GLOBAL_UA" -H "Rererer: https://www.aliyundrive.com/" -H "Content-Type: application/json" -d '{"refresh_token":"'$token'", "grant_type": "refresh_token"}'); then
WARN "网络问题,无法检测 阿里云盘 Open Token 有效性"
cache_update "${data_dir}/myopentoken.txt" "${DDSREM_CONFIG_DIR}/cache_data/check_aliyunpan_opentoken.txt" "false"
return 0
fi
refresh_token=$(echo "$response" | sed 's/:\s*/:/g' | sed -n 's/.*"refresh_token":"\([^"]*\).*/\1/p')
if [ -n "${refresh_token}" ]; then
echo "${refresh_token}" > "${data_dir}/myopentoken.txt"
INFO "有效 阿里云盘 Open Token"
cache_update "${data_dir}/myopentoken.txt" "${DDSREM_CONFIG_DIR}/cache_data/check_aliyunpan_opentoken.txt" "true"
return 0
else
ERROR "无效 阿里云盘 Open Token"
DEBUG "Response: ${response}"
cache_update "${data_dir}/myopentoken.txt" "${DDSREM_CONFIG_DIR}/cache_data/check_aliyunpan_opentoken.txt" "false"
return 1
fi
else
INFO "有效 阿里云盘 Open Token(缓存结果)"
return 0
fi
}
function qrcode_mode_choose() {
extra_parameters=
function qrcode_web() {
if ! check_port "34256"; then
ERROR "34256 端口被占用,请关闭占用此端口的程序!"
exit 1
fi
local local_ip
if [[ "${OSNAME}" = "macos" ]]; then
local_ip=$(ifconfig "$(route -n get default | grep interface | awk -F ':' '{print$2}' | awk '{$1=$1};1')" | grep 'inet ' | awk '{print$2}')
else
local_ip=$(ip address | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1 | cut -f1 -d"/")
fi
if [ -z "${local_ip}" ]; then
local_ip="小雅服务器IP"
fi
INFO "请浏览器访问 http://${local_ip}:34256 并使用手机APP扫描二维码!"
# shellcheck disable=SC2046
docker run -i --rm \
-v "${1}:/data" \
-e LANG=C.UTF-8 \
$(auto_privileged) \
$(get_default_network "qrcode") \
ddsderek/xiaoya-glue:python \
"${2}" --qrcode_mode=web ${extra_parameters}
}
if [ "${2}" == "/115cookie/115cookie.py" ]; then
while true; do
qrcode_apps=('alipaymini' 'web' 'ios' '115ios' 'android' '115android' '115ipad' 'tv' 'qandroid' 'wechatmini' 'harmony')
qrcode_app_names=('115生活(支付宝小程序)' '115生活(网页端)' '115生活(iOS端)' '115(iOS端)' '115生活(Android端)' '115(Android端)' '115(iPad端)' '115生活(Android电视端)' '115管理(Android端)' '115生活(微信小程序)' '115(鸿蒙端)')
find_qrcode_app=false
interface=
for i in "${!qrcode_apps[@]}"; do
interface="${interface}$((i + 1))、${qrcode_app_names[$i]} [${qrcode_apps[$i]}]\n"
done
INFO "请选择扫码绑定的设备(默认 1)"
echo -e "${interface}\c"
read -erp "QRCODE_APP:" QRCODE_APP_NUM
[[ -z "${QRCODE_APP_NUM}" ]] && QRCODE_APP_NUM="1"
for i in "${!qrcode_apps[@]}"; do
if [[ "$((i + 1))" == "${QRCODE_APP_NUM}" ]]; then
qrcode_app="${qrcode_apps[$i]}"
find_qrcode_app=true
break
fi
done
if [ "${find_qrcode_app}" == true ]; then
break
else
ERROR "输入无效,请重新选择"
fi
done
extra_parameters="--qrcode_app=${qrcode_app}"
elif [ "${2}" == "/aliyunopentoken/aliyunopentoken.py" ]; then
extra_parameters="--api_url=auth.xiaoya.pro"
INFO "使用 auth.xiaoya.pro 地址"
elif [ "${2}" == "/aliyuntoken/aliyuntoken.py" ]; then
if curl -Is "https://passport.aliyundrive.com/newlogin/qrcode/generate.do" | head -n 1 | grep -q '200'; then
extra_parameters="--api_url=base"
INFO "使用内置获取模块"
else
extra_parameters="--api_url=aliyuntoken.vercel.app"
INFO "使用 aliyuntoken.vercel.app 地址"
fi
fi
while true; do
INFO "请选择扫码模式 [ 1: 命令行扫码 | 2: 浏览器扫码 ](默认 2)"
read -erp "QRCODE_MODE:" QRCODE_MODE
[[ -z "${QRCODE_MODE}" ]] && QRCODE_MODE="2"
if [[ ${QRCODE_MODE} == [1] ]]; then
# shellcheck disable=SC2046
docker run -i --rm \
-v "${1}:/data" \
-e LANG=C.UTF-8 \
$(auto_privileged) \
ddsderek/xiaoya-glue:python \
"${2}" --qrcode_mode=shell ${extra_parameters}
return 0
elif [[ ${QRCODE_MODE} == [2] ]]; then
qrcode_web "${1}" "${2}"
return 0
else
ERROR "输入无效,请重新选择"
fi
done
}
function qrocde_common() {
clear_qrcode_container
if [ "${DOCKER_ARCH}" == "linux/amd64" ] || [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
INFO "${1} 扫码获取"
pull_glue_python_ddsrem
qrcode_mode_choose "${2}" "${3}"
INFO "操作全部完成!"
else
WARN "目前 ${1} 扫码获取只支持amd64和arm64架构,你的架构是:$CPU_ARCH"
fi
}
function enter_aliyunpan_refreshtoken() {
while true; do
INFO "是否使用扫码自动获取 阿里云盘 Token [Y/n](默认 Y)"
read -erp "Token:" choose_qrcode_aliyunpan_refreshtoken
[[ -z "${choose_qrcode_aliyunpan_refreshtoken}" ]] && choose_qrcode_aliyunpan_refreshtoken="y"
if [[ ${choose_qrcode_aliyunpan_refreshtoken} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_qrcode_aliyunpan_refreshtoken} == [Yy] ]]; then
qrocde_common "阿里云盘 Refresh Token" "${1}" "/aliyuntoken/aliyuntoken.py"
fi
mytokenfilesize=$(cat "${1}"/mytoken.txt)
mytokenstringsize=${#mytokenfilesize}
if [ "$mytokenstringsize" -le 31 ] || ! check_aliyunpan_refreshtoken "${1}"; then
if [[ ${choose_qrcode_aliyunpan_refreshtoken} == [Yy] ]]; then
WARN "扫码获取 阿里云盘 Token 失败,请手动获取!"
fi
while true; do
INFO "输入你的 阿里云盘 Token(32位长)"
read -erp "TOKEN:" token
token_len=${#token}
if [ "$token_len" -ne 32 ]; then
ERROR "长度不对,阿里云盘 Token是32位长"
ERROR "请参考指南配置文件: https://xiaoyaliu.notion.site/xiaoya-docker-69404af849504fa5bcf9f2dd5ecaa75f"
else
echo "$token" > "${1}"/mytoken.txt
if check_aliyunpan_refreshtoken "${1}"; then
break
fi
fi
done
fi
}
function settings_aliyunpan_refreshtoken() {
if [ "${2}" == "force" ]; then
enter_aliyunpan_refreshtoken "${1}"
elif [ "${2}" == "remove" ]; then
if [ -f "${1}/mytoken.txt" ]; then
rm -f "${1}/mytoken.txt"
fi
INFO "删除 mytoken.txt 成功!"
sleep 2
else
mytokenfilesize=$(cat "${1}"/mytoken.txt)
mytokenstringsize=${#mytokenfilesize}
if [ "$mytokenstringsize" -le 31 ] || ! check_aliyunpan_refreshtoken "${1}"; then
enter_aliyunpan_refreshtoken "${1}"
fi
fi
}
function enter_aliyunpan_opentoken() {
while true; do
INFO "是否使用扫码自动获取 阿里云盘 Open Token [Y/n](默认 Y)"
read -erp "Token:" choose_qrcode_aliyunpan_opentoken
[[ -z "${choose_qrcode_aliyunpan_opentoken}" ]] && choose_qrcode_aliyunpan_opentoken="y"
if [[ ${choose_qrcode_aliyunpan_opentoken} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_qrcode_aliyunpan_opentoken} == [Yy] ]]; then
qrocde_common "阿里云盘 Open Token" "${1}" "/aliyunopentoken/aliyunopentoken.py"
fi
myopentokenfilesize=$(cat "${1}"/myopentoken.txt)
myopentokenstringsize=${#myopentokenfilesize}
if [ "$myopentokenstringsize" -le 279 ] || ! check_aliyunpan_opentoken "${1}"; then
if [[ ${choose_qrcode_aliyunpan_opentoken} == [Yy] ]]; then
WARN "扫码获取 阿里云盘 Open Token 失败,请手动获取!"
fi
while true; do
INFO "输入你的 阿里云盘 Open Token(280位长或者335位长)"
read -erp "OPENTOKEN:" opentoken
opentoken_len=${#opentoken}
if [[ "$opentoken_len" -ne 280 ]] && [[ "$opentoken_len" -ne 335 ]]; then
ERROR "长度不对,阿里云盘 Open Token是280位长或者335位"
ERROR "请参考指南配置文件: https://xiaoyaliu.notion.site/xiaoya-docker-69404af849504fa5bcf9f2dd5ecaa75f"
else
echo "$opentoken" > "${1}"/myopentoken.txt
if check_aliyunpan_opentoken "${1}"; then
break
fi
fi
done
fi
}
function settings_aliyunpan_opentoken() {
if [ -f "${1}/open_tv_token_url.txt" ]; then
mv "${1}/open_tv_token_url.txt" "${1}/open_tv_token_url.txt.bak"
fi
if [ "${2}" == "force" ]; then
enter_aliyunpan_opentoken "${1}"
elif [ "${2}" == "remove" ]; then
if [ -f "${1}/myopentoken.txt" ]; then
rm -f "${1}/myopentoken.txt"
fi
INFO "删除 myopentoken.txt 成功!"
sleep 2
else
myopentokenfilesize=$(cat "${1}"/myopentoken.txt)
myopentokenstringsize=${#myopentokenfilesize}
if [ "$myopentokenstringsize" -le 279 ] || ! check_aliyunpan_opentoken "${1}"; then
enter_aliyunpan_opentoken "${1}"
fi
fi
}
function enter_115_cookie() {
touch_chmod "${1}/115_cookie.txt"
while true; do
INFO "是否使用扫码自动获取 115 Cookie [Y/n](默认 Y)"
read -erp "Cookie:" choose_qrcode_115_cookie
[[ -z "${choose_qrcode_115_cookie}" ]] && choose_qrcode_115_cookie="y"
if [[ ${choose_qrcode_115_cookie} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_qrcode_115_cookie} == [Yy] ]]; then
qrocde_common "115 Cookie" "${1}" "/115cookie/115cookie.py"
fi
if ! check_115_cookie "${1}"; then
if [[ ${choose_qrcode_115_cookie} == [Yy] ]]; then
WARN "扫码获取 115 Cookie 失败,请手动获取!"
fi
while true; do
INFO "输入你的 115 Cookie"
read -erp "Cookie:" set_115_cookie
echo -e "${set_115_cookie}" > ${1}/115_cookie.txt
if check_115_cookie "${1}"; then
break
fi
done
fi
}
function settings_115_cookie() {
if [ "${2}" == "force" ]; then
enter_115_cookie "${1}"
elif [ "${2}" == "remove" ]; then
if [ -f "${1}/115_cookie.txt" ]; then
rm -f "${1}/115_cookie.txt"
fi
INFO "删除 115_cookie.txt 成功!"
sleep 2
else
if [ ! -f "${1}/115_cookie.txt" ] || ! check_115_cookie "${1}"; then
while true; do
INFO "是否配置 115 Cookie [Y/n](默认 n 不配置)"
read -erp "Cookie:" choose_115_cookie
[[ -z "${choose_115_cookie}" ]] && choose_115_cookie="n"
if [[ ${choose_115_cookie} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_115_cookie} == [Yy] ]]; then
enter_115_cookie "${1}"
fi
fi
fi
}
function enter_quark_cookie() {
touch_chmod "${1}/quark_cookie.txt"
while true; do
INFO "是否使用扫码自动获取 夸克 Cookie [Y/n](默认 Y)"
read -erp "Cookie:" choose_qrcode_quark_cookie
[[ -z "${choose_qrcode_quark_cookie}" ]] && choose_qrcode_quark_cookie="y"
if [[ ${choose_qrcode_quark_cookie} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_qrcode_quark_cookie} == [Yy] ]]; then
qrocde_common "夸克 Cookie" "${1}" "/quark_cookie/quark_cookie.py"
fi
if ! check_quark_cookie "${1}"; then
if [[ ${choose_qrcode_quark_cookie} == [Yy] ]]; then
WARN "扫码获取 夸克 Cookie 失败,请手动获取!"
fi
while true; do
INFO "输入你的 夸克 Cookie"
read -erp "Cookie:" quark_cookie
echo -e "${quark_cookie}" > ${1}/quark_cookie.txt
if check_quark_cookie "${1}"; then
break
fi
done
fi
}
function settings_quark_cookie() {
if [ "${2}" == "force" ]; then
enter_quark_cookie "${1}"
elif [ "${2}" == "remove" ]; then
if [ -f "${1}/quark_cookie.txt" ]; then
rm -f "${1}/quark_cookie.txt"
fi
INFO "删除 quark_cookie.txt 成功!"
sleep 2
else
if [ ! -f "${1}/quark_cookie.txt" ] || ! check_quark_cookie "${1}"; then
while true; do
INFO "是否配置 夸克 Cookie [Y/n](默认 n 不配置)"
read -erp "Cookie:" choose_quark_cookie
[[ -z "${choose_quark_cookie}" ]] && choose_quark_cookie="n"
if [[ ${choose_quark_cookie} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_quark_cookie} == [Yy] ]]; then
enter_quark_cookie "${1}"
fi
fi
fi
}
function enter_uc_cookie() {
touch_chmod "${1}/uc_cookie.txt"
while true; do
INFO "是否使用扫码自动获取 UC Cookie [Y/n](默认 Y)"
read -erp "Cookie:" choose_qrcode_uc_cookie
[[ -z "${choose_qrcode_uc_cookie}" ]] && choose_qrcode_uc_cookie="y"
if [[ ${choose_qrcode_uc_cookie} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_qrcode_uc_cookie} == [Yy] ]]; then
qrocde_common "UC Cookie" "${1}" "/uc_cookie/uc_cookie.py"
fi
if ! check_uc_cookie "${1}"; then
if [[ ${choose_qrcode_uc_cookie} == [Yy] ]]; then
WARN "扫码获取 UC Cookie 失败,请手动获取!"
fi
while true; do
INFO "输入你的 UC Cookie"
read -erp "Cookie:" uc_cookie
echo -e "${uc_cookie}" > ${1}/uc_cookie.txt
if check_uc_cookie "${1}"; then
break
fi
done
fi
}
function settings_uc_cookie() {
if [ "${2}" == "force" ]; then
enter_uc_cookie "${1}"
elif [ "${2}" == "remove" ]; then
if [ -f "${1}/uc_cookie.txt" ]; then
rm -f "${1}/uc_cookie.txt"
fi
INFO "删除 uc_cookie.txt 成功!"
sleep 2
else
if [ ! -f "${1}/uc_cookie.txt" ] || ! check_uc_cookie "${1}"; then
while true; do
INFO "是否配置 UC Cookie [Y/n](默认 n 不配置)"
read -erp "Cookie:" choose_uc_cookie
[[ -z "${choose_uc_cookie}" ]] && choose_uc_cookie="n"
if [[ ${choose_uc_cookie} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_uc_cookie} == [Yy] ]]; then
enter_uc_cookie "${1}"
fi
fi
fi
}
function enter_ali2115() {
touch_chmod "${1}/ali2115.txt"
if [ -f "${1}/115_cookie.txt" ] && check_115_cookie "${1}"; then
INFO "自动获取 115 Cookie!"
set_115_cookie="$(cat ${1}/115_cookie.txt | head -n1)"
else
while true; do
INFO "输入你的 115 Cookie"
read -erp "Cookie:" set_115_cookie
if [ -n "${set_115_cookie}" ]; then
break
fi
done
fi
while true; do
INFO "是否自动删除115转存文件 [Y/n](默认 Y)"
read -erp "purge_pan115_temp:" purge_pan115_temp
[[ -z "${purge_pan115_temp}" ]] && purge_pan115_temp="y"
if [[ ${purge_pan115_temp} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
INFO "输入你的 115 转存文件夹 id(默认 auto)"
read -erp "dir_id:" dir_id
[[ -z "${dir_id}" ]] && dir_id="auto"
if [[ ${purge_pan115_temp} == [Yy] ]]; then
purge_pan115_temp=true
else
purge_pan115_temp=false
fi
echo -e "cookie=\"${set_115_cookie}\"\npurge_pan115_temp=${purge_pan115_temp}\ndir_id=${dir_id}" > ${1}/ali2115.txt
}
function settings_ali2115() {
if [ "${2}" == "force" ]; then
enter_ali2115 "${1}"
elif [ "${2}" == "remove" ]; then
if [ -f "${1}/ali2115.txt" ]; then
rm -f "${1}/ali2115.txt"
fi
INFO "删除 ali2115.txt 成功!"
sleep 2
else
if [ ! -f "${1}/ali2115.txt" ]; then
while true; do
INFO "是否配置 阿里转存115播放(ali2115.txt) [Y/n](默认 n 不配置)"
read -erp "ali2115:" ali2115_set
[[ -z "${ali2115_set}" ]] && ali2115_set="n"
if [[ ${ali2115_set} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${ali2115_set} == [Yy] ]]; then
enter_ali2115 "${1}"
fi
fi
fi
}
function get_aliyunpan_folder_id() {
clear_qrcode_container
if [ "${DOCKER_ARCH}" == "linux/amd64" ] || [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
INFO "阿里云盘 folder id 自动获取"
pull_glue_python_ddsrem
# shellcheck disable=SC2046
docker run -it --rm \
-v "${1}:/data" \
-e LANG=C.UTF-8 \
$(auto_privileged) \
ddsderek/xiaoya-glue:python \
/get_folder_id/get_folder_id.py --data_path='/data' --drive_mode=r
else
WARN "目前阿里云盘 folder id 自动获取只支持amd64和arm64架构,你的架构是:$CPU_ARCH"
fi
}
function settings_aliyunpan_folder_id() {
folderidfilesize=$(cat "${1}"/temp_transfer_folder_id.txt)
folderidstringsize=${#folderidfilesize}
if [ ! -f "${1}/temp_transfer_folder_id.txt" ] || [ "$folderidstringsize" -le 39 ]; then
while true; do
INFO "是否自动获取 阿里云盘转存目录 folder id [Y/n](默认 Y)"
read -erp "Token:" auto_get_folder_id
[[ -z "${auto_get_folder_id}" ]] && auto_get_folder_id="y"
if [[ ${auto_get_folder_id} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${auto_get_folder_id} == [Yy] ]]; then
get_aliyunpan_folder_id "${1}"
fi
folderidfilesize=$(cat "${1}"/temp_transfer_folder_id.txt)
folderidstringsize=${#folderidfilesize}
if [ "$folderidstringsize" -le 39 ]; then
while true; do
INFO "输入你的阿里云盘转存目录 folder id"
read -erp "FOLDERID:" folderid
folder_id_len=${#folderid}
if [ "$folder_id_len" -ne 40 ]; then
ERROR "长度不对,阿里云盘 folder id 是40位长"
ERROR "请参考指南配置文件: https://xiaoyaliu.notion.site/xiaoya-docker-69404af849504fa5bcf9f2dd5ecaa75f"
else
echo "$folderid" > "${1}"/temp_transfer_folder_id.txt
break
fi
done
fi
fi
}
function get_config_dir() {
local xiaoya_config_dir DEFAULT_CONFIG_DIR
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
xiaoya_config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/data$" | awk -F: '{print $1}')"
fi
while true; do
if [ -n "${xiaoya_config_dir}" ]; then
if [ ! -f "${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt" ] || [ -z "$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)" ]; then
echo "${xiaoya_config_dir}" > "${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt"
fi
if [ "${xiaoya_config_dir}" == "$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)" ]; then
INFO "小雅容器挂载目录与当前保存的小雅配置目录路径一致"
INFO "小雅配置目录通过小雅容器获取"
else
WARN "小雅容器挂载目录与当前保存的小雅配置目录路径不一致"
WARN "默认使用当前保存的小雅配置目录路径"
fi
xiaoya_config_dir=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
if [ -z "${xiaoya_config_dir}" ]; then
WARN "读取小雅Alist配置文件路径错误,请重新输入你的小雅Alist配置文件路径"
else
INFO "已读取小雅Alist配置文件路径:${xiaoya_config_dir} (默认不更改回车继续,如果需要更改请输入新路径)"
fi
read -erp "CONFIG_DIR:" CONFIG_DIR
[[ -z "${CONFIG_DIR}" ]] && CONFIG_DIR=${xiaoya_config_dir}
elif [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt ]; then
OLD_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
if [ -z "${OLD_CONFIG_DIR}" ]; then
WARN "读取小雅Alist配置文件路径错误,请重新输入你的小雅Alist配置文件路径"
else
INFO "已读取小雅Alist配置文件路径:${OLD_CONFIG_DIR} (默认不更改回车继续,如果需要更改请输入新路径)"
fi
read -erp "CONFIG_DIR:" CONFIG_DIR
[[ -z "${CONFIG_DIR}" ]] && CONFIG_DIR=${OLD_CONFIG_DIR}
else
DEFAULT_CONFIG_DIR="$(get_path "xiaoya_alist_config_dir")"
INFO "请输入配置文件目录(默认 ${DEFAULT_CONFIG_DIR} )"
read -erp "CONFIG_DIR:" CONFIG_DIR
[[ -z "${CONFIG_DIR}" ]] && CONFIG_DIR="${DEFAULT_CONFIG_DIR}"
touch "${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt"
fi
if check_path "${CONFIG_DIR}"; then
echo "${CONFIG_DIR}" > "${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt"
INFO "目录合法性检测通过!"
break
else
ERROR "非合法目录,请重新输入!"
fi
done
if [ -d "${CONFIG_DIR}" ]; then
INFO "读取配置目录中..."
# 将所有小雅配置文件修正成 linux 格式
if [[ "${OSNAME}" = "macos" ]]; then
find ${CONFIG_DIR} -maxdepth 1 -type f -name "*.txt" -exec sed -i '' "s/\r$//g" {} \;
else
find ${CONFIG_DIR} -maxdepth 1 -type f -name "*.txt" -exec sed -i "s/\r$//g" {} \;
fi
# 设置权限
find ${CONFIG_DIR} -maxdepth 1 -type f -exec chmod 777 {} \;
if [ -n "${GLOBAL_PUID}" ] && [ -n "${GLOBAL_PGID}" ]; then
find ${CONFIG_DIR} -maxdepth 1 -type f -exec chown "${GLOBAL_PUID}":"${GLOBAL_PGID}" {} \;
fi
fi
}
function get_media_dir() {
local media_dir DEFAULT_MEDIA_DIR
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt ]; then
XIAOYA_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
if [ -s "${XIAOYA_CONFIG_DIR}/emby_config.txt" ]; then
# shellcheck disable=SC1091
source "${XIAOYA_CONFIG_DIR}/emby_config.txt"
# shellcheck disable=SC2154
echo "${media_dir}" > ${DDSREM_CONFIG_DIR}/xiaoya_alist_media_dir.txt
INFO "媒体库目录通过 emby_config.txt 获取"
fi
fi
while true; do
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_media_dir.txt ]; then
OLD_MEDIA_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_media_dir.txt)
INFO "已读取媒体库目录:${OLD_MEDIA_DIR} (默认不更改回车继续,如果需要更改请输入新路径)"
read -erp "MEDIA_DIR:" MEDIA_DIR
[[ -z "${MEDIA_DIR}" ]] && MEDIA_DIR=${OLD_MEDIA_DIR}
else
DEFAULT_MEDIA_DIR="$(get_path "xiaoya_alist_media_dir")"
INFO "请输入媒体库目录(默认 ${DEFAULT_MEDIA_DIR} )"
read -erp "MEDIA_DIR:" MEDIA_DIR
[[ -z "${MEDIA_DIR}" ]] && MEDIA_DIR="${DEFAULT_MEDIA_DIR}"
touch "${DDSREM_CONFIG_DIR}/xiaoya_alist_media_dir.txt"
fi
if check_path "${MEDIA_DIR}"; then
echo "${MEDIA_DIR}" > "${DDSREM_CONFIG_DIR}/xiaoya_alist_media_dir.txt"
INFO "目录合法性检测通过!"
break
else
ERROR "非合法目录,请重新输入!"
fi
done
}
function main_account_management() {
function main_account_management_level_two() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}${1}${Font}\n"
echo -e "1、配置/更新"
echo -e "2、删除"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-2]:" num
case "$num" in
1)
clear
"${2}" "${3}" force
main_account_management
;;
2)
clear
"${2}" "${3}" remove
main_account_management
;;
0)
clear
main_account_management
;;
*)
clear
ERROR '请输入正确数字 [0-2]'
main_account_management_level_two "$@"
;;
esac
}
clear
local config_dir
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/data$" | awk -F: '{print $1}')"
fi
if [ -z "${config_dir}" ]; then
get_config_dir
config_dir=${CONFIG_DIR}
fi
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}账号管理${Font}\n"
echo -e "${Sky_Blue}小雅留言,会员购买指南:
基础版:阿里非会员+115会员
升级版:阿里svip+115会员(用TV token破解阿里svip的高速流量限制)
豪华版:阿里svip+第三方权益包+115会员
乞丐版:满足看emby画报但不要播放,播放用tvbox各种免费源${Font}\n"
echo -ne "${INFO} 界面加载中...${Font}\r"
echo -e "1、115 Cookie (当前:$(if [ -f "${config_dir}/115_cookie.txt" ]; then if CHECK_OUT=$(check_115_cookie "${config_dir}"); then echo -e "${Green}$(echo -e ${CHECK_OUT} | sed 's/\[.*\] //')${Font}"; else echo -e "${Red}错误${Font}"; fi; else echo -e "${Red}未配置${Font}"; fi))
2、夸克 Cookie (当前:$(if [ -f "${config_dir}/quark_cookie.txt" ]; then if CHECK_OUT=$(check_quark_cookie "${config_dir}"); then echo -e "${Green}$(echo -e ${CHECK_OUT} | sed 's/\[.*\] //')${Font}"; else echo -e "${Red}错误${Font}"; fi; else echo -e "${Red}未配置${Font}"; fi))
3、阿里云盘 Refresh Token(mytoken) (当前:$(if [ -f "${config_dir}/mytoken.txt" ]; then if CHECK_OUT=$(check_aliyunpan_refreshtoken "${config_dir}"); then echo -e "${Green}$(echo -e ${CHECK_OUT} | sed 's/\[.*\] //')${Font}"; else echo -e "${Red}错误${Font}"; fi; else echo -e "${Red}未配置${Font}"; fi))
4、阿里云盘 Open Token(myopentoken)(当前:$(if [ -f "${config_dir}/myopentoken.txt" ]; then if [ -f "${config_dir}/open_tv_token_url.txt" ]; then if CHECK_OUT=$(check_aliyunpan_tvtoken "${config_dir}"); then echo -e "${Green}$(echo -e ${CHECK_OUT} | sed 's/\[.*\] //')${Font}"; else echo -e "${Red}阿里云盘 TV Token 已失效${Font}"; fi; elif CHECK_OUT=$(check_aliyunpan_opentoken "${config_dir}"); then echo -e "${Green}$(echo -e ${CHECK_OUT} | sed 's/\[.*\] //')${Font}"; else echo -e "${Red}阿里云盘 Open Token 已失效${Font}"; fi; else echo -e "${Red}未配置${Font}"; fi))
5、UC Cookie (当前:$(if [ -f "${config_dir}/uc_cookie.txt" ]; then if CHECK_OUT=$(check_uc_cookie "${config_dir}"); then echo -e "${Green}$(echo -e ${CHECK_OUT} | sed 's/\[.*\] //')${Font}"; else echo -e "${Red}错误${Font}"; fi; else echo -e "${Red}未配置${Font}"; fi))
6、阿里转存115播放(ali2115.txt) (当前:$(if [ -f "${config_dir}/ali2115.txt" ]; then echo -e "${Green}已配置${Font}"; else echo -e "${Red}未配置${Font}"; fi))"
echo -e "7、应用配置(自动重启小雅,并返回上级菜单)"
echo -e "0、返回上级(从此处退出不会重启小雅,如果更改了上述配置请手动重启)"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-7]:" num
case "$num" in
1)
clear
main_account_management_level_two "115 Cookie" settings_115_cookie "${config_dir}"
;;
2)
clear
main_account_management_level_two "夸克 Cookie" settings_quark_cookie "${config_dir}"
;;
3)
clear
main_account_management_level_two "阿里云盘 Refresh Token(mytoken)" settings_aliyunpan_refreshtoken "${config_dir}"
;;
4)
clear
main_account_management_level_two "阿里云盘 Open Token(myopentoken)" settings_aliyunpan_opentoken "${config_dir}"
;;
5)
clear
main_account_management_level_two "UC Cookie" settings_uc_cookie "${config_dir}"
;;
6)
clear
main_account_management_level_two "阿里转存115播放(ali2115.txt)" settings_ali2115 "${config_dir}"
;;
7)
clear
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
INFO "重启小雅容器中..."
docker restart "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
wait_xiaoya_start
else
WARN "您未安装小雅,请先安装小雅容器!"
fi
if docker container inspect xiaoya-115cleaner > /dev/null 2>&1; then
docker restart xiaoya-115cleaner
fi
INFO "配置保存完成,按任意键返回菜单!"
read -rs -n 1 -p ""
clear
main_xiaoya_alist
;;
0)
clear
main_xiaoya_alist
;;
*)
clear
ERROR '请输入正确数字 [0-8]'
main_account_management
;;
esac
}
function install_xiaoya_alist() {
if [ ! -d "${CONFIG_DIR}" ]; then
mkdir -p "${CONFIG_DIR}"
auto_chown "${CONFIG_DIR}"
else
if [ -d "${CONFIG_DIR}"/mytoken.txt ]; then
rm -rf "${CONFIG_DIR}"/mytoken.txt
fi
fi
if [ ! -d "${CONFIG_DIR}/data" ]; then
mkdir -p "${CONFIG_DIR}/data"
auto_chown "${CONFIG_DIR}/data"
fi
if ! mkdir -p "${CONFIG_DIR}/watch"; then
ERROR "创建 watch 目录失败,已取消安装!"
return 1
fi
auto_chown "${CONFIG_DIR}/watch"
files=("mytoken.txt" "myopentoken.txt" "temp_transfer_folder_id.txt")
for file in "${files[@]}"; do
if [ ! -f "${CONFIG_DIR}/${file}" ]; then
touch_chmod "${CONFIG_DIR}/${file}"
fi
done
settings_aliyunpan_refreshtoken "${CONFIG_DIR}"
if [ -f "${CONFIG_DIR}/open_tv_token_url.txt" ]; then
check_aliyunpan_tvtoken "${CONFIG_DIR}"
else
settings_aliyunpan_opentoken "${CONFIG_DIR}"
fi
settings_aliyunpan_folder_id "${CONFIG_DIR}"
settings_quark_cookie "${CONFIG_DIR}"
if [ -f "${CONFIG_DIR}/quark_cookie.txt" ] && [ ! -f "${CONFIG_DIR}/quarkshare_list.txt" ] && command -v base64 > /dev/null 2>&1; then
while true; do
INFO "是否使用小雅官方分享的 quarkshare_list.txt 文件 [Y/n](默认 y)"
read -erp "quarkshare_list_choose:" quarkshare_list_choose
[[ -z "${quarkshare_list_choose}" ]] && quarkshare_list_choose="y"
if [[ ${quarkshare_list_choose} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${quarkshare_list_choose} == [Yy] ]]; then
echo "${quarkshare_list_base64}" | base64 --decode > "${CONFIG_DIR}/quarkshare_list.txt"
auto_chown "${CONFIG_DIR}/quarkshare_list.txt"
fi
fi
settings_uc_cookie "${CONFIG_DIR}"
settings_115_cookie "${CONFIG_DIR}"
if [ -f "${CONFIG_DIR}/115_cookie.txt" ] && [ ! -f "${CONFIG_DIR}/115share_list.txt" ] && command -v base64 > /dev/null 2>&1; then
while true; do
INFO "是否使用小雅官方分享的 115share_list.txt 文件 [Y/n](默认 y)"
read -erp "pan115share_list_choose:" pan115share_list_choose
[[ -z "${pan115share_list_choose}" ]] && pan115share_list_choose="y"
if [[ ${pan115share_list_choose} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${pan115share_list_choose} == [Yy] ]]; then
echo "${pan115share_list_base64}" | base64 --decode > "${CONFIG_DIR}/115share_list.txt"
auto_chown "${CONFIG_DIR}/115share_list.txt"
fi
fi
settings_ali2115 "${CONFIG_DIR}"
if [ ! -f "${CONFIG_DIR}/guestlogin.txt" ] || [ ! -f "${CONFIG_DIR}/guestpass.txt" ]; then
while true; do
INFO "是否开启强制登入 [Y/n](默认 y)"
WARN "不开启强制登入可能造成以下风险:"
WARN "1. 暴露到公网可能被坏人扫描到并无限制使用"
WARN "2. 多人异地访问可能触发网盘风控甚至封禁账号"
read -erp "force_login:" force_login
[[ -z "${force_login}" ]] && force_login="y"
if [[ ${force_login} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${force_login} == [Yy] ]]; then
INFO "强制登入用户名:dav(无法修改)"
while true; do
while true; do
INFO "请配置强制登入密码"
WARN "注意:输入的密码不会在终端显示"
read -ersp "PassWord: " password1
echo ""
if [[ -z "$password1" ]]; then
echo "错误:密码不能为空"
else
break
fi
done
INFO "请再次输入密码进行验证"
read -ersp "PassWord: " password2
echo ""
if [[ "$password1" == "$password2" ]]; then
INFO "密码设置成功"
break
else
ERROR "两次输入的密码不一致,请重新输入"
fi
done
touch "${CONFIG_DIR}/guestlogin.txt"
auto_chown "${CONFIG_DIR}/guestlogin.txt"
echo -e "${password1}" > "${CONFIG_DIR}/guestpass.txt"
auto_chown "${CONFIG_DIR}/guestpass.txt"
fi
fi
if [[ "${OSNAME}" = "macos" ]]; then
localip=$(ifconfig "$(route -n get default | grep interface | awk -F ':' '{print$2}' | awk '{$1=$1};1')" | grep 'inet ' | awk '{print$2}')
else
if command -v ifconfig > /dev/null 2>&1; then
localip=$(ifconfig -a | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1)
else
localip=$(ip address | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1 | cut -f1 -d"/")
fi
fi
INFO "本地IP:${localip}"
ports=(5678 2345 2346 2347)
for port in "${ports[@]}"; do
if ! check_port "${port}"; then
check_ports_result=false
fi
done
if [ "${check_ports_result}" == false ]; then
exit 1
fi
if [ "${SET_NET_MODE}" == true ]; then
while true; do
INFO "是否使用host网络模式 [Y/n](默认 n 不使用)"
read -erp "NET_MODE:" NET_MODE
[[ -z "${NET_MODE}" ]] && NET_MODE="n"
if [[ ${NET_MODE} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
fi
if [ ! -s "${CONFIG_DIR}"/docker_address.txt ]; then
echo "http://$localip:5678" > "${CONFIG_DIR}"/docker_address.txt
auto_chown "${CONFIG_DIR}/docker_address.txt"
fi
docker_command=("docker run" "-itd" "--privileged")
if [[ ${NET_MODE} == [Yy] ]]; then
docker_image="xiaoyaliu/alist:hostmode"
docker_command+=("--network=host")
else
docker_image="xiaoyaliu/alist:latest"
docker_command+=("-p 5678:80" "-p 2345:2345" "-p 2346:2346" "-p 2347:2347")
fi
if [[ -f ${CONFIG_DIR}/proxy.txt ]] && [[ -s ${CONFIG_DIR}/proxy.txt ]]; then
proxy_url=$(head -n1 "${CONFIG_DIR}"/proxy.txt)
docker_command+=("--env HTTP_PROXY=$proxy_url" "--env HTTPS_PROXY=$proxy_url" "--env no_proxy=*.aliyundrive.com")
fi
if [[ -f ${CONFIG_DIR}/local_dir.txt ]] && [[ -s ${CONFIG_DIR}/local_dir.txt ]]; then
strm_dir=$(head -n1 "${CONFIG_DIR}"/local_dir.txt | tr -d '\r\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [[ -n "${strm_dir}" ]] && [[ -d "${strm_dir}" ]]; then
docker_command+=("-v ${strm_dir}:/strm")
INFO "检测到 local_dir.txt 文件,将挂载 ${strm_dir} 到容器 /strm 目录"
else
WARN "local_dir.txt 文件中的路径无效或不存在: ${strm_dir}"
fi
fi
docker_command+=("-v $(printf '%q' "${CONFIG_DIR}:/data")" "-v $(printf '%q' "${CONFIG_DIR}/data:/www/data")" "-v $(printf '%q' "${CONFIG_DIR}/watch:/index/watch")" "--restart=always" "--name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" "$docker_image")
docker_pull "$docker_image"
if eval "${docker_command[*]}"; then
wait_xiaoya_start
INFO "安装完成!"
INFO "服务已成功启动,您可以根据使用需求尝试访问以下的地址:"
INFO "alist: ${Sky_Blue}http://ip:5678${Font}"
if [[ ${force_login} == [Yy] ]] || [[ -f "${CONFIG_DIR}/guestpass.txt" ]]; then
_password="$(head -n 1 "${CONFIG_DIR}/guestpass.txt")"
INFO "webdav: ${Sky_Blue}http://ip:5678/dav${Font}, 用户密码: ${Sky_Blue}dav/${_password}${Font}"
else
INFO "webdav: ${Sky_Blue}http://ip:5678/dav${Font}, 默认用户密码: ${Sky_Blue}dav/guest_Api789${Font}"
fi
INFO "tvbox: ${Sky_Blue}http://ip:5678/tvbox/my_ext_jar.json${Font}"
else
ERROR "安装失败!"
fi
}
function migrate_xiaoya_watch() {
local container_name="${1}" config_dir="${2}" migration_dir
if ! mkdir -p "${config_dir}/watch"; then
ERROR "创建 watch 目录失败,已取消更新!"
return 1
fi
migration_dir=$(mktemp -d "${config_dir}/.watch-migration.XXXXXX") || return 1
if docker cp "${container_name}:/index/watch/." "${migration_dir}/watch" 2> "${migration_dir}/error"; then
if ! cp -a "${config_dir}/watch/." "${migration_dir}/watch/" ||
! cp -a "${migration_dir}/watch/." "${config_dir}/watch/"; then
ERROR "迁移 watch 目录失败,已取消更新!临时数据保留在 ${migration_dir}"
return 1
fi
elif grep -Eq 'Could not find the file /index/watch(/\.)? in container' "${migration_dir}/error"; then
INFO "旧容器没有 /index/watch 目录,将使用配置目录下的 watch 目录"
else
cat "${migration_dir}/error" >&2
rm -rf "${migration_dir}"
ERROR "读取旧容器 watch 目录失败,已取消更新以保留原容器!"
return 1
fi
rm -rf "${migration_dir}"
auto_chown "${config_dir}/watch"
}
function update_xiaoya_alist() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始更新小雅Alist${Blue} $i ${Font}\r"
sleep 1
done
xiaoya_name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
local config_dir watch_mount watch_volume watch_sed update_status=0
local container_update_extra_command container_update_before_remove_command
if docker container inspect "${xiaoya_name}" > /dev/null 2>&1; then
config_dir="$(docker inspect --format='{{range .Mounts}}{{if and (eq .Type "bind") (eq .Destination "/data")}}{{.Source}}{{end}}{{end}}' "${xiaoya_name}")" || return 1
watch_mount="$(docker inspect --format='{{range .Mounts}}{{if eq .Destination "/index/watch"}}{{.Destination}}{{end}}{{end}}' "${xiaoya_name}")" || return 1
if [ -z "${watch_mount}" ]; then
if [ -z "${config_dir}" ]; then
ERROR "无法获取小雅配置文件目录,已取消更新!"
return 1
fi
# shellcheck disable=SC2034
printf -v container_update_before_remove_command 'migrate_xiaoya_watch %q %q' "${xiaoya_name}" "${config_dir}"
fi
fi
cat > "/tmp/container_update_xiaoya_alist_run.sh" <<- EOF
#!/bin/bash
if [[ "\$(uname -s)" == "Darwin" ]]; then
_sedsh() { sed -i '' "\$@"; }
else
_sedsh() { sed -i "\$@"; }
fi
if ! grep -q 'network=host' "/tmp/container_update_${xiaoya_name}"; then
if ! grep -q '2347' "/tmp/container_update_${xiaoya_name}"; then
_sedsh '2s/^/-p 2347:2347 /' "/tmp/container_update_${xiaoya_name}"
fi
fi
if ! grep -q 'privileged' "/tmp/container_update_${xiaoya_name}"; then
_sedsh '2s/^/--privileged /' "/tmp/container_update_${xiaoya_name}"
fi
EOF
if [ -n "${config_dir}" ] && [ -z "${watch_mount}" ]; then
printf -v watch_volume '%q' "${config_dir}/watch:/index/watch"
watch_sed=$(printf '%s' "${watch_volume}" | sed 's/[\\&|]/\\&/g')
printf '_sedsh %q %q\n' "2s|^|-v ${watch_sed} |" "/tmp/container_update_${xiaoya_name}" >> /tmp/container_update_xiaoya_alist_run.sh
INFO "将在更新时添加 ${config_dir}/watch 到容器 /index/watch 目录挂载"
fi
if [[ -n "${config_dir}" ]] && [[ -f ${config_dir}/local_dir.txt ]] && [[ -s ${config_dir}/local_dir.txt ]]; then
strm_dir=$(head -n1 "${config_dir}"/local_dir.txt | tr -d '\r\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [[ -n "${strm_dir}" ]] && [[ -d "${strm_dir}" ]]; then
cat >> "/tmp/container_update_xiaoya_alist_run.sh" <<- EOF
if ! grep -q ':/strm' "/tmp/container_update_${xiaoya_name}"; then
_sedsh '2s|$| -v ${strm_dir}:/strm|' "/tmp/container_update_${xiaoya_name}"
fi
EOF
INFO "检测到 local_dir.txt 文件,将在更新时添加 ${strm_dir} 到容器 /strm 目录挂载"
fi
fi
container_update_extra_command="bash /tmp/container_update_xiaoya_alist_run.sh"
container_update "${xiaoya_name}" || update_status=$?
rm -f /tmp/container_update_xiaoya_alist_run.sh
if [ "${update_status}" -ne 0 ]; then
return "${update_status}"
fi
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" > /dev/null 2>&1; then
if [[ "$(docker inspect -f '{{range $key, $value := .NetworkSettings.Networks}}{{$key}} {{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)")" == *"only_for_emby"* ]]; then
if [[ "$(docker inspect -f '{{range $key, $value := .NetworkSettings.Networks}}{{$key}} {{end}}' "${xiaoya_name}")" == *"bridge"* ]]; then
INFO "Emby 为屏蔽 6908 端口模式,自动加入网络中..."
docker network connect only_for_emby "${xiaoya_name}"
INFO "加入 only_for_emby 网络成功!"
fi
fi
fi
}
function uninstall_xiaoya_alist() {
while true; do
INFO "是否${Red}删除配置文件${Font} [Y/n](默认 Y 删除)"
read -erp "Clean config:" CLEAN_CONFIG
[[ -z "${CLEAN_CONFIG}" ]] && CLEAN_CONFIG="y"
if [[ ${CLEAN_CONFIG} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载小雅Alist${Blue} $i ${Font}\r"
sleep 1
done
IMAGE_NAME="$(docker inspect --format='{{.Config.Image}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)")"
VOLUMES="$(docker inspect -f '{{range .Mounts}}{{if eq .Type "volume"}}{{println .}}{{end}}{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" | cut -d' ' -f2 | awk 'NF' | tr '\n' ' ')"
docker stop "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
docker rm "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
docker rmi "${IMAGE_NAME}"
docker volume rm ${VOLUMES}
if [[ ${CLEAN_CONFIG} == [Yy] ]]; then
INFO "清理配置文件..."
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt ]; then
OLD_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
for file in "${OLD_CONFIG_DIR}/mycheckintoken.txt" "${OLD_CONFIG_DIR}/mycmd.txt" "${OLD_CONFIG_DIR}/myruntime.txt"; do
if [ -f "$file" ]; then
mv -f "$file" "/tmp/$(basename "$file")"
fi
done
rm -rf \
${OLD_CONFIG_DIR}/*.txt* \
${OLD_CONFIG_DIR}/*.m3u* \
${OLD_CONFIG_DIR}/*.m3u8*
if [ -d "${OLD_CONFIG_DIR}/xiaoya_backup" ]; then
rm -rf ${OLD_CONFIG_DIR}/xiaoya_backup
fi
for file in /tmp/mycheckintoken.txt /tmp/mycmd.txt /tmp/myruntime.txt; do
if [ -f "$file" ]; then
mv -f "$file" "${OLD_CONFIG_DIR}/$(basename "$file")"
fi
done
fi
fi
INFO "小雅Alist卸载成功!"
}
function judgment_xiaoya_alist_sync_data_status() {
if command -v crontab > /dev/null 2>&1; then
if crontab -l | grep 'xiaoya_data_downloader' > /dev/null 2>&1; then
echo -e "${Green}已创建${Font}"
else
echo -e "${Red}未创建${Font}"
fi
elif [ -f /etc/synoinfo.conf ]; then
if grep 'xiaoya_data_downloader' /etc/crontab > /dev/null 2>&1; then
echo -e "${Green}已创建${Font}"
else
echo -e "${Red}未创建${Font}"
fi
else
echo -e "${Red}未知${Font}"
fi
}
function show_xiaoya_non_intranet_ip() {
local output
output=
if ! docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
ERROR "小雅容器未安装,无法查看!"
else
if [ "$(docker inspect --format='{{.State.Status}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)")" != "running" ]; then
ERROR "小雅容器未启动,无法查看!"
else
if ! docker exec -it "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" cat /opt/alist/log/alist.log > /dev/null 2>&1; then
INFO "无非内网IP访问次数记录"
else
output="$(docker exec -it "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" bash -c 'cat /opt/alist/log/alist.log | grep -v -i fail | grep -o "([0-9]{1,3}\\.){3}[0-9]{1,3}" | grep -v "172\\.17|127\\.0|192\\.168" | sort | uniq -c | head -n10 | sed "s/^[ \t]*//"')"
if [ -n "${output}" ]; then
INFO "非内网IP访问次数情况:"
echo -e "${output}"
else
INFO "无非内网IP访问次数记录"
fi
fi
fi
fi
}
function uninstall_xiaoya_alist_sync_data() {
if command -v crontab > /dev/null 2>&1; then
crontab -l > /tmp/cronjob.tmp
sedsh '/xiaoya_data_downloader/d' /tmp/cronjob.tmp
crontab /tmp/cronjob.tmp
rm -f /tmp/cronjob.tmp
elif [ -f /etc/synoinfo.conf ]; then
sedsh '/xiaoya_data_downloader/d' /etc/crontab
fi
}
function judgment_xiaoya_restart_cron_status() {
if command -v crontab > /dev/null 2>&1; then
if crontab -l | grep 'xiaoya_restart_cron' > /dev/null 2>&1; then
echo -e "${Green}已创建${Font}"
else
echo -e "${Red}未创建${Font}"
fi
elif [ -f /etc/synoinfo.conf ]; then
if grep 'xiaoya_restart_cron' /etc/crontab > /dev/null 2>&1; then
echo -e "${Green}已创建${Font}"
else
echo -e "${Red}未创建${Font}"
fi
else
echo -e "${Red}未知${Font}"
fi
}
function install_xiaoya_restart_cron() {
local hour minu xiaoya_name
xiaoya_name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
if ! docker container inspect "${xiaoya_name}" > /dev/null 2>&1; then
ERROR "小雅容器未安装,无法创建定时重启任务!"
return 1
fi
INFO "请输入定时重启的时间(24小时制)"
while true; do
read -erp "小时 [0-23](默认 3):" hour
[[ -z "${hour}" ]] && hour="3"
if [[ "${hour}" =~ ^[0-9]+$ ]] && [ "${hour}" -ge 0 ] && [ "${hour}" -le 23 ]; then
break
else
ERROR "请输入 0-23 之间的数字"
fi
done
while true; do
read -erp "分钟 [0-59](默认 0):" minu
[[ -z "${minu}" ]] && minu="0"
if [[ "${minu}" =~ ^[0-9]+$ ]] && [ "${minu}" -ge 0 ] && [ "${minu}" -le 59 ]; then
break
else
ERROR "请输入 0-59 之间的数字"
fi
done
CRON="${minu} ${hour} * * * docker restart \"${xiaoya_name}\" >> /tmp/xiaoya_restart_cron.log 2>&1 # xiaoya_restart_cron"
if command -v crontab > /dev/null 2>&1; then
crontab -l > /tmp/cronjob.tmp 2> /dev/null || true
sedsh '/xiaoya_restart_cron/d' /tmp/cronjob.tmp
echo -e "${CRON}" >> /tmp/cronjob.tmp
crontab /tmp/cronjob.tmp
INFO '已经添加下面的记录到crontab定时任务'
INFO "${CRON}"
rm -rf /tmp/cronjob.tmp
elif [ -f /etc/synoinfo.conf ]; then
cp /etc/crontab /etc/crontab.bak
INFO "已创建/etc/crontab.bak备份文件"
sedsh '/xiaoya_restart_cron/d' /etc/crontab
echo -e "${CRON}" >> /etc/crontab
INFO '已经添加下面的记录到crontab定时任务'
INFO "${CRON}"
else
ERROR "系统不支持 crontab,无法创建定时任务!"
return 1
fi
INFO "定时重启小雅任务创建成功!将在每天 ${hour}:${minu} 执行重启"
}
function uninstall_xiaoya_restart_cron() {
if command -v crontab > /dev/null 2>&1; then
crontab -l > /tmp/cronjob.tmp 2> /dev/null || true
sedsh '/xiaoya_restart_cron/d' /tmp/cronjob.tmp
crontab /tmp/cronjob.tmp
rm -f /tmp/cronjob.tmp
INFO "已删除定时重启小雅任务"
elif [ -f /etc/synoinfo.conf ]; then
sedsh '/xiaoya_restart_cron/d' /etc/crontab
INFO "已删除定时重启小雅任务"
else
ERROR "系统不支持 crontab,无法删除定时任务!"
return 1
fi
}
function main_xiaoya_restart_cron() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}定时重启小雅${Font}\n"
echo -e "1、创建定时重启任务"
echo -e "2、删除定时重启任务"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-2]:" num
case "$num" in
1)
clear
if command -v crontab > /dev/null 2>&1; then
if crontab -l | grep 'xiaoya_restart_cron' > /dev/null 2>&1; then
WARN "定时重启任务已存在,是否删除后重新创建?"
read -erp "请输入 [Y/n]:" confirm
if [[ "${confirm}" == [Yy] ]] || [[ -z "${confirm}" ]]; then
uninstall_xiaoya_restart_cron
sleep 1
else
INFO "已取消操作"
return_menu "main_xiaoya_restart_cron"
return
fi
fi
elif [ -f /etc/synoinfo.conf ]; then
if grep 'xiaoya_restart_cron' /etc/crontab > /dev/null 2>&1; then
WARN "定时重启任务已存在,是否删除后重新创建?"
read -erp "请输入 [Y/n]:" confirm
if [[ "${confirm}" == [Yy] ]] || [[ -z "${confirm}" ]]; then
uninstall_xiaoya_restart_cron
sleep 1
else
INFO "已取消操作"
return_menu "main_xiaoya_restart_cron"
return
fi
fi
fi
install_xiaoya_restart_cron
INFO "按任意键返回菜单"
read -rs -n 1 -p ""
clear
main_xiaoya_restart_cron
;;
2)
clear
if command -v crontab > /dev/null 2>&1; then
if crontab -l | grep 'xiaoya_restart_cron' > /dev/null 2>&1; then
for i in $(seq -w 3 -1 0); do
echo -en "即将删除定时重启小雅任务${Blue} $i ${Font}\r"
sleep 1
done
uninstall_xiaoya_restart_cron
clear
INFO "已删除"
else
WARN "定时重启任务不存在!"
fi
elif [ -f /etc/synoinfo.conf ]; then
if grep 'xiaoya_restart_cron' /etc/crontab > /dev/null 2>&1; then
for i in $(seq -w 3 -1 0); do
echo -en "即将删除定时重启小雅任务${Blue} $i ${Font}\r"
sleep 1
done
uninstall_xiaoya_restart_cron
clear
INFO "已删除"
else
WARN "定时重启任务不存在!"
fi
else
ERROR "系统不支持 crontab,无法删除定时任务!"
fi
INFO "按任意键返回菜单"
read -rs -n 1 -p ""
clear
main_xiaoya_restart_cron
;;
0)
clear
main_xiaoya_alist
;;
*)
clear
ERROR '请输入正确数字 [0-2]'
main_xiaoya_restart_cron
;;
esac
}
function main_xiaoya_alist() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}小雅Alist${Font}\n"
echo -e "1、安装"
echo -e "2、更新"
echo -e "3、卸载"
echo -e "4、账号管理"
echo -e "5、非内网IP访问次数查看"
echo -e "6、定时重启小雅 当前状态:$(judgment_xiaoya_restart_cron_status)"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-6]:" num
case "$num" in
1)
clear
get_config_dir
SET_NET_MODE=true
install_xiaoya_alist
return_menu "main_xiaoya_alist"
;;
2)
clear
update_xiaoya_alist
return_menu "main_xiaoya_alist"
;;
3)
clear
uninstall_xiaoya_alist
return_menu "main_xiaoya_alist"
;;
4)
clear
main_account_management
;;
5)
clear
show_xiaoya_non_intranet_ip
INFO "按任意键返回菜单"
read -rs -n 1 -p ""
clear
main_xiaoya_alist
;;
6)
clear
main_xiaoya_restart_cron
;;
0)
clear
main_return
;;
*)
clear
ERROR '请输入正确数字 [0-6]'
main_xiaoya_alist
;;
esac
}
function get_docker0_url() {
if command -v ifconfig > /dev/null 2>&1; then
docker0=$(ifconfig docker0 | awk '/inet / {print $2}' | sed 's/addr://')
else
docker0=$(ip addr show docker0 | awk '/inet / {print $2}' | cut -d '/' -f 1)
fi
if [ -n "$docker0" ]; then
INFO "docker0 的 IP 地址是:$docker0"
else
WARN "无法获取 docker0 的 IP 地址!"
if [[ "${OSNAME}" = "macos" ]]; then
docker0=$(ifconfig "$(route -n get default | grep interface | awk -F ':' '{print$2}' | awk '{$1=$1};1')" | grep 'inet ' | awk '{print$2}')
else
docker0=$(ip address | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1 | cut -f1 -d"/")
fi
INFO "尝试使用本地IP:${docker0}"
fi
}
function get_sign() {
if [ ! -f "${1}"/nosign.txt ] && [ -f "${1}"/guestpass.txt ] && [ -f "${1}"/guestlogin.txt ]; then
sign="?sign=$(docker exec -i "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" bash -c "if [ -f /index/md5 ]; then cat /index/md5 | head -n 1; else cat /data/guestpass.txt | tr -d '\r\n' | md5sum | awk '{print \$1}'; fi")"
echo "${sign}"
fi
}
function test_xiaoya_status() {
get_docker0_url
INFO "测试xiaoya的联通性..."
if curl -siL -m 10 "http://127.0.0.1:5678/d/README.md$(get_sign "${CONFIG_DIR}")" | grep -e "x-oss-" -e "x-115-request-id"; then
xiaoya_addr="http://127.0.0.1:5678"
elif curl -siL -m 10 "http://${docker0}:5678/d/README.md$(get_sign "${CONFIG_DIR}")" | grep -e "x-oss-" -e "x-115-request-id"; then
xiaoya_addr="http://${docker0}:5678"
else
if [ -s ${CONFIG_DIR}/docker_address.txt ]; then
docker_address=$(head -n1 ${CONFIG_DIR}/docker_address.txt)
if curl -siL -m 10 "${docker_address}/d/README.md$(get_sign "${CONFIG_DIR}")" | grep -e "x-oss-" -e "x-115-request-id"; then
xiaoya_addr=${docker_address}
else
__xiaoya_connectivity_detection=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_connectivity_detection.txt)
if [ "${__xiaoya_connectivity_detection}" == "false" ]; then
xiaoya_addr=${docker_address}
WARN "您已设置跳过小雅连通性检测"
else
ERROR "请检查xiaoya是否正常运行后再试"
ERROR "小雅日志如下:"
docker logs --tail 8 "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
exit 1
fi
fi
else
ERROR "请先配置 ${CONFIG_DIR}/docker_address.txt 后重试"
exit 1
fi
fi
INFO "连接小雅地址为 ${xiaoya_addr}"
}
function test_disk_capacity() {
if [ ! -d "${MEDIA_DIR}" ]; then
mkdir -p "${MEDIA_DIR}"
auto_chown "${MEDIA_DIR}"
fi
free_size=$(df -P "${MEDIA_DIR}" | tail -n1 | awk '{print $4}')
free_size=$((free_size))
free_size_G=$((free_size / 1024 / 1024))
__disk_capacity_detection=$(cat ${DDSREM_CONFIG_DIR}/disk_capacity_detection.txt)
if [ "${__disk_capacity_detection}" == "false" ]; then
WARN "您已设置跳过磁盘容量检测"
INFO "磁盘容量:${free_size_G}G"
else
if [ "$free_size" -le 314572800 ]; then
ERROR "空间剩余容量不够:${free_size_G}G 小于最低要求 300G"
exit 1
else
INFO "磁盘容量:${free_size_G}G"
fi
fi
}
function show_disk_capacity() {
free_size=$(df -P "${1}" | tail -n1 | awk '{print $4}')
free_size=$((free_size))
free_size_G=$((free_size / 1024 / 1024))
INFO "磁盘容量:${free_size_G}G"
}
function pull_run_glue() {
if docker inspect xiaoyaliu/glue:latest > /dev/null 2>&1; then
local_sha=$(docker inspect --format='{{index .RepoDigests 0}}' xiaoyaliu/glue:latest 2> /dev/null | cut -f2 -d:)
remote_sha=$(curl -s -m 10 "https://hub.docker.com/v2/repositories/xiaoyaliu/glue/tags/latest" | grep -o '"digest":"[^"]*' | grep -o '[^"]*$' | tail -n1 | cut -f2 -d:)
if [ "$local_sha" != "$remote_sha" ]; then
docker rmi xiaoyaliu/glue:latest
docker_pull "xiaoyaliu/glue:latest"
fi
else
docker_pull "xiaoyaliu/glue:latest"
fi
if [ -n "${extra_parameters}" ]; then
# shellcheck disable=SC2046
docker run -it \
--security-opt seccomp=unconfined \
--rm \
--net=host \
-v "${MEDIA_DIR}:/media" \
-v "${CONFIG_DIR}:/etc/xiaoya" \
${extra_parameters} \
$(auto_privileged) \
-e LANG=C.UTF-8 \
-e TZ=Asia/Shanghai \
xiaoyaliu/glue:latest \
"${@}"
else
# shellcheck disable=SC2046
docker run -it \
--security-opt seccomp=unconfined \
--rm \
--net=host \
-v "${MEDIA_DIR}:/media" \
-v "${CONFIG_DIR}:/etc/xiaoya" \
$(auto_privileged) \
-e LANG=C.UTF-8 \
-e TZ=Asia/Shanghai \
xiaoyaliu/glue:latest \
"${@}"
fi
}
function pull_run_glue_xh() {
BUILDER_NAME="xiaoya_builder_$(date +%S%N | cut -c 7-11)"
if docker inspect xiaoyaliu/glue:latest > /dev/null 2>&1; then
local_sha=$(docker inspect --format='{{index .RepoDigests 0}}' xiaoyaliu/glue:latest 2> /dev/null | cut -f2 -d:)
remote_sha=$(curl -s -m 10 "https://hub.docker.com/v2/repositories/xiaoyaliu/glue/tags/latest" | grep -o '"digest":"[^"]*' | grep -o '[^"]*$' | tail -n1 | cut -f2 -d:)
if [ "$local_sha" != "$remote_sha" ]; then
docker rmi xiaoyaliu/glue:latest
docker_pull "xiaoyaliu/glue:latest"
fi
else
docker_pull "xiaoyaliu/glue:latest"
fi
if [ -n "${extra_parameters}" ]; then
# shellcheck disable=SC2046
docker run -itd \
--security-opt seccomp=unconfined \
--name=${BUILDER_NAME} \
--net=host \
-v "${MEDIA_DIR}:/media" \
-v "${CONFIG_DIR}:/etc/xiaoya" \
$(auto_privileged) \
${extra_parameters} \
-e LANG=C.UTF-8 \
xiaoyaliu/glue:latest \
"${@}" > /dev/null 2>&1
else
# shellcheck disable=SC2046
docker run -itd \
--security-opt seccomp=unconfined \
--name=${BUILDER_NAME} \
--net=host \
-v "${MEDIA_DIR}:/media" \
-v "${CONFIG_DIR}:/etc/xiaoya" \
$(auto_privileged) \
-e LANG=C.UTF-8 \
xiaoyaliu/glue:latest \
"${@}" > /dev/null 2>&1
fi
timeout=20
start_time=$(date +%s)
end_time=$((start_time + timeout))
while [ "$(date +%s)" -lt $end_time ]; do
status=$(docker inspect -f '{{.State.Status}}' "${BUILDER_NAME}")
if [ "$status" = "exited" ]; then
break
fi
sleep 1
done
status=$(docker inspect -f '{{.State.Status}}' "${BUILDER_NAME}")
if [ "$status" != "exited" ]; then
docker kill ${BUILDER_NAME} > /dev/null 2>&1
fi
docker rm ${BUILDER_NAME} > /dev/null 2>&1
}
function get_emby_version() {
local emby_name emby_image_name emby_config_dir CURRENT_ULIMIT
emby_name=$(cat "${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt")
if ! docker container inspect "${emby_name}" > /dev/null 2>&1; then
WARN "未检测到 Emby 容器,请确保您已安装 Emby!"
return 1
fi
emby_image_name="$(docker container inspect -f '{{.Config.Image}}' "${emby_name}")"
if [ -z "${emby_image_name}" ]; then
WARN "获取 Emby 镜像标签失败"
return 1
fi
emby_config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "${emby_name}" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/config$" | awk -F: '{print $1}')"
if [ -z "${emby_config_dir}" ] || ! check_path "${emby_config_dir}"; then
WARN "Emby 配置目录获取失败,使用 /tmp 目录替代!"
emby_config_dir=/tmp
fi
if [ -f "${emby_config_dir}/EmbyServer.deps.json" ]; then
rm -f "${emby_config_dir}/EmbyServer.deps.json"
fi
CURRENT_ULIMIT=$(ulimit -n)
ulimit -n 65535
docker run --rm --ulimit nofile=65535:65535 --entrypoint cp -v "${emby_config_dir}:/data" "${emby_image_name}" /system/EmbyServer.deps.json /data
ulimit -n "${CURRENT_ULIMIT}"
if [ ! -f "${emby_config_dir}/EmbyServer.deps.json" ]; then
WARN "Emby 版本数据文件复制失败!"
return 1
fi
emby_version=$(grep "EmbyServer" "${emby_config_dir}/EmbyServer.deps.json" | head -n 1 | sed -n 's|.*EmbyServer/\(.*\)":.*|\1|p')
rm -f "${emby_config_dir}/EmbyServer.deps.json"
if [ -z "${emby_version}" ]; then
WARN "当前 Emby 版本获取失败!"
return 1
fi
return 0
}
function set_emby_server() {
get_docker0_url
if [[ "${OSNAME}" = "macos" ]]; then
local_ip=$(ifconfig "$(route -n get default | grep interface | awk -F ':' '{print$2}' | awk '{$1=$1};1')" | grep 'inet ' | awk '{print$2}')
else
local_ip=$(ip address | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1 | cut -f1 -d"/")
fi
if docker exec -i "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" curl -I -s "http://127.0.0.1:6908" | grep -m1 "^HTTP/" | grep -q "302"; then
INFO "使用 127.0.0.1 IP 配置 emby_server.txt"
echo "http://127.0.0.1:6908" > "${CONFIG_DIR}"/emby_server.txt
elif docker exec -i "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" curl -I -s "http://$docker0:6908" | grep -m1 "^HTTP/" | grep -q "302"; then
INFO "使用 $docker0 IP 配置 emby_server.txt"
echo "http://$docker0:6908" > "${CONFIG_DIR}"/emby_server.txt
else
INFO "使用 $local_ip IP 配置 emby_server.txt"
echo "http://$local_ip:6908" > "${CONFIG_DIR}"/emby_server.txt
fi
auto_chown "${CONFIG_DIR}/emby_server.txt"
}
function check_metadata_size() {
function simple_check_metadata_size() {
case "${1}" in
config.mp4)
if [[ "$2" -le 3200000 ]]; then
return 1
fi
;;
all.mp4)
if [[ "$2" -le 30000000 ]]; then
return 1
fi
;;
115.mp4)
if [[ "$2" -le 16000000 ]]; then
return 1
fi
;;
蓝光原盘.mp4)
if [[ "$2" -le 4200000 ]]; then
return 1
fi
;;
config.new.mp4)
if [[ "$2" -le 3200000 ]]; then
return 1
fi
;;
esac
}
local file_size file_size_b remote_metadata_size check_result
if [ -z "${xiaoya_addr}" ]; then
test_xiaoya_status
fi
pull_run_glue_xh xh --headers --follow --timeout=10 -o /media/headers.log "${xiaoya_addr}/d/元数据/${1}$(get_sign "${CONFIG_DIR}")" "User-Agent: ${GLOBAL_UA}"
remote_metadata_size=$(grep 'Content-Length' "${MEDIA_DIR}/headers.log" | awk '{print $2}')
rm -f "${MEDIA_DIR}/headers.log"
pull_run_glue bash -c "du -k /media/temp/${1} | cut -f1 > /media/size.txt"
if [ ! -f "${MEDIA_DIR}/size.txt" ]; then
ERROR "获取元数据文件本地大小失败(单位k)"
return 1
fi
file_size=$(head -n 1 "${MEDIA_DIR}/size.txt")
rm -f "${MEDIA_DIR}/size.txt"
if [ -n "${remote_metadata_size}" ] &&
awk -v remote="${remote_metadata_size}" -v threshold="2147483648" 'BEGIN { if (remote > threshold) print "1"; else print "0"; }' | grep -q "1"; then
INFO "精准校验文件大小模式"
pull_run_glue bash -c "du -b /media/temp/${1} | cut -f1 > /media/size.txt"
if [ ! -f "${MEDIA_DIR}/size.txt" ]; then
WARN "获取元数据文件本地大小失败(单位b)"
if ! simple_check_metadata_size "${1}" "${file_size}"; then
check_result=false
fi
else
file_size_b=$(head -n 1 "${MEDIA_DIR}/size.txt")
rm -f "${MEDIA_DIR}/size.txt"
INFO "${1} REMOTE_METADATA_SIZE: ${remote_metadata_size}"
INFO "${1} LOCAL_METADATA_SIZE: ${file_size_b}"
if [ "${remote_metadata_size}" != "${file_size_b}" ]; then
check_result=false
fi
fi
else
if ! simple_check_metadata_size "${1}" "${file_size}"; then
check_result=false
fi
fi
if [ "${check_result}" == false ]; then
ERROR "${1} 下载不完整,文件大小(in KB):$file_size 小于预期"
return 1
fi
INFO "${1} 文件大小验证正常,文件大小(in KB):$file_size"
return 0
}
function __unzip_metadata() {
function metadata_unziper() {
if ! check_metadata_size "${1}"; then
exit 1
fi
if [[ "${OSNAME}" = "macos" ]] || [[ "$(cat "${DDSREM_CONFIG_DIR}/use_host_7z_command.txt")" == "true" ]]; then
INFO "使用宿主机 7z 命令解压"
if [ "${1}" == "config.mp4" ] || [ "${1}" == "config.new.mp4" ]; then
if [ ! -d "${MEDIA_DIR}" ]; then
mkdir -p "${MEDIA_DIR}"
auto_chown "${MEDIA_DIR}"
chmod 777 "${MEDIA_DIR}"
fi
cd "${MEDIA_DIR}" || return 1
else
if [ ! -d "${MEDIA_DIR}/xiaoya" ]; then
mkdir -p "${MEDIA_DIR}/xiaoya"
auto_chown "${MEDIA_DIR}/xiaoya"
chmod 777 "${MEDIA_DIR}/xiaoya"
fi
cd "${MEDIA_DIR}/xiaoya" || return 1
fi
INFO "当前解压工作目录:$(pwd)"
if ! 7z x -aoa -mmt=16 "${MEDIA_DIR}/temp/${1}"; then
if ! 7z x -aoa -mmt=16 -bb3 "${MEDIA_DIR}/temp/${1}"; then
__unzip_metadata_debug "${1}"
fi
fi
else
if [ "${1}" == "config.mp4" ] || [ "${1}" == "config.new.mp4" ]; then
extra_parameters="--workdir=/media"
else
extra_parameters="--workdir=/media/xiaoya"
fi
if ! pull_run_glue 7z x -aoa -mmt=16 "/media/temp/${1}"; then
if ! pull_run_glue 7z x -aoa -mmt=16 -bb3 "/media/temp/${1}"; then
__unzip_metadata_debug "${1}"
fi
fi
fi
if [ "$(cat "${DDSREM_CONFIG_DIR}/auto_clean_metadata_mp4_file.txt")" == "true" ]; then
INFO "自动清理 ${1} 文件中..."
rm -f "${MEDIA_DIR}/temp/${1}"
fi
}
start_time1=$(date +%s)
if [ "${1}" == "all_metadata" ]; then
for file in "${ALL_METADATA_FILES[@]}"; do
metadata_unziper "${file}"
done
INFO "设置目录权限..."
INFO "这可能需要一定时间,请耐心等待!"
chmod -R 777 "${MEDIA_DIR}"
elif [ "${1}" == "config.mp4" ] || [ "${1}" == "config.new.mp4" ]; then
metadata_unziper "${1}"
emby_fix_strmassistant "${MEDIA_DIR}/config"
emby_install_coverart "${MEDIA_DIR}/config"
INFO "设置目录权限..."
INFO "这可能需要一定时间,请耐心等待!"
chmod -R 777 "${MEDIA_DIR}"/config
else
metadata_unziper "${1}"
INFO "设置目录权限..."
chmod 777 "${MEDIA_DIR}"/xiaoya
fi
end_time1=$(date +%s)
total_time1=$((end_time1 - start_time1))
total_time1=$((total_time1 / 60))
INFO "解压执行时间:$total_time1 分钟"
}
function __download_metadata() {
function metadata_downloader() {
local __data_downloader
INFO "开始下载 ${1} ..."
INFO "下载路径:${MEDIA_DIR}/temp/${1}"
__data_downloader=$(cat "${DDSREM_CONFIG_DIR}/data_downloader.txt")
INFO "使用下载器:${__data_downloader}"
extra_parameters="--workdir=/media/temp"
if [ "${__data_downloader}" == "wget" ]; then
# wget 下载模式下只能单线程下载
if ! pull_run_glue wget -c --show-progress "${xiaoya_addr}/d/元数据/${1}$(get_sign "${CONFIG_DIR}")" -U "${GLOBAL_UA}" -O "${1}"; then
DEBUG "${OSNAME} $(uname -a)"
ERROR "${1} 下载失败!"
exit 1
fi
else
local download_threads
pull_run_glue_xh xh --headers --follow --timeout=10 -o /media/headers.log "${xiaoya_addr}/d/元数据/${1}$(get_sign "${CONFIG_DIR}")" "User-Agent: ${GLOBAL_UA}"
if [ -f "${MEDIA_DIR}/headers.log" ]; then
# 115网盘下载链接:返回为 X-115-Request-Id,并且存在 ali2115.txt 文件
if grep "X-115-Request-Id" "${MEDIA_DIR}/headers.log" && [ -f "${CONFIG_DIR}/ali2115.txt" ]; then
download_threads="2"
# 阿里云盘下载链接:非 115 链接情况下,返回为 X-Oss-Request-Id + X-Oss-Storage-Class
elif grep "X-Oss-Request-Id" "${MEDIA_DIR}/headers.log" && grep "X-Oss-Storage-Class" "${MEDIA_DIR}/headers.log"; then
download_threads="6"
# 其余不确定的情况全部使用四线程下载
else
download_threads="4"
fi
rm -f "${MEDIA_DIR}/headers.log"
else
if [ -f "${CONFIG_DIR}/ali2115.txt" ]; then
download_threads="2"
else
download_threads="6"
fi
fi
if [ "${download_threads}" == "1" ]; then
INFO "单线程下载"
else
INFO "多线程下载,线程数:${download_threads}"
fi
if pull_run_glue aria2c -o "${1}" --header="User-Agent: ${GLOBAL_UA}" --allow-overwrite=true --auto-file-renaming=false --enable-color=false --file-allocation=none -c "-x${download_threads}" "${xiaoya_addr}/d/元数据/${1}$(get_sign "${CONFIG_DIR}")"; then
if [ -f "${MEDIA_DIR}/temp/${1}.aria2" ]; then
ERROR "存在 ${MEDIA_DIR}/temp/${1}.aria2 文件,下载不完整!"
exit 1
else
INFO "${1} 下载成功!"
fi
else
DEBUG "${OSNAME} $(uname -a)"
ERROR "${1} 下载失败!"
exit 1
fi
fi
}
if [ "${1}" == "all_metadata" ]; then
for file in "${ALL_METADATA_FILES[@]}"; do
metadata_downloader "${file}"
done
INFO "设置目录权限..."
chmod -R 777 "${MEDIA_DIR}"/temp
auto_chown "${MEDIA_DIR}/temp" "-R"
else
metadata_downloader "${1}"
INFO "设置目录权限..."
chmod 777 "${MEDIA_DIR}"/temp/"${1}"
auto_chown "${MEDIA_DIR}/temp/${1}"
fi
}
function unzip_xiaoya_all_emby() {
get_config_dir
get_media_dir
test_xiaoya_status
mkdir -p "${MEDIA_DIR}"/temp
rm -rf "${MEDIA_DIR}"/config
test_disk_capacity
mkdir -p "${MEDIA_DIR}"/xiaoya
mkdir -p "${MEDIA_DIR}"/config
chmod 755 "${MEDIA_DIR}"
auto_chown "${MEDIA_DIR}"
auto_chown "${MEDIA_DIR}/xiaoya"
auto_chown "${MEDIA_DIR}/config"
auto_chown "${MEDIA_DIR}/temp"
INFO "开始解压..."
__unzip_metadata "all_metadata"
INFO "解压完成!"
}
function unzip_xiaoya_emby() {
get_config_dir
get_media_dir
show_disk_capacity "${MEDIA_DIR}"
chmod 777 "${MEDIA_DIR}"
auto_chown "${MEDIA_DIR}"
INFO "开始解压 ${MEDIA_DIR}/temp/${1} ..."
if [ -f "${MEDIA_DIR}/temp/${1}.aria2" ]; then
ERROR "存在 ${MEDIA_DIR}/temp/${1}.aria2 文件,文件不完整!"
exit 1
fi
if [ "${1}" == "config.mp4" ]; then
if [ -d "${MEDIA_DIR}/config" ]; then
INFO "清理旧配置文件中..."
INFO "这可能需要一定时间,请耐心等待!"
rm -rf ${MEDIA_DIR}/config
fi
mkdir -p "${MEDIA_DIR}"/config
auto_chown "${MEDIA_DIR}/config"
chmod -R 777 "${MEDIA_DIR}"/config
__unzip_metadata "${1}"
else
mkdir -p "${MEDIA_DIR}"/xiaoya
auto_chown "${MEDIA_DIR}/xiaoya"
__unzip_metadata "${1}"
fi
INFO "解压完成!"
}
function unzip_appoint_xiaoya_emby_jellyfin() {
function metadata_unziper() {
if ! check_metadata_size "${1}"; then
exit 1
fi
if [[ "${OSNAME}" = "macos" ]] || [[ "$(cat "${DDSREM_CONFIG_DIR}/use_host_7z_command.txt")" == "true" ]]; then
INFO "使用宿主机 7z 命令解压"
if [ ! -d "${MEDIA_DIR}/xiaoya" ]; then
mkdir -p "${MEDIA_DIR}/xiaoya"
auto_chown "${MEDIA_DIR}/xiaoya"
chmod 777 "${MEDIA_DIR}/xiaoya"
fi
cd "${MEDIA_DIR}/xiaoya" || return 1
INFO "当前解压工作目录:$(pwd)"
if ! 7z x -aoa -mmt=16 "${MEDIA_DIR}/temp/${1}" "${2}/*" -o"${MEDIA_DIR}/xiaoya"; then
if ! 7z x -aoa -mmt=16 -bb3 "${MEDIA_DIR}/temp/${1}" "${2}/*" -o"${MEDIA_DIR}/xiaoya"; then
__unzip_metadata_debug "${1}"
fi
fi
else
extra_parameters="--workdir=/media/xiaoya"
if ! pull_run_glue 7z x -aoa -mmt=16 "/media/temp/${1}" "${2}/*" -o/media/xiaoya; then
if ! pull_run_glue 7z x -aoa -mmt=16 -bb3 "/media/temp/${1}" "${2}/*" -o/media/xiaoya; then
__unzip_metadata_debug "${1}"
fi
fi
fi
}
get_config_dir
get_media_dir
if [ "${1}" == "all.mp4" ] || [ "${1}" == "all_jf.mp4" ]; then
INFO "请选择要解压的压缩包目录 [ 1:动漫 | 2:每日更新 | 3:电影 | 4:电视剧 | 5:纪录片 | 6:纪录片(已刮削)| 7:综艺 | 8:短剧 ]"
valid_choice=false
while [ "$valid_choice" = false ]; do
read -erp "请输入数字 [1-8]:" choice
for i in {1..8}; do
if [ "$choice" = "$i" ]; then
valid_choice=true
break
fi
done
if [ "$valid_choice" = false ]; then
ERROR "请输入正确数字 [1-8]"
fi
done
case $choice in
1)
UNZIP_FOLD=动漫
;;
2)
UNZIP_FOLD=每日更新
;;
3)
UNZIP_FOLD=电影
;;
4)
UNZIP_FOLD=电视剧
;;
5)
UNZIP_FOLD=纪录片
;;
6)
UNZIP_FOLD=纪录片(已刮削)
;;
7)
UNZIP_FOLD=综艺
;;
8)
UNZIP_FOLD=短剧
;;
esac
elif [ "${1}" == "115.mp4" ]; then
INFO "请选择要解压的压缩包目录 [ 1:电视剧 | 2:电影 | 3:动漫 ]"
valid_choice=false
while [ "$valid_choice" = false ]; do
read -erp "请输入数字 [1-3]:" choice
for i in {1..3}; do
if [ "$choice" = "$i" ]; then
valid_choice=true
break
fi
done
if [ "$valid_choice" = false ]; then
ERROR "请输入正确数字 [1-3]"
fi
done
case $choice in
1)
UNZIP_FOLD=电视剧
;;
2)
UNZIP_FOLD=电影
;;
3)
UNZIP_FOLD=动漫
;;
esac
else
ERROR "此文件暂时不支持解压指定元数据!"
fi
show_disk_capacity "${MEDIA_DIR}"
chmod 777 "${MEDIA_DIR}"
auto_chown "${MEDIA_DIR}"
INFO "开始解压 ${MEDIA_DIR}/temp/${1} ${UNZIP_FOLD} ..."
if [ -f "${MEDIA_DIR}/temp/${1}.aria2" ]; then
ERROR "存在 ${MEDIA_DIR}/temp/${1}.aria2 文件,文件不完整!"
exit 1
fi
start_time1=$(date +%s)
if [ "${1}" == "all.mp4" ] || [ "${1}" == "all_jf.mp4" ]; then
mkdir -p "${MEDIA_DIR}"/xiaoya
auto_chown "${MEDIA_DIR}/xiaoya"
metadata_unziper "${1}" "${UNZIP_FOLD}"
elif [ "${1}" == "115.mp4" ]; then
mkdir -p "${MEDIA_DIR}"/xiaoya/115
auto_chown "${MEDIA_DIR}/xiaoya/115"
metadata_unziper "${1}" "115/${UNZIP_FOLD}"
else
ERROR "此文件暂时不支持解压指定元数据!"
exit 1
fi
INFO "设置目录权限..."
chmod 777 "${MEDIA_DIR}"/xiaoya
end_time1=$(date +%s)
total_time1=$((end_time1 - start_time1))
total_time1=$((total_time1 / 60))
INFO "解压执行时间:$total_time1 分钟"
INFO "解压完成!"
}
function download_xiaoya_emby() {
get_config_dir
get_media_dir
test_xiaoya_status
mkdir -p "${MEDIA_DIR}"/temp
auto_chown "${MEDIA_DIR}/temp"
chmod 777 "${MEDIA_DIR}"/temp
show_disk_capacity "${MEDIA_DIR}"
if [ -f "${MEDIA_DIR}/temp/${1}" ]; then
INFO "清理旧 ${1} 中..."
rm -f "${MEDIA_DIR}/temp/${1}"
if [ -f "${MEDIA_DIR}/temp/${1}.aria2" ]; then
rm -rf "${MEDIA_DIR}/temp/${1}.aria2"
fi
fi
__download_metadata "${1}"
INFO "下载完成!"
}
function download_unzip_xiaoya_all_emby() {
get_config_dir
get_media_dir
test_xiaoya_status
rm -rf "${MEDIA_DIR}/config"
test_disk_capacity
mkdir -p "${MEDIA_DIR}/xiaoya"
mkdir -p "${MEDIA_DIR}/config"
mkdir -p "${MEDIA_DIR}/temp"
auto_chown "${MEDIA_DIR}"
auto_chown "${MEDIA_DIR}/xiaoya"
auto_chown "${MEDIA_DIR}/config"
auto_chown "${MEDIA_DIR}/temp"
chmod 777 "${MEDIA_DIR}"
for file in "${ALL_METADATA_FILES[@]}"; do
if [ -f "${MEDIA_DIR}/temp/${file}.aria2" ]; then
rm -rf "${MEDIA_DIR}/temp/${file}.aria2"
fi
done
INFO "开始下载解压..."
__download_metadata "all_metadata"
__unzip_metadata "all_metadata"
INFO "刮削数据已经下载解压完成!"
}
function download_unzip_xiaoya_emby_new_config() {
function compare_metadata_size() {
local REMOTE_METADATA_SIZE LOCAL_METADATA_SIZE
pull_run_glue_xh xh --headers --follow --timeout=10 -o /media/headers.log "${xiaoya_addr}/d/元数据/${1}$(get_sign "${CONFIG_DIR}")" "User-Agent: ${GLOBAL_UA}"
REMOTE_METADATA_SIZE=$(cat ${MEDIA_DIR}/headers.log | grep 'Content-Length' | awk '{print $2}')
rm -f ${MEDIA_DIR}/headers.log
if [ -f "${MEDIA_DIR}/temp/${1}" ] && [ ! -f "${MEDIA_DIR}/temp/${1}.aria2" ]; then
pull_run_glue bash -c "du -b /media/temp/${1} | cut -f1 > /media/size.txt"
if [ ! -f "${MEDIA_DIR}/size.txt" ]; then
WARN "获取元数据文件本地大小失败(单位b)"
LOCAL_METADATA_SIZE=0
else
LOCAL_METADATA_SIZE=$(head -n 1 "${MEDIA_DIR}/size.txt")
rm -f "${MEDIA_DIR}/size.txt"
fi
else
LOCAL_METADATA_SIZE=0
fi
INFO "${1} REMOTE_METADATA_SIZE: ${REMOTE_METADATA_SIZE}"
INFO "${1} LOCAL_METADATA_SIZE: ${LOCAL_METADATA_SIZE}"
if
[ "${REMOTE_METADATA_SIZE}" != "${LOCAL_METADATA_SIZE}" ] &&
[ -n "${REMOTE_METADATA_SIZE}" ] &&
awk -v remote="${REMOTE_METADATA_SIZE}" -v threshold="2147483648" 'BEGIN { if (remote > threshold) print "1"; else print "0"; }' | grep -q "1"
then
return 1
else
return 0
fi
}
get_config_dir
get_media_dir
if [ -f "${MEDIA_DIR}/config/config/system.xml" ]; then
INFO "检测到非第一次安装全家桶..."
WARN "警告:本次元数据升级会丢失当前 Emby 所有用户配置信息!"
local OPERATE
while true; do
INFO "是否继续操作 [Y/n](默认 Y)"
read -erp "OPERATE:" OPERATE
[[ -z "${OPERATE}" ]] && OPERATE="y"
if [[ ${OPERATE} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ "${OPERATE}" == [Nn] ]]; then
exit 0
fi
if get_emby_version; then
INFO "当前 Emby 版本:${emby_version}"
else
ERROR "当前 Emby 版本获取失败!"
exit 1
fi
if version_lt "${emby_version}" "4.9.0.42"; then
INFO "您的 Emby 版本过低,开始进入升级流程,请升级到 4.9.0.42 或更高版本!"
oneclick_upgrade_emby
fi
INFO "关闭 Emby 容器中..."
if ! docker stop "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)"; then
if ! docker kill "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)"; then
ERROR "关闭 Emby 容器失败!"
exit 1
fi
fi
fi
test_xiaoya_status
INFO "清理旧配置文件中..."
INFO "这可能需要一定时间,请耐心等待!"
rm -rf "${MEDIA_DIR}/config"
mkdir -p "${MEDIA_DIR}/config"
auto_chown "${MEDIA_DIR}/config"
chmod -R 777 "${MEDIA_DIR}/config"
if [ -f "${MEDIA_DIR}/temp/config.new.mp4.aria2" ]; then
rm -rf "${MEDIA_DIR}/temp/config.new.mp4.aria2"
if [ -f "${MEDIA_DIR}/temp/config.new.mp4" ]; then
INFO "清理不完整 config.new.mp4 中..."
rm -rf "${MEDIA_DIR}/temp/config.new.mp4"
fi
fi
if [ -f "${MEDIA_DIR}/temp/config.new.mp4" ]; then
if compare_metadata_size "config.new.mp4"; then
INFO "当前 config.new.mp4 已是最新,无需重新下载!"
else
INFO "清理旧 config.new.mp4 中..."
rm -rf "${MEDIA_DIR}/temp/config.new.mp4"
fi
fi
show_disk_capacity "${MEDIA_DIR}"
INFO "开始下载解压..."
if [ ! -f "${MEDIA_DIR}/temp/config.new.mp4" ]; then
__download_metadata "config.new.mp4"
fi
__unzip_metadata "config.new.mp4"
docker start "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)"
wait_emby_start
INFO "操作完成!"
}
function main_download_unzip_xiaoya_emby() {
__data_downloader=$(cat ${DDSREM_CONFIG_DIR}/data_downloader.txt)
function main_download_unzip_xiaoya_emby_page1() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}下载/解压 元数据${Font}\n"
echo -e "1、下载并解压 全部元数据"
echo -e "2、解压 全部元数据"
echo -e "3、下载 all.mp4"
echo -e "4、解压 all.mp4"
echo -e "5、解压 all.mp4 的指定元数据目录【非全部解压】"
echo -e "6、下载 config.mp4(4.9.0.42)"
echo -e "7、解压 config.mp4(4.9.0.42)"
echo -e "8、下载 115.mp4"
echo -e "9、解压 115.mp4"
echo -e "n、下一页"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
}
function main_download_unzip_xiaoya_emby_page2() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}下载/解压 元数据${Font}\n"
echo -e "10、解压 115.mp4 的指定元数据目录【非全部解压】"
echo -e "11、下载 蓝光原盘.mp4"
echo -e "12、解压 蓝光原盘.mp4"
echo -e "13、下载 json.mp4"
echo -e "14、解压 json.mp4"
echo -e "15、下载 music.mp4"
echo -e "16、解压 music.mp4"
echo -e "17、下载 短剧.mp4"
echo -e "18、解压 短剧.mp4"
echo -e "19、当前下载器【aria2/wget】 当前状态:${Green}${__data_downloader}${Font}"
# echo -e "101、下载并解压 config.new.mp4(4.9.0.42)"
echo -e "p、上一页"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
}
__next_operate=
local page next_page next_page_choose
if [ -z "${1}" ]; then
page=1
else
page="${1}"
fi
"main_download_unzip_xiaoya_emby_page${page}"
read -erp "请输入数字(支持输入多个数字,空格分离,按输入顺序执行)[0-19]:" -a nums
for num in "${nums[@]}"; do
if [ $num -ge 1 ] && [ $num -le 18 ]; then
case "$num" in
1)
clear
download_unzip_xiaoya_all_emby
;;
2)
clear
unzip_xiaoya_all_emby
;;
3)
clear
download_xiaoya_emby "all.mp4"
;;
4)
clear
unzip_xiaoya_emby "all.mp4"
;;
5)
clear
unzip_appoint_xiaoya_emby_jellyfin "all.mp4"
;;
6)
clear
download_xiaoya_emby "config.mp4"
;;
7)
clear
unzip_xiaoya_emby "config.mp4"
;;
8)
clear
download_xiaoya_emby "115.mp4"
;;
9)
clear
unzip_xiaoya_emby "115.mp4"
;;
10)
clear
unzip_appoint_xiaoya_emby_jellyfin "115.mp4"
;;
11)
clear
download_xiaoya_emby "蓝光原盘.mp4"
;;
12)
clear
unzip_xiaoya_emby "蓝光原盘.mp4"
;;
13)
clear
download_xiaoya_emby "json.mp4"
;;
14)
clear
unzip_xiaoya_emby "json.mp4"
;;
15)
clear
download_xiaoya_emby "music.mp4"
;;
16)
clear
unzip_xiaoya_emby "music.mp4"
;;
17)
clear
download_xiaoya_emby "短剧.mp4"
;;
18)
clear
unzip_xiaoya_emby "短剧.mp4"
;;
esac
__next_operate=return_menu
elif [ $num == 101 ]; then
clear
download_unzip_xiaoya_emby_new_config
__next_operate=return_menu
elif [ $num == 19 ]; then
if [ "${__data_downloader}" == "wget" ]; then
echo 'aria2' > ${DDSREM_CONFIG_DIR}/data_downloader.txt
elif [ "${__data_downloader}" == "aria2" ]; then
echo 'wget' > ${DDSREM_CONFIG_DIR}/data_downloader.txt
else
echo 'aria2' > ${DDSREM_CONFIG_DIR}/data_downloader.txt
fi
clear
__next_operate=main_download_unzip_xiaoya_emby
break
elif [ $num == 0 ]; then
clear
__next_operate=main_xiaoya_all_emby
break
elif [ $num == "n" ]; then
clear
next_page=$((page + 1))
next_page_choose=n
__next_operate=next_page
break
elif [ $num == "p" ]; then
clear
next_page=$((page - 1))
next_page_choose=p
__next_operate=next_page
break
else
clear
ERROR '请输入正确数字 [0-21]'
__next_operate=main_download_unzip_xiaoya_emby
break
fi
done
if [ -z ${__next_operate} ]; then
clear
ERROR '请输入正确数字 [0-21]'
__next_operate=main_download_unzip_xiaoya_emby
fi
if [ "${__next_operate}" == "return_menu" ]; then
return_menu "main_download_unzip_xiaoya_emby"
elif [ "${__next_operate}" == "main_download_unzip_xiaoya_emby" ]; then
main_download_unzip_xiaoya_emby "${page}"
elif [ "${__next_operate}" == "main_xiaoya_all_emby" ]; then
main_xiaoya_all_emby
elif [ "${__next_operate}" == "next_page" ]; then
if [ $next_page -ge 1 ] && [ $next_page -le 2 ]; then
main_download_unzip_xiaoya_emby "${next_page}"
else
clear
if [ "${next_page_choose}" == "n" ]; then
ERROR '当前页面为最后一页,无法前往下一页'
else
ERROR '当前页面为第一页,无法前往前一页'
fi
main_download_unzip_xiaoya_emby "${page}"
fi
fi
}
function install_emby_embyserver() {
INFO "开始安装Emby容器....."
if [ "${DOCKER_ARCH}" == "linux/amd64" ]; then
image_name="emby/embyserver"
elif [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
image_name="emby/embyserver_arm64v8"
else
ERROR "目前只支持amd64和arm64架构,你的架构是:$CPU_ARCH"
exit 1
fi
docker_pull "${image_name}:${IMAGE_VERSION}"
if [ -n "${extra_parameters}" ]; then
# shellcheck disable=SC2046
docker run -itd \
--name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" \
-v "${MEDIA_DIR}/config:/config" \
-v "${MEDIA_DIR}/xiaoya:/media" \
-v ${NSSWITCH}:/etc/nsswitch.conf \
--add-host="xiaoya.host:$xiaoya_host" \
${NET_MODE} \
$(auto_privileged) \
${extra_parameters} \
-e UID=0 \
-e GID=0 \
-e TZ=Asia/Shanghai \
--restart=always \
"${image_name}:${IMAGE_VERSION}"
else
# shellcheck disable=SC2046
docker run -itd \
--name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" \
-v "${MEDIA_DIR}/config:/config" \
-v "${MEDIA_DIR}/xiaoya:/media" \
-v ${NSSWITCH}:/etc/nsswitch.conf \
--add-host="xiaoya.host:$xiaoya_host" \
${NET_MODE} \
$(auto_privileged) \
-e UID=0 \
-e GID=0 \
-e TZ=Asia/Shanghai \
--restart=always \
"${image_name}:${IMAGE_VERSION}"
fi
}
function install_amilys_embyserver() {
INFO "开始安装Emby容器....."
if [ "${DOCKER_ARCH}" == "linux/amd64" ]; then
image_name="amilys/embyserver"
elif [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
image_name="amilys/embyserver_arm64v8"
else
ERROR "目前只支持amd64和arm64架构,你的架构是:$CPU_ARCH"
exit 1
fi
docker_pull "${image_name}:${IMAGE_VERSION}"
if [ -n "${extra_parameters}" ]; then
# shellcheck disable=SC2046
docker run -itd \
--name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" \
-v "${MEDIA_DIR}/config:/config" \
-v "${MEDIA_DIR}/xiaoya:/media" \
-v ${NSSWITCH}:/etc/nsswitch.conf \
--add-host="xiaoya.host:$xiaoya_host" \
${NET_MODE} \
${extra_parameters} \
$(auto_privileged) \
-e UID=0 \
-e GID=0 \
-e TZ=Asia/Shanghai \
--restart=always \
"${image_name}:${IMAGE_VERSION}"
else
# shellcheck disable=SC2046
docker run -itd \
--name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" \
-v "${MEDIA_DIR}/config:/config" \
-v "${MEDIA_DIR}/xiaoya:/media" \
-v ${NSSWITCH}:/etc/nsswitch.conf \
--add-host="xiaoya.host:$xiaoya_host" \
${NET_MODE} \
$(auto_privileged) \
-e UID=0 \
-e GID=0 \
-e TZ=Asia/Shanghai \
--restart=always \
"${image_name}:${IMAGE_VERSION}"
fi
}
function install_iceyheart_embyserver() {
INFO "开始安装Emby容器....."
if [ "${DOCKER_ARCH}" == "linux/amd64" ] || [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
image_name="iceyheart/embycrk"
else
ERROR "目前只支持amd64和arm64架构,你的架构是:$CPU_ARCH"
exit 1
fi
docker_pull "${image_name}:${IMAGE_VERSION}"
if [ -n "${extra_parameters}" ]; then
# shellcheck disable=SC2046
docker run -itd \
--name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" \
-v "${MEDIA_DIR}/config:/config" \
-v "${MEDIA_DIR}/xiaoya:/media" \
-v ${NSSWITCH}:/etc/nsswitch.conf \
--add-host="xiaoya.host:$xiaoya_host" \
${NET_MODE} \
${extra_parameters} \
$(auto_privileged) \
-e UID=0 \
-e GID=0 \
-e TZ=Asia/Shanghai \
--restart=always \
"${image_name}:${IMAGE_VERSION}"
else
# shellcheck disable=SC2046
docker run -itd \
--name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" \
-v "${MEDIA_DIR}/config:/config" \
-v "${MEDIA_DIR}/xiaoya:/media" \
-v ${NSSWITCH}:/etc/nsswitch.conf \
--add-host="xiaoya.host:$xiaoya_host" \
${NET_MODE} \
$(auto_privileged) \
-e UID=0 \
-e GID=0 \
-e TZ=Asia/Shanghai \
--restart=always \
"${image_name}:${IMAGE_VERSION}"
fi
}
function install_lovechen_embyserver() {
INFO "开始安装Emby容器....."
INFO "开始转换数据库..."
mv ${MEDIA_DIR}/config/data/library.db ${MEDIA_DIR}/config/data/library.org.db
if [ -f "${MEDIA_DIR}/config/data/library.db-wal" ]; then
rm -rf ${MEDIA_DIR}/config/data/library.db-wal
fi
if [ -f "${MEDIA_DIR}/config/data/library.db-shm" ]; then
rm -rf ${MEDIA_DIR}/config/data/library.db-shm
fi
chmod 777 ${MEDIA_DIR}/config/data/library.org.db
curl -o ${MEDIA_DIR}/config/data/library.db https://cdn.jsdelivr.net/gh/xiaoyaDev/xiaoya-alist@latest/emby_lovechen/library.db
curl -o ${MEDIA_DIR}/temp.sql https://cdn.jsdelivr.net/gh/xiaoyaDev/xiaoya-alist@latest/emby_lovechen/temp.sql
pull_run_glue sqlite3 /media/config/data/library.db ".read /media/temp.sql"
INFO "数据库转换成功!"
rm -rf ${MEDIA_DIR}/temp.sql
docker_pull "lovechen/embyserver:${IMAGE_VERSION}"
if [ -n "${extra_parameters}" ]; then
# shellcheck disable=SC2046
docker run -itd \
--name "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" \
-v "${MEDIA_DIR}/config:/config" \
-v "${MEDIA_DIR}/xiaoya:/media" \
-v ${NSSWITCH}:/etc/nsswitch.conf \
--add-host="xiaoya.host:$xiaoya_host" \
${NET_MODE} \
${extra_parameters} \
$(auto_privileged) \
-e UID=0 \
-e GID=0 \
-e TZ=Asia/Shanghai \
--restart=always \
lovechen/embyserver:${IMAGE_VERSION}
else
# shellcheck disable=SC2046
docker run -itd \
--name "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" \
-v "${MEDIA_DIR}/config:/config" \
-v "${MEDIA_DIR}/xiaoya:/media" \
-v ${NSSWITCH}:/etc/nsswitch.conf \
--add-host="xiaoya.host:$xiaoya_host" \
${NET_MODE} \
$(auto_privileged) \
-e UID=0 \
-e GID=0 \
-e TZ=Asia/Shanghai \
--restart=always \
lovechen/embyserver:${IMAGE_VERSION}
fi
}
function choose_network_mode() {
INFO "请选择使用的网络模式 [ 1:host | 2:bridge ](默认 1)"
read -erp "Net:" MODE
[[ -z "${MODE}" ]] && MODE="1"
if [[ ${MODE} == [1] ]]; then
MODE=host
elif [[ ${MODE} == [2] ]]; then
MODE=bridge
else
ERROR "输入无效,请重新选择"
choose_network_mode
fi
if [ "$MODE" == "host" ]; then
NET_MODE="--net=host"
elif [ "$MODE" == "bridge" ]; then
NET_MODE="-p 6908:6908"
fi
}
function choose_emby_image() {
INFO "您的架构是:$CPU_ARCH"
if [ "${DOCKER_ARCH}" == "linux/amd64" ]; then
INFO "请选择使用的Emby镜像 [ 1:amilys/embyserver | 2:emby/embyserver | 3:iceyheart/embycrk ](默认 2)"
read -erp "IMAGE:" IMAGE
[[ -z "${IMAGE}" ]] && IMAGE="2"
if [[ ${IMAGE} == [1] ]]; then
CHOOSE_EMBY=amilys_embyserver
elif [[ ${IMAGE} == [2] ]]; then
CHOOSE_EMBY=emby_embyserver
elif [[ ${IMAGE} == [3] ]]; then
CHOOSE_EMBY=iceyheart_embycrk
elif [[ ${IMAGE} == [4] ]]; then
CHOOSE_EMBY=lovechen_embyserver
else
ERROR "输入无效,请重新选择"
choose_emby_image
fi
elif [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
WARN "${DOCKER_ARCH} 只支持官方镜像!"
INFO "请选择使用的Emby镜像 [ 1:emby/embyserver | 2:iceyheart/embycrk ](默认 1)"
read -erp "IMAGE:" IMAGE
[[ -z "${IMAGE}" ]] && IMAGE="1"
if [[ ${IMAGE} == [1] ]]; then
CHOOSE_EMBY=amilys_embyserver
elif [[ ${IMAGE} == [2] ]]; then
CHOOSE_EMBY=iceyheart_embycrk
else
ERROR "输入无效,请重新选择"
choose_emby_image
fi
else
ERROR "全家桶 Emby 目前只支持 amd64 和 arm64 架构,你的架构是:$CPU_ARCH"
exit 1
fi
}
function get_nsswitch_conf_path() {
if [ -f /etc/nsswitch.conf ]; then
NSSWITCH="/etc/nsswitch.conf"
else
CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
if [ -d "${CONFIG_DIR}/nsswitch.conf" ]; then
rm -rf ${CONFIG_DIR}/nsswitch.conf
fi
echo -e "hosts:\tfiles dns" > ${CONFIG_DIR}/nsswitch.conf
echo -e "networks:\tfiles" >> ${CONFIG_DIR}/nsswitch.conf
NSSWITCH="${CONFIG_DIR}/nsswitch.conf"
fi
INFO "nsswitch.conf 配置文件路径:${NSSWITCH}"
}
function get_xiaoya_hosts() { # 调用这个函数必须设置 $MODE 此变量
if ! grep -q xiaoya.host ${HOSTS_FILE_PATH}; then
if [ "$MODE" == "host" ]; then
echo -e "127.0.0.1\txiaoya.host\n" >> ${HOSTS_FILE_PATH}
xiaoya_host="127.0.0.1"
elif [ "$MODE" == "bridge" ]; then
echo -e "$docker0\txiaoya.host\n" >> ${HOSTS_FILE_PATH}
xiaoya_host="$docker0"
fi
else
if [ "$MODE" == "host" ]; then
if grep -q "^${docker0}.*xiaoya\.host" ${HOSTS_FILE_PATH}; then
sedsh '/xiaoya.host/d' ${HOSTS_FILE_PATH}
echo -e "127.0.0.1\txiaoya.host\n" >> ${HOSTS_FILE_PATH}
fi
elif [ "$MODE" == "bridge" ]; then
if grep -q "^127\.0\.0\.1.*xiaoya\.host" ${HOSTS_FILE_PATH}; then
sedsh '/xiaoya.host/d' ${HOSTS_FILE_PATH}
echo -e "$docker0\txiaoya.host\n" >> ${HOSTS_FILE_PATH}
fi
fi
xiaoya_host=$(grep xiaoya.host ${HOSTS_FILE_PATH} | awk '{print $1}' | head -n1)
fi
XIAOYA_HOSTS_SHOW=$(grep xiaoya.host ${HOSTS_FILE_PATH})
# if echo "${XIAOYA_HOSTS_SHOW}" | awk '
# {
# split($1, ip, ".");
# if(length(ip) == 4 && ip[1] >= 0 && ip[1] <= 255 && ip[2] >= 0 && ip[2] <= 255 && ip[3] >= 0 && ip[3] <= 255 && ip[4] >= 0 && ip[4] <= 255 && index($2, "\t") == 0)
# exit 0;
# else
# exit 1;
# }'; then
# INFO "hosts 文件设置正确!"
# else
# WARN "hosts 文件设置错误!"
# INFO "是否使用脚本自动纠错(只支持单机部署自动纠错,如果小雅和全家桶不在同一台机器上,请手动修改)[Y/n](默认 Y)"
# read -erp "自动纠错:" FIX_HOST_ERROR
# [[ -z "${FIX_HOST_ERROR}" ]] && FIX_HOST_ERROR="y"
# if [[ ${FIX_HOST_ERROR} == [Yy] ]]; then
# INFO "开始自动纠错..."
# sedsh '/xiaoya\.host/d' /etc/hosts
# get_xiaoya_hosts
# else
# exit 1
# fi
# fi
if echo "${XIAOYA_HOSTS_SHOW}" | awk '{ if($1 ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/ && $2 ~ /^[^\t]+$/) exit 0; else exit 1 }'; then
INFO "hosts 文件格式设置正确!"
else
WARN "hosts 文件格式设置错误!"
while true; do
INFO "是否使用脚本自动纠错(只支持单机部署自动纠错,如果小雅和全家桶不在同一台机器上,请手动修改)[Y/n](默认 Y)"
read -erp "自动纠错:" FIX_HOST_ERROR
[[ -z "${FIX_HOST_ERROR}" ]] && FIX_HOST_ERROR="y"
if [[ ${FIX_HOST_ERROR} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${FIX_HOST_ERROR} == [Yy] ]]; then
INFO "开始自动纠错..."
sedsh '/xiaoya\.host/d' /etc/hosts
get_xiaoya_hosts
else
exit 1
fi
fi
INFO "${XIAOYA_HOSTS_SHOW}"
response="$(curl -s -o /dev/null -w '%{http_code}' http://${xiaoya_host}:5678)"
if [[ "$response" == "302" || "$response" == "200" ]]; then
INFO "hosts 文件设置正确,本机可以正常访问小雅容器!"
else
response="$(curl -s -o /dev/null -w '%{http_code}' http://${xiaoya_host}:5678)"
if [[ "$response" == "302" || "$response" == "200" ]]; then
INFO "hosts 文件设置正确,本机可以正常访问小雅容器!"
else
if [[ "${OSNAME}" = "macos" ]]; then
localip=$(ifconfig "$(route -n get default | grep interface | awk -F ':' '{print$2}' | awk '{$1=$1};1')" | grep 'inet ' | awk '{print$2}')
else
if command -v ifconfig > /dev/null 2>&1; then
localip=$(ifconfig -a | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1)
else
localip=$(ip address | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1 | cut -f1 -d"/")
fi
fi
INFO "尝试使用本机IP:${localip}"
response="$(curl -s -o /dev/null -w '%{http_code}' http://${localip}:5678)"
if [[ "$response" == "302" || "$response" == "200" ]]; then
sedsh '/xiaoya.host/d' ${HOSTS_FILE_PATH}
echo -e "$localip\txiaoya.host\n" >> ${HOSTS_FILE_PATH}
INFO "hosts 文件设置成功,本机可以正常访问小雅容器!"
else
ERROR "hosts 文件设置错误,本机无法正常访问小雅容器!"
exit 1
fi
fi
fi
}
function emby_fix_strmassistant() {
function emby_test_exist_strmassistant() {
if [ -f "${1}/plugins/StrmAssistant.dll" ]; then
DEBUG "Emby神医助手 已安装:${1}/plugins/StrmAssistant.dll"
return 0
fi
return 1
}
if [ "${DOCKER_ARCH}" == "linux/amd64" ] || [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
if [ "${DOCKER_ARCH}" == "linux/amd64" ]; then
INFO "当前系统架构支持 Emby神医助手"
elif [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
INFO "当前系统架构支持 Emby神医助手(v2.0.0.30+ 版本已支持 arm64)"
fi
if emby_test_exist_strmassistant "${1}"; then
INFO "是否安装/更新 Emby神医助手 [Y/n](默认 Y)"
else
INFO "是否安装 Emby神医助手 [Y/n](默认 Y)"
fi
read -erp "请选择:" install_strmassistant
[[ -z "${install_strmassistant}" ]] && install_strmassistant="Y"
if [[ ${install_strmassistant} == [Yy] ]]; then
clear_qrcode_container
pull_glue_python_ddsrem
# shellcheck disable=SC2046
docker run -it --rm \
-v "${1}:/media/config" \
-e LANG=C.UTF-8 \
$(auto_privileged) \
ddsderek/xiaoya-glue:python \
/strmassistanthelper/strmassistanthelper.py
else
if emby_test_exist_strmassistant "${1}"; then
INFO "跳过 Emby神医助手 安装/更新"
else
INFO "跳过 Emby神医助手 安装"
fi
fi
else
WARN "未知的系统架构,无法确认是否支持 Emby神医助手"
emby_test_exist_strmassistant "${1}"
fi
}
function emby_install_coverart() {
if [ ! -f "${1}/config/plugins/CoverArt.dll" ]; then
INFO "开始安装 CoverArt ..."
clear_qrcode_container
pull_glue_python_ddsrem
# shellcheck disable=SC2046
docker run -it --rm \
-v "${1}:/media/config" \
-e LANG=C.UTF-8 \
$(auto_privileged) \
ddsderek/xiaoya-glue:python \
sh /coverart/install.sh
else
INFO "CoverArt 已安装,无需重复安装"
fi
}
function install_emby_xiaoya_all_emby() {
get_docker0_url
if [ -f "${MEDIA_DIR}/config/config/system.xml" ]; then
if ! grep -q 6908 ${MEDIA_DIR}/config/config/system.xml; then
ERROR "Emby config 出错,请重新下载解压!"
exit 1
fi
else
if [ ! -f "${MEDIA_DIR}/temp/config.mp4" ]; then
ERROR "config.mp4 不存在,请下载此文件并解压!"
else
ERROR "Emby config 出错,请重新下载解压!"
fi
exit 1
fi
if [ -f "${MEDIA_DIR}/config/data/device.txt" ]; then
INFO "检测到存在 device.txt 文件!"
if grep -q "1999bfd1661041cd85ff5e260bc04c06" ${MEDIA_DIR}/config/data/device.txt; then
INFO "删除 device.txt 文件中..."
rm -f ${MEDIA_DIR}/config/data/device.txt
fi
fi
XIAOYA_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
if [ -s "${XIAOYA_CONFIG_DIR}/emby_config.txt" ]; then
# shellcheck disable=SC1091
source "${XIAOYA_CONFIG_DIR}/emby_config.txt"
if ! check_port "6908"; then
ERROR "6908 端口被占用,请关闭占用此端口的程序!"
exit 1
fi
# shellcheck disable=SC2154
if [ "${mode}" == "bridge" ]; then
MODE=bridge
NET_MODE="-p 6908:6908"
elif [ "${mode}" == "host" ]; then
MODE=host
NET_MODE="--net=host"
else
choose_network_mode
fi
get_xiaoya_hosts
# shellcheck disable=SC2154
if [ "${dev_dri}" == "yes" ]; then
extra_parameters="--device /dev/dri:/dev/dri --privileged -e GIDLIST=0,0 -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=all"
fi
get_nsswitch_conf_path
if [ -n "${version}" ]; then
IMAGE_VERSION="${version}"
else
IMAGE_VERSION=4.9.0.42
fi
emby_fix_strmassistant "${MEDIA_DIR}/config"
emby_install_coverart "${MEDIA_DIR}/config"
# shellcheck disable=SC2154
if [ "${image}" == "emby" ]; then
install_emby_embyserver
elif [ "${image}" == "iceyheart" ]; then
install_iceyheart_embyserver
else
if [ "${DOCKER_ARCH}" == "linux/amd64" ] || [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
if [ "${IMAGE_VERSION}" == "${amilys_embyserver_beta_version}" ]; then
IMAGE_VERSION=beta
fi
if [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
WARN "amilys/embyserver_arm64v8 镜像无法指定版本号,默认拉取 latest 镜像!"
IMAGE_VERSION=latest
fi
install_amilys_embyserver
else
ERROR "全家桶 Emby 目前只支持 amd64 和 arm64 架构,你的架构是:$CPU_ARCH"
exit 1
fi
fi
else
choose_emby_image
if ! check_port "6908"; then
ERROR "6908 端口被占用,请关闭占用此端口的程序!"
exit 1
fi
choose_network_mode
get_xiaoya_hosts
INFO "如果需要开启Emby硬件转码请先返回主菜单开启容器运行额外参数添加 -> 72"
container_run_extra_parameters=$(cat ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt)
if [ "${container_run_extra_parameters}" == "true" ]; then
local RETURN_DATA
RETURN_DATA="$(data_crep "r" "install_xiaoya_emby")"
if [ "${RETURN_DATA}" == "None" ]; then
INFO "请输入其他参数(默认 --device /dev/dri:/dev/dri --privileged -e GIDLIST=0,0 -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=all )"
read -erp "Extra parameters:" extra_parameters
[[ -z "${extra_parameters}" ]] && extra_parameters="--device /dev/dri:/dev/dri --privileged -e GIDLIST=0,0 -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=all"
else
INFO "已读取您上次设置的参数:${RETURN_DATA} (默认不更改回车继续,如果需要更改请输入新参数)"
read -erp "Extra parameters:" extra_parameters
[[ -z "${extra_parameters}" ]] && extra_parameters=${RETURN_DATA}
if [ "${extra_parameters}" == "None" ]; then
extra_parameters="--device /dev/dri:/dev/dri --privileged -e GIDLIST=0,0 -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=all"
fi
fi
extra_parameters=$(data_crep "write" "install_xiaoya_emby")
fi
get_nsswitch_conf_path
while true; do
case ${CHOOSE_EMBY} in
"amilys_embyserver")
if [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
WARN "amilys/embyserver_arm64v8 镜像无法指定版本号,默认拉取 latest 镜像!"
IMAGE_VERSION=latest
break
else
INFO "请选择 Emby 镜像版本 [ 1: 4.9.0.42 | 2;latest(${amilys_embyserver_latest_version}) ](默认 1)"
read -erp "CHOOSE_IMAGE_VERSION:" CHOOSE_IMAGE_VERSION
[[ -z "${CHOOSE_IMAGE_VERSION}" ]] && CHOOSE_IMAGE_VERSION="1"
case ${CHOOSE_IMAGE_VERSION} in
1)
IMAGE_VERSION=4.9.0.42
if [ "${IMAGE_VERSION}" == "${amilys_embyserver_beta_version}" ]; then
IMAGE_VERSION=beta
fi
break
;;
2)
# IMAGE_VERSION=latest
# break
WARN "小雅 Emby 全家桶目前不支持 latest 镜像!"
INFO "按任意键重新配置"
read -rs -n 1 -p ""
;;
*)
ERROR "输入无效,请重新选择"
;;
esac
fi
;;
"lovechen_embyserver")
WARN "lovechen/embyserver 镜像无法指定版本号,默认拉取 4.7.14.0 镜像!"
IMAGE_VERSION=4.7.14.0
break
;;
"iceyheart_embycrk")
INFO "请选择 Emby 镜像版本 [ 1;4.9.0.42 ](默认 1)"
read -erp "CHOOSE_IMAGE_VERSION:" CHOOSE_IMAGE_VERSION
[[ -z "${CHOOSE_IMAGE_VERSION}" ]] && CHOOSE_IMAGE_VERSION="1"
case ${CHOOSE_IMAGE_VERSION} in
1)
IMAGE_VERSION=4.9.0.42
break
;;
*)
ERROR "输入无效,请重新选择"
;;
esac
;;
"emby_embyserver")
INFO "请选择 Emby 镜像版本 [ 1;4.9.0.42 | 2;latest(${emby_embyserver_latest_version}) ](默认 1)"
read -erp "CHOOSE_IMAGE_VERSION:" CHOOSE_IMAGE_VERSION
[[ -z "${CHOOSE_IMAGE_VERSION}" ]] && CHOOSE_IMAGE_VERSION="1"
case ${CHOOSE_IMAGE_VERSION} in
1)
IMAGE_VERSION=4.9.0.42
break
;;
2)
# IMAGE_VERSION=latest
# break
WARN "小雅 Emby 全家桶目前不支持 latest 镜像!"
INFO "按任意键重新配置"
read -rs -n 1 -p ""
;;
*)
ERROR "输入无效,请重新选择"
;;
esac
;;
esac
done
emby_fix_strmassistant "${MEDIA_DIR}/config"
emby_install_coverart "${MEDIA_DIR}/config"
case ${CHOOSE_EMBY} in
emby_embyserver)
install_emby_embyserver
;;
lovechen_embyserver)
install_lovechen_embyserver
;;
amilys_embyserver)
install_amilys_embyserver
;;
iceyheart_embycrk)
install_iceyheart_embyserver
;;
esac
fi
if [ ! -f "${CONFIG_DIR}"/infuse_api_key.txt ]; then
echo "e825ed6f7f8f44ffa0563cddaddce14d" > "${CONFIG_DIR}"/infuse_api_key.txt
auto_chown "${CONFIG_DIR}/infuse_api_key.txt"
fi
wait_emby_start
sleep 2
set_emby_server
if ! docker exec -i "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" curl -I -s http://127.0.0.1:2345/ | grep -q "302"; then
INFO "重启小雅容器中..."
docker restart "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
wait_xiaoya_start
fi
INFO "Emby安装完成!"
}
function oneclick_upgrade_emby() {
local emby_name emby_config_dir emby_ip
emby_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)
if docker inspect ddsderek/runlike:latest > /dev/null 2>&1; then
local_sha=$(docker inspect --format='{{index .RepoDigests 0}}' ddsderek/runlike:latest 2> /dev/null | cut -f2 -d:)
remote_sha=$(curl -s -m 10 "https://hub.docker.com/v2/repositories/ddsderek/runlike/tags/latest" | grep -o '"digest":"[^"]*' | grep -o '[^"]*$' | tail -n1 | cut -f2 -d:)
if [ "$local_sha" != "$remote_sha" ]; then
docker rmi ddsderek/runlike:latest
docker_pull "ddsderek/runlike:latest"
fi
else
docker_pull "ddsderek/runlike:latest"
fi
INFO "获取 ${emby_name} 容器信息中..."
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp ddsderek/runlike "${emby_name}" > "/tmp/container_update_${emby_name}"
old_image=$(docker container inspect -f '{{.Config.Image}}' "${emby_name}")
old_image_name="$(echo "${old_image}" | cut -d':' -f1)"
emby_config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "${emby_name}" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/config$" | awk -F: '{print $1}')"
if [[ "$(docker inspect -f '{{range $key, $value := .NetworkSettings.Networks}}{{$key}} {{end}}' "${emby_name}")" == *"only_for_emby"* ]]; then
emby_ip="$(docker inspect -f "{{ (index .NetworkSettings.Networks \"only_for_emby\").IPAddress }}" "${emby_name}")"
else
emby_ip=""
fi
INFO "获取 Emby 版本中..."
if get_emby_version; then
INFO "当前 Emby 版本:${emby_version}"
check_emby_version_status=true
else
check_emby_version_status=false
fi
while true; do
if [ "${old_image_name}" == "amilys/embyserver" ] || [ "${old_image_name}" == "amilys/embyserver_arm64v8" ]; then
if [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
WARN "amilys/embyserver_arm64v8 镜像无法指定版本号,默认重新拉取 latest 镜像更新容器!"
IMAGE_VERSION=latest
break
else
INFO "请选择 Emby 镜像版本 [ 1;4.9.0.42 | 2;latest(${amilys_embyserver_latest_version})| 3;beta(${amilys_embyserver_beta_version})](默认 1)"
read -erp "CHOOSE_IMAGE_VERSION:" CHOOSE_IMAGE_VERSION
[[ -z "${CHOOSE_IMAGE_VERSION}" ]] && CHOOSE_IMAGE_VERSION="1"
case ${CHOOSE_IMAGE_VERSION} in
1)
IMAGE_VERSION=4.9.0.42
if [ "${IMAGE_VERSION}" == "${amilys_embyserver_beta_version}" ]; then
IMAGE_VERSION=beta
choose_emby_version="${amilys_embyserver_beta_version}"
else
choose_emby_version="${IMAGE_VERSION}"
fi
;;
2)
# IMAGE_VERSION=latest
# choose_emby_version="${amilys_embyserver_latest_version}"
WARN "小雅 Emby 全家桶目前不支持 latest 镜像!"
INFO "按任意键继续配置"
read -rs -n 1 -p ""
;;
3)
IMAGE_VERSION=beta
choose_emby_version="${amilys_embyserver_beta_version}"
;;
*)
ERROR "输入无效,请重新选择"
;;
esac
if [ "${check_emby_version_status}" == true ] && [ -n "${choose_emby_version}" ]; then
if version_lt "${choose_emby_version}" "${emby_version}"; then
ERROR "您选择升级的 Emby 版本低于当前安装 Emby 版本,Emby 版本无法降级,请重新选择"
else
break
fi
elif [ "${check_emby_version_status}" == false ] && [ -n "${choose_emby_version}" ]; then
break
fi
fi
elif [ "${old_image_name}" == "lovechen/embyserver" ]; then
WARN "lovechen/embyserver 镜像无法更新!"
exit 0
elif [ "${old_image_name}" == "emby/embyserver" ] || [ "${old_image_name}" == "emby/embyserver_arm64v8" ]; then
INFO "请选择 Emby 镜像版本 [ 1;4.9.0.42 | 2;latest(${emby_embyserver_latest_version}) | 3;beta(${emby_embyserver_beta_version})](默认 1)"
read -erp "CHOOSE_IMAGE_VERSION:" CHOOSE_IMAGE_VERSION
[[ -z "${CHOOSE_IMAGE_VERSION}" ]] && CHOOSE_IMAGE_VERSION="1"
case ${CHOOSE_IMAGE_VERSION} in
1)
IMAGE_VERSION=4.9.0.42
choose_emby_version="${IMAGE_VERSION}"
;;
2)
# IMAGE_VERSION=latest
# choose_emby_version="${emby_embyserver_latest_version}"
WARN "小雅 Emby 全家桶目前不支持 latest 镜像!"
INFO "按任意键继续配置"
read -rs -n 1 -p ""
;;
3)
IMAGE_VERSION=beta
choose_emby_version="${emby_embyserver_beta_version}"
;;
*)
ERROR "输入无效,请重新选择"
;;
esac
if [ "${check_emby_version_status}" == true ] && [ -n "${choose_emby_version}" ]; then
if version_lt "${choose_emby_version}" "${emby_version}"; then
ERROR "您选择升级的 Emby 版本低于当前安装 Emby 版本,Emby 版本无法降级,请重新选择"
else
break
fi
elif [ "${check_emby_version_status}" == false ] && [ -n "${choose_emby_version}" ]; then
break
fi
else
WARN "${old_image_name} 此镜像暂时不支持升级操作!"
exit 0
fi
done
local config_dir
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/data$" | awk -F: '{print $1}')"
fi
if [ -n "${config_dir}" ]; then
if [ -f "${config_dir}/emby_config.txt" ]; then
INFO "检测到配置 emby_config.txt,自动更新 emby_config.txt 版本信息"
sedsh "s/version=.*/version=${IMAGE_VERSION}/" "${config_dir}/emby_config.txt"
fi
fi
if [ -n "${emby_config_dir}" ]; then
emby_fix_strmassistant "${emby_config_dir}"
emby_install_coverart "${emby_config_dir}"
fi
run_image="$(echo "${old_image}" | cut -d':' -f1):${IMAGE_VERSION}"
remove_image=$(docker images -q ${old_image})
sedsh "s|${old_image}|${run_image}|g" "/tmp/container_update_${emby_name}"
INFO "${old_image} ${old_image_name} ${run_image} ${remove_image}"
local retries=0
local max_retries=3
IMAGE_MIRROR=$(cat "${DDSREM_CONFIG_DIR}/image_mirror.txt")
while [ $retries -lt $max_retries ]; do
if docker pull "${IMAGE_MIRROR}/${run_image}"; then
INFO "${emby_name} 镜像拉取成功!"
break
else
WARN "${emby_name} 镜像拉取失败,正在进行第 $((retries + 1)) 次重试..."
retries=$((retries + 1))
fi
done
if [ $retries -eq $max_retries ]; then
ERROR "镜像拉取失败,已达到最大重试次数!"
exit 1
else
if [ "${IMAGE_MIRROR}" != "docker.io" ]; then
pull_image=$(docker images -q "${IMAGE_MIRROR}/${run_image}")
else
pull_image=$(docker images -q "${run_image}")
fi
if ! docker stop "${emby_name}" > /dev/null 2>&1; then
if ! docker kill "${emby_name}" > /dev/null 2>&1; then
docker rmi "${IMAGE_MIRROR}/${run_image}"
ERROR "更新失败,停止 ${emby_name} 容器失败!"
exit 1
fi
fi
INFO "停止 ${emby_name} 容器成功!"
if ! docker rm --force "${emby_name}" > /dev/null 2>&1; then
ERROR "更新失败,删除 ${emby_name} 容器失败!"
exit 1
fi
INFO "删除 ${emby_name} 容器成功!"
if [ "${pull_image}" != "${remove_image}" ]; then
INFO "删除 ${remove_image} 镜像中..."
docker rmi "${remove_image}" > /dev/null 2>&1
fi
if [ "${IMAGE_MIRROR}" != "docker.io" ]; then
docker tag "${IMAGE_MIRROR}/${run_image}" "${run_image}" > /dev/null 2>&1
docker rmi "${IMAGE_MIRROR}/${run_image}" > /dev/null 2>&1
fi
if [ -n "${emby_ip}" ]; then
if grep -q 'network=host' "/tmp/container_update_${emby_name}"; then
INFO "更改 host 网络模式为 only_for_emby 模式"
sedsh "s/network=host/network=only_for_emby --ip=${emby_ip}/" "/tmp/container_update_${emby_name}"
elif grep -q 'network=bridge' "/tmp/container_update_${emby_name}"; then
INFO "更改 bridge 网络模式为 only_for_emby 模式"
sedsh "s/network=bridge/network=only_for_emby --ip=${emby_ip}/" "/tmp/container_update_${emby_name}"
elif grep -q 'network=only_for_emby' "/tmp/container_update_${emby_name}"; then
INFO "重新配置 only_for_emby 网络模式"
sedsh "s/network=bridge/network=only_for_emby --ip=${emby_ip}/" "/tmp/container_update_${emby_name}"
else
INFO "添加 only_for_emby 网络模式"
sedsh "s/name=${emby_name}/name=${emby_name} --network=only_for_emby --ip=${emby_ip}/" "/tmp/container_update_${emby_name}"
fi
fi
if bash "/tmp/container_update_${emby_name}"; then
rm -f "/tmp/container_update_${emby_name}"
if [ -n "${emby_ip}" ]; then
INFO "${emby_name} 重新加入 bridge 网络"
docker network connect bridge "${emby_name}"
fi
wait_emby_start
INFO "${emby_name} 更新成功"
return 0
else
ERROR "更新失败,创建 ${emby_name} 容器失败!"
exit 1
fi
fi
}
function emby_close_6908_port() {
echo -e "${Yellow}此功能关闭 6908 访问是通过将 Emby 设置为桥接模式并取消端口映射,非防火墙屏蔽!!!${Font}"
echo -e "${Yellow}如果您使用此功能关闭 6908 访问,那您无法再使用浏览器访问 6908 端口使用 Emby!!!${Font}"
echo -e "${Yellow}如果您需要访问 Emby 并且走服务端流量,可以访问 2347 端口,此端口与 6908 逻辑一致!!!${Font}"
echo -e "${Yellow}正常使用依旧是访问 2345 端口即可愉快观影!!!${Font}"
local OPERATE
while true; do
INFO "是否继续操作 [Y/n](默认 Y)"
read -erp "OPERATE:" OPERATE
[[ -z "${OPERATE}" ]] && OPERATE="y"
if [[ ${OPERATE} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ "${OPERATE}" == [Nn] ]]; then
exit 0
fi
local CONTAINERS NETWORK_NAME SUBNET_CANDIDATES AVAILABLE_SUBNET ENBY_IP
NETWORK_NAME="only_for_emby"
SUBNET_CANDIDATES=(
"10.250.0.0/24"
"10.250.1.0/24"
"10.250.2.0/24"
"10.251.0.0/24"
)
if docker network inspect "$NETWORK_NAME" > /dev/null 2>&1; then
CONTAINERS=$(docker network inspect -f '{{range .Containers}}{{.Name}} {{end}}' "$NETWORK_NAME")
if [ -n "$CONTAINERS" ]; then
INFO "以下容器正在使用该网络,将被强制断开:"
INFO "$CONTAINERS"
for container in $CONTAINERS; do
INFO "正在断开容器 $container ..."
docker network disconnect -f "$NETWORK_NAME" "$container"
done
fi
docker network rm "$NETWORK_NAME"
INFO "旧 ${NETWORK_NAME} 网络已删除"
fi
function find_available_subnet() {
for subnet in "${SUBNET_CANDIDATES[@]}"; do
local conflict=0
local existing_networks config
existing_networks=$(docker network ls --quiet)
for net_id in $existing_networks; do
config=$(docker network inspect "$net_id" --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}')
if [ "$config" = "$subnet" ]; then
conflict=1
break
fi
done
if [ "$conflict" -eq 0 ]; then
echo "$subnet"
return 0
fi
done
echo ""
return 1
}
AVAILABLE_SUBNET=$(find_available_subnet)
if [ -z "$AVAILABLE_SUBNET" ]; then
ERROR "所有候选子网均已被占用,请手动删除冲突的子网"
exit 1
fi
GATEWAY="${AVAILABLE_SUBNET//0\/24/1}"
ENBY_IP="${AVAILABLE_SUBNET//0\/24/100}"
INFO "正在创建网络 $NETWORK_NAME,使用子网 $AVAILABLE_SUBNET,网关 $GATEWAY..."
docker network create \
--driver bridge \
--subnet "$AVAILABLE_SUBNET" \
--gateway "$GATEWAY" \
"$NETWORK_NAME"
INFO "网络 $NETWORK_NAME 创建成功!"
local emby_name config_dir xiaoya_name
xiaoya_name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
emby_name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)"
if docker inspect ddsderek/runlike:latest > /dev/null 2>&1; then
local_sha=$(docker inspect --format='{{index .RepoDigests 0}}' ddsderek/runlike:latest 2> /dev/null | cut -f2 -d:)
remote_sha=$(curl -s -m 10 "https://hub.docker.com/v2/repositories/ddsderek/runlike/tags/latest" | grep -o '"digest":"[^"]*' | grep -o '[^"]*$' | tail -n1 | cut -f2 -d:)
if [ "$local_sha" != "$remote_sha" ]; then
docker rmi ddsderek/runlike:latest
docker_pull "ddsderek/runlike:latest"
fi
else
docker_pull "ddsderek/runlike:latest"
fi
INFO "获取 ${emby_name} 容器信息中..."
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp ddsderek/runlike -p "${emby_name}" > "/tmp/container_update_${emby_name}"
INFO "更改 Emby 为 only_for_emby 模式并取消端口映射中..."
if grep -q 'network=host' "/tmp/container_update_${emby_name}"; then
INFO "更改 host 网络模式为 only_for_emby 模式"
sedsh "s/network=host/network=only_for_emby --ip=${ENBY_IP}/" "/tmp/container_update_${emby_name}"
elif grep -q 'network=bridge' "/tmp/container_update_${emby_name}"; then
INFO "更改 bridge 网络模式为 only_for_emby 模式"
sedsh "s/network=bridge/network=only_for_emby --ip=${ENBY_IP}/" "/tmp/container_update_${emby_name}"
elif grep -q 'network=only_for_emby' "/tmp/container_update_${emby_name}"; then
INFO "重新配置 only_for_emby 网络模式"
sedsh "s/network=bridge/network=only_for_emby --ip=${ENBY_IP}/" "/tmp/container_update_${emby_name}"
else
INFO "添加 only_for_emby 网络模式"
sedsh "s/name=${emby_name}/name=${emby_name} --network=only_for_emby --ip=${ENBY_IP}/" "/tmp/container_update_${emby_name}"
fi
if grep -q '6908:6908' "/tmp/container_update_${emby_name}"; then
INFO "关闭 6908 端口映射"
sedsh '/-p 6908:6908/d' "/tmp/container_update_${emby_name}"
fi
MODE=bridge
get_docker0_url
get_xiaoya_hosts
INFO "更改容器 host 配置"
sedsh "s/--add-host xiaoya.host.*/--add-host xiaoya.host:${xiaoya_host} \\\/" "/tmp/container_update_${emby_name}"
if ! docker stop "${emby_name}" > /dev/null 2>&1; then
if ! docker kill "${emby_name}" > /dev/null 2>&1; then
docker rmi "${IMAGE_MIRROR}/${run_image}"
ERROR "停止 ${emby_name} 容器失败!"
exit 1
fi
fi
INFO "停止 ${emby_name} 容器成功!"
if ! docker rm --force "${emby_name}" > /dev/null 2>&1; then
ERROR "删除 ${emby_name} 容器失败!"
exit 1
fi
if bash "/tmp/container_update_${emby_name}"; then
rm -f "/tmp/container_update_${emby_name}"
wait_emby_start
INFO "${emby_name} 容器启动成功!"
else
ERROR "创建 ${emby_name} 容器失败!"
exit 1
fi
docker network connect bridge "${emby_name}"
if [[ "$(docker inspect -f '{{range $key, $value := .NetworkSettings.Networks}}{{$key}} {{end}}' "${xiaoya_name}")" == *"bridge"* ]]; then
INFO "小雅容器自动加入 only_for_emby 网络中..."
docker network connect only_for_emby "${xiaoya_name}"
fi
INFO "配置 emby_server.txt 文件中"
config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "${xiaoya_name}" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/data$" | awk -F: '{print $1}')"
if [ -z "${config_dir}" ]; then
WARN "小雅容器配置目录获取失败,请手动输入!"
get_config_dir
config_dir=${CONFIG_DIR}
fi
echo "http://$ENBY_IP:6908" > "${config_dir}"/emby_server.txt
auto_chown "${config_dir}/emby_server.txt"
INFO "重启小雅容器"
docker restart "${xiaoya_name}"
wait_xiaoya_start
INFO "关闭 Emby 6908 端口完成!"
}
function xiaoya_emd_updated_tips() {
if ! docker exec -i xiaoya-emd grep -q 'main_solid' /entrypoint.sh > /dev/null 2>&1; then
ERROR "当前版本小雅元数据定时爬虫不支持执行此操作,请手动卸载重新安装!"
exit 1
fi
if [ "${1}" != "None" ]; then
if version_lt "$(docker exec -i xiaoya-emd awk -F '=' '/IMAGE_VERSION/ {print $2}' /entrypoint.sh | head -n 1)" "${1}"; then
ERROR "当前版本小雅元数据定时爬虫不支持执行此操作,请手动卸载重新安装!"
exit 1
fi
fi
}
function xiaoya_emd_pathlib() {
if [ "${1}" == "install" ]; then
PATHLIB_DIR="${2}/pathlib.txt"
if [ ! -f "${PATHLIB_DIR}" ]; then
echo -e "每日更新/\n纪录片(已刮削)/\n" > "${PATHLIB_DIR}"
fi
elif [ "${1}" == "once" ]; then
PATHLIB_DIR="${2}/once_pathlib.txt"
touch_chmod "${2}/once_pathlib.txt"
fi
sedsh '/^[[:space:]]*$/d' "${PATHLIB_DIR}"
while true; do
clear
emd_all_paths=('动漫/' '每日更新/' '电影/' '电视剧/' '纪录片/' '纪录片(已刮削)/' '综艺/' '音乐/' '测试/' '📺画质演示测试(4K,8K,HDR,Dolby)/')
interface=
file_array=()
while IFS= read -r line; do
file_array+=("$line")
done < "${PATHLIB_DIR}"
for i in "${file_array[@]}"; do
skip=false
for j in "${emd_all_paths[@]}"; do
if [ "$i" == "$j" ]; then
skip=true
break
fi
done
if [[ "$skip" = false ]]; then
emd_all_paths+=("$i")
fi
done
for i in "${!emd_all_paths[@]}"; do
local CONTENT
if grep -q "^${emd_all_paths[$i]}$" "${PATHLIB_DIR}"; then
CONTENT="${Green}已选中${Font}"
else
CONTENT="${Red}未选中${Font}"
fi
if ((i + 1 <= 10)); then
interface+="$((i + 1))、${emd_all_paths[$i]}(${CONTENT})\n"
else
interface+="$((i + 1))、${emd_all_paths[$i]}(${Sky_Blue}用户自定义${Font})(${CONTENT})\n"
fi
done
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}爬取目录选择${Font}\n"
echo -e "${Sky_Blue}红色代表未选中,绿色代表已选中,输入对应选项数字可勾选或取消勾选"
echo -e "支持输入多个数字,支持自定义爬取路径和现有选项一起输入,自定义爬取路径需要用''包裹"
echo -e "示例:1 5 8 9 10 '电影/豆瓣 top 1000部/' '每日更新/动漫/'${Font}\n"
echo -e "${interface}\c"
if [ "${1}" == "install" ]; then
echo -e "101、重置配置"
fi
echo -e "0、保存退出"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字或路径:" user_paths
if [ -n "${user_paths}" ]; then
if [ "${user_paths}" == 0 ]; then
clear
break
fi
if [ "${user_paths}" == 101 ] && [ "${1}" == "install" ]; then
echo -e "每日更新/\n纪录片(已刮削)/\n" > "${PATHLIB_DIR}"
clear
fi
eval "user_path_array=($user_paths)"
# shellcheck disable=SC2154
for j in "${!user_path_array[@]}"; do
if [[ "${user_path_array[$j]}" -eq "${user_path_array[$j]}" ]] 2> /dev/null; then
for i in "${!emd_all_paths[@]}"; do
if [[ "$((i + 1))" == "${user_path_array[$j]}" ]]; then
if grep -q "^${emd_all_paths[$i]}$" "${PATHLIB_DIR}"; then
sedsh "\#${emd_all_paths[$i]}#d" "${PATHLIB_DIR}"
else
echo "${emd_all_paths[$i]}" >> "${PATHLIB_DIR}"
fi
break
fi
done
else
if grep -q "^${user_path_array[$j]}$" "${PATHLIB_DIR}"; then
sedsh "\#${user_path_array[$j]}#d" "${PATHLIB_DIR}"
else
echo "${user_path_array[$j]}" >> "${PATHLIB_DIR}"
fi
fi
done
sedsh '/^[[:space:]]*$/d' "${PATHLIB_DIR}"
fi
done
}
function install_xiaoya_emd() {
if docker container inspect xiaoya-emd-go > /dev/null 2>&1; then
WARN "当前已安装 小雅元数据爬虫(Web 版本),无法同时安装多个爬虫"
return 1
fi
get_media_dir
while true; do
INFO "请输入您希望的爬虫同步间隔"
WARN "循环时间必须大于12h,为了减轻服务器压力,请用户理解!"
read -erp "请输入以小时为单位的正整数同步间隔时间(默认:12):" sync_interval
[[ -z "${sync_interval}" ]] && sync_interval="12"
if [[ "$sync_interval" -ge 12 ]]; then
break
else
ERROR "输入错误,请重新输入。同步间隔时间必须为12以上的正整数。"
fi
done
cycle=$((sync_interval * 60 * 60))
xiaoya_emd_pathlib "install" "${MEDIA_DIR}/xiaoya"
while true; do
INFO "是否开启重启容器自动更新到最新程序 [Y/n](默认 n 不开启)"
WARN "需要拥有良好的上网环境才可以更新成功,要能访问 Github 和 Python PIP 库!"
read -erp "RESTART_AUTO_UPDATE:" RESTART_AUTO_UPDATE
[[ -z "${RESTART_AUTO_UPDATE}" ]] && RESTART_AUTO_UPDATE="n"
if [[ ${RESTART_AUTO_UPDATE} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${RESTART_AUTO_UPDATE} == [Yy] ]]; then
RESTART_AUTO_UPDATE=true
else
RESTART_AUTO_UPDATE=false
fi
while true; do
INFO "请选择镜像版本 [ 1;latest | 2;beta ](默认 1)"
read -erp "CHOOSE_IMAGE_VERSION:" CHOOSE_IMAGE_VERSION
[[ -z "${CHOOSE_IMAGE_VERSION}" ]] && CHOOSE_IMAGE_VERSION="1"
case ${CHOOSE_IMAGE_VERSION} in
1)
IMAGE_VERSION=latest
break
;;
2)
IMAGE_VERSION=beta
break
;;
*)
ERROR "输入无效,请重新选择"
;;
esac
done
while true; do
INFO "是否自动配置系统 inotify watches & instances 的数值 [Y/n](默认 Y)"
read -erp "inotify:" inotify_set
[[ -z "${inotify_set}" ]] && inotify_set="y"
if [[ ${inotify_set} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${inotify_set} == [Yy] ]]; then
if ! grep -q "fs.inotify.max_user_watches=524288" /etc/sysctl.conf; then
echo fs.inotify.max_user_watches=524288 | tee -a /etc/sysctl.conf
else
INFO "系统 inotify watches 数值已存在!"
fi
if ! grep -q "fs.inotify.max_user_instances=524288" /etc/sysctl.conf; then
echo fs.inotify.max_user_instances=524288 | tee -a /etc/sysctl.conf
else
INFO "系统 inotify instances 数值已存在!"
fi
# 清除多余的inotify设置
awk \
'!seen[$0]++ || !/^(fs\.inotify\.max_user_instances|fs\.inotify\.max_user_watches)/' /etc/sysctl.conf > \
/tmp/sysctl.conf.tmp && mv /tmp/sysctl.conf.tmp /etc/sysctl.conf
sysctl -p
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" > /dev/null 2>&1; then
case "$(docker inspect --format='{{.State.Status}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)")" in
"running")
INFO "重启 Emby 容器中..."
docker restart "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)"
;;
esac
fi
INFO "系统 inotify watches & instances 数值配置成功!"
fi
extra_parameters=
container_run_extra_parameters=$(cat ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt)
if [ "${container_run_extra_parameters}" == "true" ]; then
local RETURN_DATA
RETURN_DATA="$(data_crep "r" "install_xiaoya_emd")"
# 兼容新版本参数
if [ "${RETURN_DATA}" == "--media /media" ]; then
RETURN_DATA="--media /media --paths /media/pathlib.txt"
fi
if [ "${RETURN_DATA}" == "None" ]; then
INFO "请输入运行参数(默认 --media /media --paths /media/pathlib.txt )"
WARN "如果需要更改此设置请注意容器目录映射,默认媒体库路径映射到容器内的 /media 文件夹下!"
WARN "警告!!! 默认请勿修改 /media 路径!!!"
read -erp "Extra parameters:" extra_parameters
[[ -z "${extra_parameters}" ]] && extra_parameters="--media /media --paths /media/pathlib.txt"
else
INFO "已读取您上次设置的运行参数:${RETURN_DATA} (默认不更改回车继续,如果需要更改请输入新参数)"
WARN "如果需要更改此设置请注意容器目录映射,默认媒体库路径映射到容器内的 /media 文件夹下!"
WARN "警告!!! 默认请勿修改 /media 路径!!!"
read -erp "Extra parameters:" extra_parameters
[[ -z "${extra_parameters}" ]] && extra_parameters=${RETURN_DATA}
if [ "${extra_parameters}" == "None" ]; then
extra_parameters="--media /media --paths /media/pathlib.txt"
fi
fi
else
extra_parameters="--media /media --paths /media/pathlib.txt"
fi
script_extra_parameters="$(data_crep "write" "install_xiaoya_emd")"
extra_parameters=
container_run_extra_parameters=$(cat ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt)
if [ "${container_run_extra_parameters}" == "true" ]; then
local RETURN_DATA_2
RETURN_DATA_2="$(data_crep "r" "install_xiaoya_emd_2")"
if [ "${RETURN_DATA_2}" == "None" ]; then
INFO "请输入运行容器额外参数(默认 无 )"
read -erp "Extra parameters:" extra_parameters
else
INFO "已读取您上次设置的运行容器额外参数:${RETURN_DATA_2} (默认不更改回车继续,如果需要更改请输入新参数)"
read -erp "Extra parameters:" extra_parameters
[[ -z "${extra_parameters}" ]] && extra_parameters=${RETURN_DATA_2}
fi
run_extra_parameters=$(data_crep "w" "install_xiaoya_emd_2")
fi
docker_pull "ddsderek/xiaoya-emd:${IMAGE_VERSION}"
# shellcheck disable=SC2046
docker run -d \
--name=xiaoya-emd \
--restart=always \
--net=host \
-v "${MEDIA_DIR}/xiaoya:/media" \
-e "CYCLE=${cycle}" \
-e "RESTART_AUTO_UPDATE=${RESTART_AUTO_UPDATE}" \
-e TZ=Asia/Shanghai \
${run_extra_parameters} \
$(auto_privileged) \
ddsderek/xiaoya-emd:${IMAGE_VERSION} \
${script_extra_parameters}
INFO "安装完成!"
}
function update_xiaoya_emd() {
xiaoya_emd_updated_tips "None"
for i in $(seq -w 3 -1 0); do
echo -en "即将开始更新小雅元数据定时爬虫${Blue} $i ${Font}\r"
sleep 1
done
xiaoya_emd_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' xiaoya-emd | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/media$" | awk -F: '{print $1}')"
if [ -n "${xiaoya_emd_dir}" ]; then
if [ -f "${xiaoya_emd_dir}/solid.lock" ]; then
INFO "检测到存在进程锁,清理中..."
rm -f "${xiaoya_emd_dir}/solid.lock"
fi
fi
container_update xiaoya-emd
}
function unisntall_xiaoya_emd() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载小雅元数据定时爬虫${Blue} $i ${Font}\r"
sleep 1
done
xiaoya_emd_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' xiaoya-emd | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/media$" | awk -F: '{print $1}')"
docker stop xiaoya-emd
docker rm xiaoya-emd
docker rmi ddsderek/xiaoya-emd:latest
if [ -n "${xiaoya_emd_dir}" ]; then
for file in "solid.lock" "once_pathlib.txt" "pathlib.txt" ".tempfiles.db" ".localfiles.db"; do
if [ -f "${xiaoya_emd_dir}/${file}" ]; then
INFO "清理 ${file} 文件"
rm -f "${xiaoya_emd_dir}/${file}"
fi
done
fi
INFO "小雅元数据定时爬虫卸载成功!"
}
function once_xiaoya_emd() {
xiaoya_emd_updated_tips "v1.0.0"
xiaoya_emd_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' xiaoya-emd | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/media$" | awk -F: '{print $1}')"
if [ -z "${xiaoya_emd_dir}" ]; then
get_media_dir
xiaoya_emd_dir="${MEDIA_DIR}/xiaoya"
fi
INFO "小雅媒体库路径:${xiaoya_emd_dir}"
sleep 2
xiaoya_emd_pathlib "once" "${xiaoya_emd_dir}"
cat << EOF > "${xiaoya_emd_dir}/once_run.sh"
cd /app || exit 1
if [ -d /tmp/db ]; then
rm -rf /tmp/db
fi
mkdir -p /tmp/db
if [ -f /media/solid.lock ] && grep -q 'python3 solid.py'; then
echo -e "${ERROR} 当前已有爬虫进程在运行,请稍后再试!"
exit 1
else
touch /media/solid.lock
echo -e "${INFO} 开始下载同步!"
echo -e "${INFO} python3 solid.py --media /media --paths /media/once_pathlib.txt --location /tmp/db"
python3 solid.py --media /media --paths /media/once_pathlib.txt --location /tmp/db
echo -e "${INFO} 运行完成!"
rm -f /media/solid.lock
exit 0
fi
EOF
for i in $(seq -w 3 -1 0); do
echo -en "即将开始爬取指定元数据${Blue} $i ${Font}\r"
sleep 1
done
docker exec -it xiaoya-emd bash /media/once_run.sh
docker exec -it xiaoya-emd rm -f /media/once_run.sh
docker exec -it xiaoya-emd rm -f /media/once_pathlib.txt
}
function main_xiaoya_emd() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}小雅元数据定时爬虫${Font}\n"
echo -e "${Sky_Blue}小雅元数据定时爬虫由 https://github.com/Rik-F5 更新维护,在此表示感谢!"
echo -e "具体详细配置参数请看项目README:https://github.com/xiaoyaDev/xiaoya_db${Font}\n"
echo -e "1、安装"
echo -e "2、更新"
echo -e "3、卸载"
echo -e "4、立刻爬取指定目录"
echo -e "5、容器定时爬取目录单独配置"
echo -e "6、清理爬虫进程锁"
echo -e "7、重置爬虫数据库"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-7]:" num
case "$num" in
1)
clear
install_xiaoya_emd
return_menu "main_xiaoya_emd"
;;
2)
clear
update_xiaoya_emd
return_menu "main_xiaoya_emd"
;;
3)
clear
unisntall_xiaoya_emd
return_menu "main_xiaoya_emd"
;;
4)
clear
once_xiaoya_emd
return_menu "main_xiaoya_emd"
;;
5)
clear
xiaoya_emd_updated_tips "v1.0.0"
xiaoya_emd_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' xiaoya-emd | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/media$" | awk -F: '{print $1}')"
if [ -z "${xiaoya_emd_dir}" ]; then
get_media_dir
xiaoya_emd_dir="${MEDIA_DIR}/xiaoya"
fi
INFO "小雅媒体库路径:${xiaoya_emd_dir}"
sleep 2
xiaoya_emd_pathlib "install" "${xiaoya_emd_dir}"
return_menu "main_xiaoya_emd"
;;
6)
clear
xiaoya_emd_updated_tips "v1.0.0"
if [ "$(docker inspect --format='{{.State.Status}}' xiaoya-emd)" == "running" ]; then
if docker exec -it xiaoya-emd ps -ef | grep -q 'python3 solid.py'; then
ERROR "当前有爬虫进程正在运行,无法清理进程锁!"
exit 1
else
if docker exec -it xiaoya-emd ls -al /media/solid.lock > /dev/null 2>&1; then
INFO "检测到存在进程锁,清理中..."
docker exec -it xiaoya-emd rm -f /media/solid.lock
fi
fi
else
xiaoya_emd_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' xiaoya-emd | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/media$" | awk -F: '{print $1}')"
if [ -n "${xiaoya_emd_dir}" ]; then
if [ -f "${xiaoya_emd_dir}/solid.lock" ]; then
INFO "检测到存在进程锁,清理中..."
rm -f "${xiaoya_emd_dir}/solid.lock"
fi
fi
fi
INFO "进程锁清理完成!"
return_menu "main_xiaoya_emd"
;;
7)
clear
xiaoya_emd_updated_tips "v1.0.0"
if [ "$(docker inspect --format='{{.State.Status}}' xiaoya-emd)" == "running" ]; then
if docker exec -it xiaoya-emd ps -ef | grep -q 'python3 solid.py'; then
ERROR "当前有爬虫进程正在运行,无法重置数据库!"
exit 1
fi
fi
xiaoya_emd_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' xiaoya-emd | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/media$" | awk -F: '{print $1}')"
if [ -n "${xiaoya_emd_dir}" ]; then
for file in ".tempfiles.db" ".localfiles.db"; do
if [ -f "${xiaoya_emd_dir}/${file}" ]; then
INFO "清理 ${file} 文件"
rm -f "${xiaoya_emd_dir}/${file}"
fi
done
INFO "数据库重置完成!"
else
ERROR "数据库重置失败,无法读取媒体库路径,请手动删除媒体库路径下面的 db 后缀文件!"
exit 1
fi
return_menu "main_xiaoya_emd"
;;
0)
clear
main_xiaoya_all_emby
;;
*)
clear
ERROR '请输入正确数字 [0-7]'
main_xiaoya_emd
;;
esac
}
function install_xiaoya_emd_go() {
if docker container inspect xiaoya-emd > /dev/null 2>&1; then
WARN "当前已安装 小雅元数据定时爬虫,无法同时安装多个爬虫"
return 1
fi
local web_port
get_media_dir
while true; do
INFO "请输入后台管理端口(默认 9801 )"
read -erp "Web Port:" web_port
[[ -z "${web_port}" ]] && web_port="9801"
if check_port "${web_port}"; then
break
else
ERROR "${web_port} 此端口被占用,请输入其他端口!"
fi
done
while true; do
INFO "是否自动配置系统 inotify watches & instances 的数值 [Y/n](默认 Y)"
read -erp "inotify:" inotify_set
[[ -z "${inotify_set}" ]] && inotify_set="y"
if [[ ${inotify_set} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${inotify_set} == [Yy] ]]; then
if ! grep -q "fs.inotify.max_user_watches=524288" /etc/sysctl.conf; then
echo fs.inotify.max_user_watches=524288 | tee -a /etc/sysctl.conf
else
INFO "系统 inotify watches 数值已存在!"
fi
if ! grep -q "fs.inotify.max_user_instances=524288" /etc/sysctl.conf; then
echo fs.inotify.max_user_instances=524288 | tee -a /etc/sysctl.conf
else
INFO "系统 inotify instances 数值已存在!"
fi
# 清除多余的inotify设置
awk \
'!seen[$0]++ || !/^(fs\.inotify\.max_user_instances|fs\.inotify\.max_user_watches)/' /etc/sysctl.conf > \
/tmp/sysctl.conf.tmp && mv /tmp/sysctl.conf.tmp /etc/sysctl.conf
sysctl -p
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)" > /dev/null 2>&1; then
case "$(docker inspect --format='{{.State.Status}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)")" in
"running")
INFO "重启 Emby 容器中..."
docker restart "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)"
;;
esac
fi
INFO "系统 inotify watches & instances 数值配置成功!"
fi
docker_pull "ddsderek/xiaoya-emd-go:latest"
docker run -d \
--name=xiaoya-emd-go \
--restart=always \
--net=host \
-v "${MEDIA_DIR}/xiaoya:/media" \
ddsderek/xiaoya-emd-go:latest \
--media=/media --port="${web_port}"
INFO "安装完成!"
INFO "浏览器访问 爬虫后台:${Sky_Blue}http://ip:${web_port}${Font}"
}
function update_xiaoya_emd_go() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始更新小雅元数据爬虫(Web 版本)${Blue} $i ${Font}\r"
sleep 1
done
container_update xiaoya-emd-go
}
function unisntall_xiaoya_emd_go() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载小雅元数据爬虫(Web 版本)${Blue} $i ${Font}\r"
sleep 1
done
docker stop xiaoya-emd-go
docker rm xiaoya-emd-go
docker rmi ddsderek/xiaoya-emd-go:latest
INFO "小雅元数据爬虫(Web 版本)卸载成功!"
}
function main_xiaoya_emd_go() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}小雅元数据爬虫(Web 版本)${Font}\n"
echo -e "${Red}警告:此功能目前处于公测状态,请自行甄别使用风险${Font}\n"
echo -e "1、安装"
echo -e "2、更新"
echo -e "3、卸载"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-3]:" num
case "$num" in
1)
clear
install_xiaoya_emd_go
return_menu "main_xiaoya_emd_go"
;;
2)
clear
update_xiaoya_emd_go
return_menu "main_xiaoya_emd_go"
;;
3)
clear
unisntall_xiaoya_emd_go
return_menu "main_xiaoya_emd_go"
;;
0)
clear
main_xiaoya_all_emby
;;
*)
clear
ERROR '请输入正确数字 [0-7]'
main_xiaoya_emd_go
;;
esac
}
function uninstall_xiaoya_all_emby() {
while true; do
INFO "是否${Red}删除配置文件${Font} [Y/n](默认 Y 删除)"
read -erp "Clean config:" CLEAN_CONFIG
[[ -z "${CLEAN_CONFIG}" ]] && CLEAN_CONFIG="y"
if [[ ${CLEAN_CONFIG} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载小雅Emby全家桶${Blue} $i ${Font}\r"
sleep 1
done
IMAGE_NAME="$(docker inspect --format='{{.Config.Image}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)")"
docker stop "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)"
docker rm "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)"
docker rmi "${IMAGE_NAME}"
if [[ ${CLEAN_CONFIG} == [Yy] ]]; then
INFO "清理配置文件..."
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_media_dir.txt ]; then
OLD_MEDIA_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_media_dir.txt)
rm -rf "${OLD_MEDIA_DIR}"
fi
fi
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_resilio_name.txt)" > /dev/null 2>&1; then
unisntall_resilio
fi
if docker container inspect xiaoya-emd > /dev/null 2>&1; then
unisntall_xiaoya_emd
fi
INFO "全家桶卸载成功!"
}
function auto_clean_metadata_mp4_files() {
__auto_clean_metadata_mp4_file=$(cat "${DDSREM_CONFIG_DIR}/auto_clean_metadata_mp4_file.txt")
if [ "${__auto_clean_metadata_mp4_file}" == "true" ]; then
_auto_clean_metadata_mp4_file="${Green}开启${Font}"
elif [ "${__auto_clean_metadata_mp4_file}" == "false" ]; then
_auto_clean_metadata_mp4_file="${Red}关闭${Font}"
else
_auto_clean_metadata_mp4_file="${Red}错误${Font}"
fi
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}元数据压缩文件清理${Font}\n"
echo -e "1、开启/关闭 解压成功后自动清理 mp4 元数据文件 当前状态:${_auto_clean_metadata_mp4_file}"
echo -e "2、一键清理当前所有 mp4 元数据文件"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-2]:" num
case "$num" in
1)
if [ "${__auto_clean_metadata_mp4_file}" == "false" ]; then
echo 'true' > ${DDSREM_CONFIG_DIR}/auto_clean_metadata_mp4_file.txt
else
echo 'false' > ${DDSREM_CONFIG_DIR}/auto_clean_metadata_mp4_file.txt
fi
clear
auto_clean_metadata_mp4_files
;;
2)
clear
get_media_dir
WARN "将清理以下所有文件:"
find "${MEDIA_DIR}/temp" -type f -name "*.mp4"
local OPERATE
while true; do
INFO "是否继续操作 [Y/n](默认 Y)"
read -erp "OPERATE:" OPERATE
[[ -z "${OPERATE}" ]] && OPERATE="y"
if [[ ${OPERATE} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ "${OPERATE}" == [Nn] ]]; then
exit 0
fi
for i in $(seq -w 3 -1 0); do
echo -en "即将开始清理${Blue} $i ${Font}\r"
sleep 1
done
find "${MEDIA_DIR}/temp" -type f -name "*.mp4" -delete
INFO "清理完成!"
return_menu "auto_clean_metadata_mp4_files"
;;
0)
clear
main_xiaoya_all_emby_other_features
;;
*)
clear
ERROR '请输入正确数字 [0-2]'
auto_clean_metadata_mp4_files
;;
esac
}
function main_xiaoya_all_emby_other_features() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}小雅Emby全家桶其他功能${Font}\n"
echo -e "1、自动清理 mp4 元数据文件"
echo -e "2、关闭 Emby 6908 端口访问"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-2]:" num
case "$num" in
1)
clear
auto_clean_metadata_mp4_files
;;
2)
clear
emby_close_6908_port
return_menu "main_xiaoya_all_emby_other_features"
;;
0)
clear
main_xiaoya_all_emby
;;
*)
clear
ERROR '请输入正确数字 [0-2]'
main_xiaoya_all_emby_other_features
;;
esac
}
function main_xiaoya_all_emby() {
local show_main_xiaoya_all_emby
show_main_xiaoya_all_emby=false
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}小雅Emby全家桶${Font}\n"
echo -e "${Yellow}注意:当前 Emby 全家桶要求 Emby 容器版本不低于 4.9.0.42${Font}"
echo -e "${Yellow}如果您的版本低于 4.9.0.42 请使用 菜单2-7 一键升级版本${Font}"
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
local container_status
container_status=$(docker inspect --format='{{.State.Status}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)")
case "${container_status}" in
"running")
echo
show_main_xiaoya_all_emby=true
;;
*)
echo -e "\n${Red}警告:您的小雅容器未正常启动,请先检查小雅容器后再安装全家桶${Font}\n"
;;
esac
else
echo -e "${Red}\n警告:您未安装小雅容器,请先安装小雅容器后再安装全家桶${Font}\n"
fi
echo -ne "${INFO} 界面加载中...${Font}\r"
if [ "${show_main_xiaoya_all_emby}" == "true" ]; then
echo -e "1、一键安装Emby全家桶
2、下载/解压 元数据
3、安装 Emby(可选择版本)
4、图形化编辑 emby_config.txt
5、安装/更新/卸载 小雅元数据定时爬虫 当前状态:$(judgment_container xiaoya-emd)
6、安装/更新/卸载 小雅元数据爬虫(Web 版本) 当前状态:$(judgment_container xiaoya-emd-go)
7、一键升级 Emby 容器(可选择镜像版本)
8、卸载 Emby 全家桶
9、其他功能"
fi
echo -e "0、返回上级 "
echo -e "——————————————————————————————————————————————————————————————————————————————————"
if [ "${show_main_xiaoya_all_emby}" == "true" ]; then
read -erp "请输入数字 [0-9]:" num
else
read -erp "请输入数字 [0]:" num
fi
case "$num" in
1)
clear
download_unzip_xiaoya_all_emby
install_emby_xiaoya_all_emby
XIAOYA_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
if [ -s "${XIAOYA_CONFIG_DIR}/emby_config.txt" ]; then
# shellcheck disable=SC1091
source "${XIAOYA_CONFIG_DIR}/emby_config.txt"
if [ -n "${resilio}" ]; then
WARN "Resilio-Sync 已弃用,默认使用 小雅元数据定时爬虫"
fi
fi
while true; do
INFO "是否安装 小雅元数据定时爬虫 [Y/n](默认 Y)"
read -erp "INSTALL:" xiaoya_emd_install
[[ -z "${xiaoya_emd_install}" ]] && xiaoya_emd_install="y"
if [[ ${xiaoya_emd_install} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${xiaoya_emd_install} == [Yy] ]]; then
install_xiaoya_emd
fi
INFO "Emby 全家桶安装完成! "
INFO "浏览器访问 Emby 服务:${Sky_Blue}http://ip:2345${Font}, 默认用户密码: ${Sky_Blue}xiaoya/1234${Font}"
return_menu "main_xiaoya_all_emby"
;;
2)
clear
main_download_unzip_xiaoya_emby "1"
;;
3)
clear
get_config_dir
get_media_dir
install_emby_xiaoya_all_emby
return_menu "main_xiaoya_all_emby"
;;
4)
clear
get_config_dir
bash -c "$(curl -sLk https://ddsrem.com/xiaoya/emby_config_editor.sh)" -s ${CONFIG_DIR}
main_xiaoya_all_emby
;;
5)
clear
main_xiaoya_emd
;;
6)
clear
main_xiaoya_emd_go
;;
7)
clear
oneclick_upgrade_emby
return_menu "main_xiaoya_all_emby"
;;
8)
clear
uninstall_xiaoya_all_emby
;;
9)
clear
main_xiaoya_all_emby_other_features
;;
0)
clear
main_return
;;
*)
clear
ERROR '请输入正确数字 [0-9]'
main_xiaoya_all_emby
;;
esac
}
function xiaoyahelper_install_check() {
local URL="$1"
if bash -c "$(curl --insecure -fsSL -k ${URL} | tail -n +2)" -s "${MODE}" ${TG_CHOOSE}; then
if docker container inspect xiaoyakeeper > /dev/null 2>&1; then
INFO "安装完成!"
return 0
else
return 1
fi
else
return 1
fi
}
function install_xiaoyahelper() {
INFO "选择模式:[3/5](默认 3)"
INFO "模式3: 定时运行小雅转存清理并升级小雅镜像"
INFO "模式5: 只要产生了播放缓存一分钟内立即清理。签到和定时升级同模式3"
read -erp "MODE:" MODE
[[ -z "${MODE}" ]] && MODE="3"
while true; do
INFO "是否使用Telegram通知 [Y/n](默认 n 不使用)"
read -erp "TG:" TG
[[ -z "${TG}" ]] && TG="n"
if [[ ${TG} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${TG} == [Yy] ]]; then
TG_CHOOSE="-tg"
fi
docker_pull "ddsderek/xiaoyakeeper:latest"
XIAOYAHELPER_URL="https://xiaoyahelper.ddsrem.com/aliyun_clear.sh"
if xiaoyahelper_install_check "${XIAOYAHELPER_URL}"; then
return 0
fi
XIAOYAHELPER_URL="https://xiaoyahelper.zengge99.eu.org/aliyun_clear.sh"
if xiaoyahelper_install_check "${XIAOYAHELPER_URL}"; then
return 0
fi
ERROR "安装失败!"
return 1
}
function once_xiaoyahelper() {
while true; do
INFO "是否使用Telegram通知 [Y/n](默认 n 不使用)"
read -erp "TG:" TG
[[ -z "${TG}" ]] && TG="n"
if [[ ${TG} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${TG} == [Yy] ]]; then
TG_CHOOSE="-tg"
fi
XIAOYAHELPER_URL="https://xiaoyahelper.ddsrem.com/aliyun_clear.sh"
if bash -c "$(curl --insecure -fsSL -k ${XIAOYAHELPER_URL} | tail -n +2)" -s 1 ${TG_CHOOSE}; then
INFO "运行完成!"
else
XIAOYAHELPER_URL="https://xiaoyahelper.zengge99.eu.org/aliyun_clear.sh"
if bash -c "$(curl --insecure -fsSL -k ${XIAOYAHELPER_URL} | tail -n +2)" -s 1 ${TG_CHOOSE}; then
INFO "运行完成!"
else
ERROR "运行失败!"
exit 1
fi
fi
}
function uninstall_xiaoyahelper() {
while true; do
INFO "是否${Red}删除配置文件${Font} [Y/n](默认 Y 删除)"
read -erp "Clean config:" CLEAN_CONFIG
[[ -z "${CLEAN_CONFIG}" ]] && CLEAN_CONFIG="y"
if [[ ${CLEAN_CONFIG} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载小雅助手(xiaoyahelper)${Blue} $i ${Font}\r"
sleep 1
done
docker stop xiaoyakeeper
docker rm xiaoyakeeper
docker rmi dockerproxy.com/library/alpine:3.18.2 > /dev/null 2>&1
docker rmi alpine:3.18.2 > /dev/null 2>&1
docker rmi ddsderek/xiaoyakeeper:latest
if [[ ${CLEAN_CONFIG} == [Yy] ]]; then
INFO "清理配置文件..."
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt ]; then
OLD_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
for file in "${OLD_CONFIG_DIR}/mycheckintoken.txt" "${OLD_CONFIG_DIR}/mycmd.txt" "${OLD_CONFIG_DIR}/myruntime.txt"; do
if [ -f "$file" ]; then
rm -f "$file"
fi
done
fi
rm -f ${OLD_CONFIG_DIR}/*json
fi
INFO "小雅助手(xiaoyahelper)卸载成功!"
}
function main_xiaoyahelper() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}小雅助手(xiaoyahelper)${Font}\n"
echo -e "1、安装/更新"
echo -e "2、一次性运行"
echo -e "3、卸载"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-3]:" num
case "$num" in
1)
clear
install_xiaoyahelper
return_menu "main_xiaoyahelper"
;;
2)
clear
once_xiaoyahelper
;;
3)
clear
uninstall_xiaoyahelper
return_menu "main_xiaoyahelper"
;;
0)
clear
main_return
;;
*)
clear
ERROR '请输入正确数字 [0-3]'
main_xiaoyahelper
;;
esac
}
function install_xiaoya_alist_tvbox() {
local DEFAULT_CONFIG_DIR
while true; do
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_tvbox_config_dir.txt ]; then
OLD_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_tvbox_config_dir.txt)
INFO "已读取小雅Alist-TVBox配置文件路径:${OLD_CONFIG_DIR} (默认不更改回车继续,如果需要更改请输入新路径)"
read -erp "CONFIG_DIR:" CONFIG_DIR
[[ -z "${CONFIG_DIR}" ]] && CONFIG_DIR=${OLD_CONFIG_DIR}
else
DEFAULT_CONFIG_DIR="$(get_path "xiaoya_alist_config_dir")"
INFO "请输入配置文件目录(默认 ${DEFAULT_CONFIG_DIR} )"
read -erp "CONFIG_DIR:" CONFIG_DIR
[[ -z "${CONFIG_DIR}" ]] && CONFIG_DIR="${DEFAULT_CONFIG_DIR}"
touch ${DDSREM_CONFIG_DIR}/xiaoya_alist_tvbox_config_dir.txt
fi
if check_path "${CONFIG_DIR}"; then
echo "${CONFIG_DIR}" > "${DDSREM_CONFIG_DIR}/xiaoya_alist_tvbox_config_dir.txt"
INFO "目录合法性检测通过!"
break
else
ERROR "非合法目录,请重新输入!"
fi
done
while true; do
INFO "请输入Alist端口(默认 5344 )"
read -erp "ALIST_PORT:" ALIST_PORT
[[ -z "${ALIST_PORT}" ]] && ALIST_PORT="5344"
if check_port "${ALIST_PORT}"; then
break
else
ERROR "${ALIST_PORT} 此端口被占用,请输入其他端口!"
fi
done
while true; do
INFO "请输入后台管理端口(默认 4567 )"
read -erp "HT_PORT:" HT_PORT
[[ -z "${HT_PORT}" ]] && HT_PORT="4567"
if check_port "${HT_PORT}"; then
break
else
ERROR "${HT_PORT} 此端口被占用,请输入其他端口!"
fi
done
INFO "请输入内存限制(默认 -Xmx512M )"
read -erp "MEM_OPT:" MEM_OPT
[[ -z "${MEM_OPT}" ]] && MEM_OPT="-Xmx512M"
INFO "您的CPU架构:${CPU_ARCH}"
if [ "${DOCKER_ARCH}" == "linux/amd64" ]; then
while true; do
INFO "是否使用内存优化版镜像 [Y/n](默认 n 不使用)"
read -erp "Native:" choose_native
[[ -z "${choose_native}" ]] && choose_native="n"
if [[ ${choose_native} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${choose_native} == [Yy] ]]; then
__choose_native="native"
else
__choose_native="latest"
fi
elif [ "${DOCKER_ARCH}" == "linux/arm64/v8" ]; then
__choose_native="latest"
else
ERROR "Xiaoya-TVBox 目前只支持 amd64 和 arm64 架构,你的架构是:$CPU_ARCH"
exit 1
fi
container_run_extra_parameters=$(cat ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt)
if [ "${container_run_extra_parameters}" == "true" ]; then
local RETURN_DATA
RETURN_DATA="$(data_crep "r" "install_xiaoya_alist_tvbox")"
if [ "${RETURN_DATA}" == "None" ]; then
INFO "请输入其他参数(默认 无 )"
read -erp "Extra parameters:" extra_parameters
else
INFO "已读取您上次设置的参数:${RETURN_DATA} (默认不更改回车继续,如果需要更改请输入新参数)"
read -erp "Extra parameters:" extra_parameters
[[ -z "${extra_parameters}" ]] && extra_parameters=${RETURN_DATA}
fi
extra_parameters=$(data_crep "w" "install_xiaoya_alist_tvbox")
fi
if ls ${CONFIG_DIR}/*.txt 1> /dev/null 2>&1; then
INFO "备份小雅配置数据中..."
mkdir -p ${CONFIG_DIR}/xiaoya_backup
cp -rf ${CONFIG_DIR}/*.txt ${CONFIG_DIR}/xiaoya_backup
INFO "完成备份小雅配置数据!"
INFO "备份数据路径:${CONFIG_DIR}/xiaoya_backup"
fi
docker_pull "haroldli/xiaoya-tvbox:${__choose_native}"
if [ -n "${extra_parameters}" ]; then
docker run -itd \
-p "${HT_PORT}":4567 \
-p "${ALIST_PORT}":80 \
-e ALIST_PORT="${ALIST_PORT}" \
-e MEM_OPT="${MEM_OPT}" \
-e TZ=Asia/Shanghai \
-v "${CONFIG_DIR}:/data" \
${extra_parameters} \
--restart=always \
--name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)" \
haroldli/xiaoya-tvbox:${__choose_native}
else
docker run -itd \
-p "${HT_PORT}":4567 \
-p "${ALIST_PORT}":80 \
-e ALIST_PORT="${ALIST_PORT}" \
-e MEM_OPT="${MEM_OPT}" \
-e TZ=Asia/Shanghai \
-v "${CONFIG_DIR}:/data" \
--restart=always \
--name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)" \
haroldli/xiaoya-tvbox:${__choose_native}
fi
INFO "安装完成!"
INFO "浏览器访问 小雅Alist-TVBox 服务:${Sky_Blue}http://ip:${HT_PORT}${Font}, 默认用户密码: ${Sky_Blue}admin/admin${Font}"
}
function update_xiaoya_alist_tvbox() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始更新小雅Alist-TVBox${Blue} $i ${Font}\r"
sleep 1
done
VOLUMES="$(docker inspect -f '{{range .Mounts}}{{if eq .Type "volume"}}{{println .}}{{end}}{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)" | cut -d' ' -f2 | awk 'NF' | tr '\n' ' ')"
# shellcheck disable=SC2034
container_update_extra_command="sedsh '/\/opt\/atv\/data/d; \/opt\/alist\/data/d' "/tmp/container_update_$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)""
container_update "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)"
docker volume rm ${VOLUMES}
}
function uninstall_xiaoya_alist_tvbox() {
local CLEAN_CONFIG IMAGE_NAME VOLUMES
while true; do
INFO "是否${Red}删除配置文件${Font} [Y/n](默认 Y 删除)"
read -erp "Clean config:" CLEAN_CONFIG
[[ -z "${CLEAN_CONFIG}" ]] && CLEAN_CONFIG="y"
if [[ ${CLEAN_CONFIG} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载小雅Alist-TVBox${Blue} $i ${Font}\r"
sleep 1
done
IMAGE_NAME="$(docker inspect --format='{{.Config.Image}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)")"
VOLUMES="$(docker inspect -f '{{range .Mounts}}{{if eq .Type "volume"}}{{println .}}{{end}}{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)" | cut -d' ' -f2 | awk 'NF' | tr '\n' ' ')"
docker stop "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)"
docker rm "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)"
docker rmi "${IMAGE_NAME}"
docker volume rm ${VOLUMES}
if [[ ${CLEAN_CONFIG} == [Yy] ]]; then
INFO "清理配置文件..."
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_tvbox_config_dir.txt ]; then
OLD_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_tvbox_config_dir.txt)
for dir in "${OLD_CONFIG_DIR}"/*/; do
rm -rf "$dir"
done
rm -rf ${OLD_CONFIG_DIR}/*.db
fi
fi
INFO "小雅Alist-TVBox卸载成功!"
}
function main_xiaoya_alist_tvbox() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}小雅Alist-TVBox${Font}\n"
echo -e "1、安装"
echo -e "2、更新"
echo -e "3、卸载"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-3]:" num
case "$num" in
1)
clear
install_xiaoya_alist_tvbox
return_menu "main_xiaoya_alist_tvbox"
;;
2)
clear
update_xiaoya_alist_tvbox
return_menu "main_xiaoya_alist_tvbox"
;;
3)
clear
uninstall_xiaoya_alist_tvbox
return_menu "main_xiaoya_alist_tvbox"
;;
0)
clear
main_other_tools
;;
*)
clear
ERROR '请输入正确数字 [0-3]'
main_xiaoya_alist_tvbox
;;
esac
}
function install_xiaoya_115_cleaner() {
extra_parameters=
local config_dir
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/data$" | awk -F: '{print $1}')"
fi
if [ -z "${config_dir}" ]; then
get_config_dir
config_dir=${CONFIG_DIR}
fi
settings_115_cookie "${config_dir}"
if [ ! -f "${config_dir}/115_key.txt" ]; then
touch ${config_dir}/115_key.txt
INFO "输入你的 115 回收站密码"
INFO "注意:此选项为必填项,如果您关闭了回收站密码请手动开启并输入!"
read -erp "Key:" password_key
echo -e "${password_key}" > ${config_dir}/115_key.txt
fi
while true; do
INFO "请选择 115 Cleaner 清理模式(默认 1)"
INFO "1:标准模式,清空 /最近接收 下面的文件并同时清理回收站的对应文件"
INFO "2:只清空 115云盘 回收站文件,不会清理其他地方的文件"
INFO "3:清空 /最近接收 下面的文件并同时清空回收站"
INFO "4:只清空 /最近接收 下面的文件,不清理回收站"
read -erp "CHOOSE_RUN_MODE:" CHOOSE_RUN_MODE
[[ -z "${CHOOSE_RUN_MODE}" ]] && CHOOSE_RUN_MODE="1"
if [ -f "${config_dir}/115_cleaner_all_recyclebin.txt" ]; then
rm -rf "${config_dir}/115_cleaner_all_recyclebin.txt"
fi
if [ -f "${config_dir}/115_cleaner_only_recyclebin.txt" ]; then
rm -rf "${config_dir}/115_cleaner_only_recyclebin.txt"
fi
if [ -f "${config_dir}/115_cleaner_only_receive.txt" ]; then
rm -rf "${config_dir}/115_cleaner_only_receive.txt"
fi
case ${CHOOSE_RUN_MODE} in
1)
break
;;
2)
touch "${config_dir}/115_cleaner_only_recyclebin.txt"
break
;;
3)
touch "${config_dir}/115_cleaner_all_recyclebin.txt"
break
;;
4)
touch "${config_dir}/115_cleaner_only_receive.txt"
break
;;
*)
ERROR "输入无效,请重新选择"
;;
esac
done
if [ -f "${config_dir}/ali2115.txt" ]; then
while true; do
INFO "是否将 ali2115 转存文件交由 115 Cleaner 清理 [Y/n](默认 y)"
read -erp "ali2115:" choose_ali2115
[[ -z "${choose_ali2115}" ]] && choose_ali2115="y"
if [[ ${choose_ali2115} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
fi
if [[ ${choose_ali2115} == [Yy] ]]; then
touch "${config_dir}/115_cleaner_auto_set_ali2115.txt"
fi
container_run_extra_parameters=$(cat ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt)
if [ "${container_run_extra_parameters}" == "true" ]; then
local RETURN_DATA
RETURN_DATA="$(data_crep "r" "install_xiaoya_115_cleaner")"
if [ "${RETURN_DATA}" == "None" ]; then
INFO "请输入其他参数(默认 无 )"
read -erp "Extra parameters:" extra_parameters
else
INFO "已读取您上次设置的参数:${RETURN_DATA} (默认不更改回车继续,如果需要更改请输入新参数)"
read -erp "Extra parameters:" extra_parameters
[[ -z "${extra_parameters}" ]] && extra_parameters=${RETURN_DATA}
fi
extra_parameters=$(data_crep "w" "install_xiaoya_115_cleaner")
fi
docker_pull "ddsderek/xiaoya-115cleaner:latest"
docker run -d \
--name=xiaoya-115cleaner \
-v "${config_dir}:/data" \
--net=host \
-e TZ=Asia/Shanghai \
${extra_parameters} \
--restart=always \
ddsderek/xiaoya-115cleaner:latest
INFO "安装完成!"
}
function update_xiaoya_115_cleaner() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始更新115清理助手${Blue} $i ${Font}\r"
sleep 1
done
container_update xiaoya-115cleaner
}
function uninstall_xiaoya_115_cleaner() {
while true; do
INFO "是否${Red}删除配置文件${Font} [Y/n](默认 Y 删除)"
read -erp "Clean config:" CLEAN_CONFIG
[[ -z "${CLEAN_CONFIG}" ]] && CLEAN_CONFIG="y"
if [[ ${CLEAN_CONFIG} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载115清理助手${Blue} $i ${Font}\r"
sleep 1
done
docker stop xiaoya-115cleaner
docker rm xiaoya-115cleaner
docker rmi ddsderek/xiaoya-115cleaner:latest
if [[ ${CLEAN_CONFIG} == [Yy] ]]; then
INFO "清理配置文件..."
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt ]; then
OLD_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
for file in "${OLD_CONFIG_DIR}/115_cleaner_only_recyclebin.txt" "${OLD_CONFIG_DIR}/115_cleaner_all_recyclebin.txt" "${OLD_CONFIG_DIR}/115_key.txt"; do
if [ -f "$file" ]; then
rm -f "$file"
fi
done
fi
fi
INFO "115清理助手卸载成功!"
}
function main_xiaoya_115_cleaner() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}115 清理助手${Font}\n"
echo -e "1、安装"
echo -e "2、更新"
echo -e "3、卸载"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-3]:" num
case "$num" in
1)
clear
install_xiaoya_115_cleaner
return_menu "main_xiaoya_115_cleaner"
;;
2)
clear
update_xiaoya_115_cleaner
return_menu "main_xiaoya_115_cleaner"
;;
3)
clear
uninstall_xiaoya_115_cleaner
return_menu "main_xiaoya_115_cleaner"
;;
0)
clear
main_return
;;
*)
clear
ERROR '请输入正确数字 [0-3]'
main_xiaoya_115_cleaner
;;
esac
}
function install_xiaoya_proxy() {
local config_dir
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/data$" | awk -F: '{print $1}')"
else
ERROR "请先安装小雅容器后再使用 Xiaoya Proxy!"
exit 1
fi
if [ -z "${config_dir}" ]; then
get_config_dir
config_dir=${CONFIG_DIR}
fi
INFO "小雅配置文件目录:${config_dir}"
container_run_extra_parameters=$(cat ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt)
if [ "${container_run_extra_parameters}" == "true" ]; then
local RETURN_DATA
RETURN_DATA="$(data_crep "r" "install_xiaoya_proxy")"
if [ "${RETURN_DATA}" == "None" ]; then
INFO "请输入其他参数(默认 无 )"
read -erp "Extra parameters:" extra_parameters
else
INFO "已读取您上次设置的参数:${RETURN_DATA} (默认不更改回车继续,如果需要更改请输入新参数)"
read -erp "Extra parameters:" extra_parameters
[[ -z "${extra_parameters}" ]] && extra_parameters=${RETURN_DATA}
fi
extra_parameters=$(data_crep "w" "install_xiaoya_proxy")
fi
if ! check_port "9988"; then
ERROR "9988 端口被占用,请关闭占用此端口的程序!"
exit 1
fi
docker_pull "ddsderek/xiaoya-proxy:latest"
# shellcheck disable=SC2046
docker run -d \
--name=xiaoya-proxy \
--restart=always \
$(get_default_network "xiaoya-proxy") \
${extra_parameters} \
-e TZ=Asia/Shanghai \
ddsderek/xiaoya-proxy:latest
if [[ "${OSNAME}" = "macos" ]]; then
local_ip=$(ifconfig "$(route -n get default | grep interface | awk -F ':' '{print$2}' | awk '{$1=$1};1')" | grep 'inet ' | awk '{print$2}')
else
local_ip=$(ip address | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1 | cut -f1 -d"/")
fi
if [ -z "${local_ip}" ]; then
WARN "请手动配置 ${config_dir}/xiaoya_proxy.txt 文件,内容为 http://小雅服务器IP:9988"
else
INFO "本机IP:${local_ip}"
echo "http://${local_ip}:9988" > ${config_dir}/xiaoya_proxy.txt
INFO "xiaoya_proxy.txt 配置完成!"
fi
docker restart "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
wait_xiaoya_start
INFO "安装完成!"
}
function update_xiaoya_proxy() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始更新 Xiaoya Proxy${Blue} $i ${Font}\r"
sleep 1
done
container_update xiaoya-proxy
}
function uninstall_xiaoya_proxy() {
while true; do
INFO "是否${Red}删除配置文件${Font} [Y/n](默认 Y 删除)"
read -erp "Clean config:" CLEAN_CONFIG
[[ -z "${CLEAN_CONFIG}" ]] && CLEAN_CONFIG="y"
if [[ ${CLEAN_CONFIG} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载 Xiaoya Proxy${Blue} $i ${Font}\r"
sleep 1
done
docker stop xiaoya-proxy
docker rm xiaoya-proxy
docker rmi ddsderek/xiaoya-proxy:latest
if [[ ${CLEAN_CONFIG} == [Yy] ]]; then
INFO "清理配置文件..."
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt ]; then
OLD_CONFIG_DIR=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)
if [ -f "${OLD_CONFIG_DIR}/xiaoya_proxy.txt" ]; then
rm -f "${OLD_CONFIG_DIR}/xiaoya_proxy.txt"
fi
fi
fi
INFO "Xiaoya Proxy 卸载成功!"
}
function main_xiaoya_proxy() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}Xiaoya Proxy${Font}\n"
echo -e "1、安装"
echo -e "2、更新"
echo -e "3、卸载"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-3]:" num
case "$num" in
1)
clear
install_xiaoya_proxy
return_menu "main_xiaoya_proxy"
;;
2)
clear
update_xiaoya_proxy
return_menu "main_xiaoya_proxy"
;;
3)
clear
uninstall_xiaoya_proxy
return_menu "main_xiaoya_proxy"
;;
0)
clear
main_other_tools
;;
*)
clear
ERROR '请输入正确数字 [0-3]'
main_xiaoya_proxy
;;
esac
}
function install_xiaoya_aliyuntvtoken_connector() {
CONFIG_DIR=$1
if [ ! -f "${CONFIG_DIR}/open_tv_token_url.txt" ]; then
INFO "当前未配置 阿里云盘 TV Token,开始进入 TV Token 配置流程..."
qrocde_common "阿里云盘 TV Token" "${CONFIG_DIR}" "/aliyuntvtoken/alitoken2.py"
else
INFO "阿里云盘 TV Token 当前已配置!"
fi
if ! check_port "34278"; then
ERROR "34278 端口被占用,请关闭占用此端口的程序!"
exit 1
fi
docker_pull "ddsderek/xiaoya-glue:aliyuntvtoken_connector"
# shellcheck disable=SC2046
docker run -d \
$(get_default_network "xiaoya-aliyuntvtoken_connector") \
--name=xiaoya-aliyuntvtoken_connector \
--restart=always \
ddsderek/xiaoya-glue:aliyuntvtoken_connector
sleep 2
get_docker0_url
local xiaoya_name aliyuntvtoken_connector_addr local_ip xiaoya_running
xiaoya_name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
xiaoya_running=false
if docker container inspect "${xiaoya_name}" > /dev/null 2>&1; then
case "$(docker inspect --format='{{.State.Status}}' "${xiaoya_name}")" in
"running")
xiaoya_running=true
;;
esac
fi
function set_local_ip() {
if [[ "${OSNAME}" = "macos" ]]; then
local_ip=$(ifconfig "$(route -n get default | grep interface | awk -F ':' '{print$2}' | awk '{$1=$1};1')" | grep 'inet ' | awk '{print$2}')
else
local_ip=$(ip address | grep inet | grep -v 172.17 | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | sed 's/addr://' | head -n1 | cut -f1 -d"/")
fi
if [ -z "${local_ip}" ]; then
WARN "请手动配置 ${CONFIG_DIR}/open_tv_token_url.txt 文件,内容为 http://小雅服务器IP:34278/oauth/alipan/token"
else
INFO "本机IP:${local_ip}"
aliyuntvtoken_connector_addr="http://${local_ip}:34278/oauth/alipan/token"
fi
}
if [ "${xiaoya_running}" == "true" ]; then
if docker exec -it "${xiaoya_name}" curl -siL -m 10 http://127.0.0.1:34278/oauth/alipan/token | grep 405; then
aliyuntvtoken_connector_addr="http://127.0.0.1:34278/oauth/alipan/token"
elif docker exec -it "${xiaoya_name}" curl -siL -m 10 http://${docker0}:34278/oauth/alipan/token | grep 405; then
aliyuntvtoken_connector_addr="http://${docker0}:34278/oauth/alipan/token"
else
set_local_ip
fi
else
set_local_ip
fi
if [ -n "${aliyuntvtoken_connector_addr}" ]; then
INFO "本地阿里云盘 TV Token 鉴权接口地址:${aliyuntvtoken_connector_addr}"
echo "${aliyuntvtoken_connector_addr}" > "${CONFIG_DIR}/open_tv_token_url.txt"
fi
if docker container inspect "${xiaoya_name}" > /dev/null 2>&1; then
docker restart "${xiaoya_name}"
sleep 5
wait_xiaoya_start
fi
INFO "安装完成!"
}
function update_xiaoya_aliyuntvtoken_connector() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始更新 xiaoya-aliyuntvtoken_connector${Blue} $i ${Font}\r"
sleep 1
done
container_update xiaoya-aliyuntvtoken_connector
}
function uninstall_xiaoya_aliyuntvtoken_connector() {
while true; do
INFO "是否停止使用 阿里云盘 TV Token 配置 [Y/n](默认 n)"
read -erp "Use_TV_Token:" USE_TV_TOKEN
[[ -z "${USE_TV_TOKEN}" ]] && USE_TV_TOKEN="n"
if [[ ${USE_TV_TOKEN} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载 xiaoya-aliyuntvtoken_connector${Blue} $i ${Font}\r"
sleep 1
done
docker stop xiaoya-aliyuntvtoken_connector
docker rm xiaoya-aliyuntvtoken_connector
docker rmi ddsderek/xiaoya-glue:aliyuntvtoken_connector
local xiaoya_name config_dir
xiaoya_name="$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
if docker container inspect "${xiaoya_name}" > /dev/null 2>&1; then
config_dir="$(docker inspect -f '{{ range .Mounts }}{{ if eq .Destination "/data" }}{{ .Source }}{{ end }}{{ end }}' "${xiaoya_name}")"
elif [ -f "${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt" ]; then
config_dir="$(cat ${DDSREM_CONFIG_DIR}/xiaoya_alist_config_dir.txt)"
else
get_config_dir
config_dir="${CONFIG_DIR}"
fi
INFO "小雅容器配置目录:${config_dir}"
if [[ ${USE_TV_TOKEN} == [Yy] ]]; then
rm -f "${config_dir}/open_tv_token_url.txt"
rm -f "${config_dir}/myopentoken.txt"
while true; do
INFO "是否配置阿里云盘 Open Token(myopentoken文件) [Y/n](默认 y)"
read -erp "Set_Open_Token:" SET_OPEN_TOKEN
[[ -z "${SET_OPEN_TOKEN}" ]] && SET_OPEN_TOKEN="y"
if [[ ${SET_OPEN_TOKEN} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${SET_OPEN_TOKEN} == [Yy] ]]; then
settings_aliyunpan_opentoken "${config_dir}" force
fi
else
INFO "切换使用公共鉴权接口:https://www.voicehub.top/api/v1/oauth/alipan/token"
echo "https://www.voicehub.top/api/v1/oauth/alipan/token" > "${config_dir}/open_tv_token_url.txt"
fi
if docker container inspect "${xiaoya_name}" > /dev/null 2>&1; then
docker restart "${xiaoya_name}"
sleep 5
wait_xiaoya_start
fi
INFO "xiaoya-aliyuntvtoken_connector 卸载成功!"
}
function main_xiaoya_aliyuntvtoken_connector() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}阿里云盘 TV Token 令牌刷新接口(xiaoya-aliyuntvtoken_connector)${Font}\n"
echo -e "1、安装"
echo -e "2、更新"
echo -e "3、卸载"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-3]:" num
case "$num" in
1)
clear
get_config_dir
install_xiaoya_aliyuntvtoken_connector "${CONFIG_DIR}"
return_menu "main_xiaoya_aliyuntvtoken_connector"
;;
2)
clear
update_xiaoya_aliyuntvtoken_connector
return_menu "main_xiaoya_aliyuntvtoken_connector"
;;
3)
clear
uninstall_xiaoya_aliyuntvtoken_connector
return_menu "main_xiaoya_aliyuntvtoken_connector"
;;
0)
clear
main_other_tools
;;
*)
clear
ERROR '请输入正确数字 [0-3]'
main_xiaoya_aliyuntvtoken_connector
;;
esac
}
function install_lrcapi() {
INFO "开始安装 LrcAPI"
if ! check_port "28883"; then
ERROR "28883 端口被占用,请关闭占用此端口的程序!"
exit 1
fi
docker_pull "hisatri/lrcapi:latest"
docker run -d \
-p 28883:28883 \
--name=lrcapi \
-e "API_AUTH=1234" \
hisatri/lrcapi:latest
INFO "安装完成!"
INFO "LrcAPI API地址:${Sky_Blue}http://ip:28883${Font}"
INFO "LrcAPI API密码:${Sky_Blue}1234${Font}"
}
function update_lrcapi() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始更新 LrcAPI${Blue} $i ${Font}\r"
sleep 1
done
container_update lrcapi
}
function uninstall_lrcapi() {
for i in $(seq -w 3 -1 0); do
echo -en "即将开始卸载 LrcAPI${Blue} $i ${Font}\r"
sleep 1
done
docker stop lrcapi
docker rm lrcapi
docker rmi hisatri/lrcapi:latest
INFO "LrcAPI 卸载成功!"
}
function main_lrcapi() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}LrcAPI${Font}\n"
echo -e "1、安装"
echo -e "2、更新"
echo -e "3、卸载"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-3]:" num
case "$num" in
1)
clear
install_lrcapi
return_menu "main_lrcapi"
;;
2)
clear
update_lrcapi
return_menu "main_lrcapi"
;;
3)
clear
uninstall_lrcapi
return_menu "main_lrcapi"
;;
0)
clear
main_other_tools
;;
*)
clear
ERROR '请输入正确数字 [0-3]'
main_lrcapi
;;
esac
}
function init_container_name() {
if [ ! -d ${DDSREM_CONFIG_DIR}/container_name ]; then
mkdir -p ${DDSREM_CONFIG_DIR}/container_name
fi
if [ -f ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt ]; then
xiaoya_alist_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)
else
echo 'xiaoya' > ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt
xiaoya_alist_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)
fi
if [ -f ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt ]; then
xiaoya_emby_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)
else
echo 'emby' > ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt
xiaoya_emby_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_emby_name.txt)
fi
if [ -f ${DDSREM_CONFIG_DIR}/container_name/xiaoya_jellyfin_name.txt ]; then
xiaoya_jellyfin_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_jellyfin_name.txt)
else
echo 'jellyfin' > ${DDSREM_CONFIG_DIR}/container_name/xiaoya_jellyfin_name.txt
xiaoya_jellyfin_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_jellyfin_name.txt)
fi
if [ -f ${DDSREM_CONFIG_DIR}/container_name/xiaoya_resilio_name.txt ]; then
xiaoya_resilio_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_resilio_name.txt)
else
echo 'resilio' > ${DDSREM_CONFIG_DIR}/container_name/xiaoya_resilio_name.txt
xiaoya_resilio_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_resilio_name.txt)
fi
if [ -f ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt ]; then
xiaoya_tvbox_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)
else
echo 'xiaoya-tvbox' > ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt
xiaoya_tvbox_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_tvbox_name.txt)
fi
if [ -f ${DDSREM_CONFIG_DIR}/container_name/xiaoya_onelist_name.txt ]; then
xiaoya_onelist_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_onelist_name.txt)
else
echo 'onelist' > ${DDSREM_CONFIG_DIR}/container_name/xiaoya_onelist_name.txt
xiaoya_onelist_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_onelist_name.txt)
fi
if [ -f ${DDSREM_CONFIG_DIR}/container_name/portainer_name.txt ]; then
portainer_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/portainer_name.txt)
else
echo 'portainer' > ${DDSREM_CONFIG_DIR}/container_name/portainer_name.txt
portainer_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/portainer_name.txt)
fi
if [ -f ${DDSREM_CONFIG_DIR}/container_name/auto_symlink_name.txt ]; then
auto_symlink_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/auto_symlink_name.txt)
else
echo 'auto_symlink' > ${DDSREM_CONFIG_DIR}/container_name/auto_symlink_name.txt
auto_symlink_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/auto_symlink_name.txt)
fi
}
function change_container_name() {
INFO "请输入新的容器名称"
read -erp "Container name:" container_name
[[ -z "${container_name}" ]] && container_name=$(cat ${DDSREM_CONFIG_DIR}/container_name/"${1}".txt)
echo "${container_name}" > ${DDSREM_CONFIG_DIR}/container_name/"${1}".txt
clear
container_name_settings
}
function container_name_settings() {
init_container_name
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}容器名称设置${Font}\n"
echo -e "1、更改 小雅 容器名 (当前:${Green}${xiaoya_alist_name}${Font})"
echo -e "2、更改 小雅Emby 容器名 (当前:${Green}${xiaoya_emby_name}${Font})"
echo -e "3、更改 Resilio 容器名 (当前:${Green}${xiaoya_resilio_name}${Font})"
echo -e "4、更改 小雅Alist-TVBox 容器名 (当前:${Green}${xiaoya_tvbox_name}${Font})"
echo -e "5、更改 Onelist 容器名 (当前:${Green}${xiaoya_onelist_name}${Font})"
echo -e "6、更改 Portainer 容器名 (当前:${Green}${portainer_name}${Font})"
echo -e "7、更改 Auto_Symlink 容器名 (当前:${Green}${auto_symlink_name}${Font})"
echo -e "8、更改 Jellyfin 容器名 (当前:${Green}${xiaoya_jellyfin_name}${Font})"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-8]:" num
case "$num" in
1)
change_container_name "xiaoya_alist_name"
;;
2)
change_container_name "xiaoya_emby_name"
;;
3)
change_container_name "xiaoya_resilio_name"
;;
4)
change_container_name "xiaoya_tvbox_name"
;;
5)
change_container_name "xiaoya_onelist_name"
;;
6)
change_container_name "portainer_name"
;;
7)
change_container_name "auto_symlink_name"
;;
8)
change_container_name "xiaoya_jellyfin_name"
;;
0)
clear
main_advanced_configuration
;;
*)
clear
ERROR '请输入正确数字 [0-8]'
container_name_settings
;;
esac
}
function reset_script_configuration() {
INFO "是否${Red}删除所有脚本配置文件${Font} [Y/n](默认 Y 删除)"
read -erp "Clean config:" CLEAN_CONFIG
[[ -z "${CLEAN_CONFIG}" ]] && CLEAN_CONFIG="y"
if [[ ${CLEAN_CONFIG} == [Yy] ]]; then
for i in $(seq -w 3 -1 0); do
echo -en "即将开始清理配置文件${Blue} $i ${Font}\r"
sleep 1
done
FILES_TO_REMOVE=(
"xiaoya_alist_tvbox_config_dir.txt"
"xiaoya_alist_media_dir.txt"
"xiaoya_alist_config_dir.txt"
"resilio_config_dir.txt"
"portainer_config_dir.txt"
"onelist_config_dir.txt"
"container_run_extra_parameters.txt"
"auto_symlink_config_dir.txt"
"data_downloader.txt"
"disk_capacity_detection.txt"
"xiaoya_connectivity_detection.txt"
"image_mirror.txt"
"image_mirror_user.txt"
"default_network.txt"
)
for file in "${FILES_TO_REMOVE[@]}"; do
rm -f ${DDSREM_CONFIG_DIR}/$file
done
rm -rf \
${DDSREM_CONFIG_DIR}/container_name \
${DDSREM_CONFIG_DIR}/data_crep
INFO "清理完成!"
for i in $(seq -w 3 -1 0); do
echo -en "即将返回主界面并重新生成默认配置${Blue} $i ${Font}\r"
sleep 1
done
first_init
clear
main_return
else
return 0
fi
}
function main_advanced_configuration() {
__container_run_extra_parameters=$(cat "${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt")
if [ "${__container_run_extra_parameters}" == "true" ]; then
_container_run_extra_parameters="${Green}开启${Font}"
elif [ "${__container_run_extra_parameters}" == "false" ]; then
_container_run_extra_parameters="${Red}关闭${Font}"
else
_container_run_extra_parameters="${Red}错误${Font}"
fi
__use_host_7z_command=$(cat "${DDSREM_CONFIG_DIR}/use_host_7z_command.txt")
if [ "${__use_host_7z_command}" == "true" ]; then
_use_host_7z_command="${Green}开启${Font}"
elif [ "${__use_host_7z_command}" == "false" ]; then
_use_host_7z_command="${Red}关闭${Font}"
else
_use_host_7z_command="${Red}错误${Font}"
fi
__disk_capacity_detection=$(cat ${DDSREM_CONFIG_DIR}/disk_capacity_detection.txt)
if [ "${__disk_capacity_detection}" == "true" ]; then
_disk_capacity_detection="${Green}开启${Font}"
elif [ "${__disk_capacity_detection}" == "false" ]; then
_disk_capacity_detection="${Red}关闭${Font}"
else
_disk_capacity_detection="${Red}错误${Font}"
fi
__xiaoya_connectivity_detection=$(cat ${DDSREM_CONFIG_DIR}/xiaoya_connectivity_detection.txt)
if [ "${__xiaoya_connectivity_detection}" == "true" ]; then
_xiaoya_connectivity_detection="${Green}开启${Font}"
elif [ "${__xiaoya_connectivity_detection}" == "false" ]; then
_xiaoya_connectivity_detection="${Red}关闭${Font}"
else
_xiaoya_connectivity_detection="${Red}错误${Font}"
fi
_default_network=$(cat "${DDSREM_CONFIG_DIR}/default_network.txt")
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}高级配置${Font}\n"
echo -e "1、容器名称设置"
echo -e "2、开启/关闭 容器运行额外参数添加 当前状态:${_container_run_extra_parameters}"
echo -e "3、重置脚本配置"
echo -e "4、开启/关闭 磁盘容量检测 当前状态:${_disk_capacity_detection}"
echo -e "5、开启/关闭 小雅连通性检测 当前状态:${_xiaoya_connectivity_detection}"
echo -e "6、Docker镜像源选择"
echo -e "7、非可选网络模式容器默认网络模式 当前状态:${Blue}${_default_network}${Font}"
echo -e "8、弃用菜单"
echo -e "9、开启/关闭 使用宿主机7z命令解压 当前状态:${_use_host_7z_command}"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-9]:" num
case "$num" in
1)
clear
container_name_settings
;;
2)
if [ "${__container_run_extra_parameters}" == "false" ]; then
echo 'true' > ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt
else
echo 'false' > ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt
fi
clear
main_advanced_configuration
;;
3)
clear
reset_script_configuration
return_menu "main_advanced_configuration"
;;
4)
if [ "${__disk_capacity_detection}" == "true" ]; then
echo 'false' > ${DDSREM_CONFIG_DIR}/disk_capacity_detection.txt
elif [ "${__disk_capacity_detection}" == "false" ]; then
echo 'true' > ${DDSREM_CONFIG_DIR}/disk_capacity_detection.txt
else
echo 'true' > ${DDSREM_CONFIG_DIR}/disk_capacity_detection.txt
fi
clear
main_advanced_configuration
;;
5)
if [ "${__xiaoya_connectivity_detection}" == "true" ]; then
echo 'false' > ${DDSREM_CONFIG_DIR}/xiaoya_connectivity_detection.txt
elif [ "${__xiaoya_connectivity_detection}" == "false" ]; then
echo 'true' > ${DDSREM_CONFIG_DIR}/xiaoya_connectivity_detection.txt
else
echo 'true' > ${DDSREM_CONFIG_DIR}/xiaoya_connectivity_detection.txt
fi
clear
main_advanced_configuration
;;
6)
clear
choose_image_mirror "main_advanced_configuration"
;;
7)
if [ "${_default_network}" == "host" ]; then
echo 'bridge' > ${DDSREM_CONFIG_DIR}/default_network.txt
elif [ "${_default_network}" == "bridge" ]; then
echo 'host' > ${DDSREM_CONFIG_DIR}/default_network.txt
else
echo 'host' > ${DDSREM_CONFIG_DIR}/default_network.txt
fi
clear
main_advanced_configuration
;;
8)
clear
main_deprecation
;;
9)
if [ "${__use_host_7z_command}" == "false" ]; then
echo 'true' > ${DDSREM_CONFIG_DIR}/use_host_7z_command.txt
else
echo 'false' > ${DDSREM_CONFIG_DIR}/use_host_7z_command.txt
fi
clear
main_advanced_configuration
;;
0)
clear
main_return
;;
*)
clear
ERROR '请输入正确数字 [0-9]'
main_advanced_configuration
;;
esac
}
function main_other_tools() {
echo -e "——————————————————————————————————————————————————————————————————————————————————"
echo -e "${Blue}其他工具${Font}\n"
echo -ne "${INFO} 界面加载中...${Font}\r"
echo -e "1、安装/更新/卸载 Portainer 当前状态:$(judgment_container "${portainer_name}")
2、安装/更新/卸载 Auto_Symlink 当前状态:$(judgment_container "${auto_symlink_name}")
3、安装/更新/卸载 Onelist 当前状态:$(judgment_container "${xiaoya_onelist_name}")
4、安装/更新/卸载 Xiaoya Proxy 当前状态:$(judgment_container xiaoya-proxy)
5、安装/更新/卸载 Xiaoya aliyuntvtoken_connector 当前状态:$(judgment_container xiaoya-aliyuntvtoken_connector)
6、安装/更新/卸载 小雅Alist-TVBox(非原版) 当前状态:$(judgment_container "${xiaoya_tvbox_name}")
7、安装/更新/卸载 LrcAPI 当前状态:$(judgment_container lrcapi)"
echo -e "8、查看系统磁盘挂载"
echo -e "9、安装/卸载 CasaOS"
echo -e "0、返回上级"
echo -e "——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-9]:" num
case "$num" in
1)
clear
main_portainer
;;
2)
clear
main_auto_symlink
;;
3)
clear
main_onelist
;;
4)
clear
main_xiaoya_proxy
;;
5)
clear
main_xiaoya_aliyuntvtoken_connector
;;
6)
clear
main_xiaoya_alist_tvbox
;;
7)
clear
main_lrcapi
;;
8)
clear
INFO "系统磁盘挂载情况:"
show_disk_mount
INFO "按任意键返回菜单"
read -rs -n 1 -p ""
clear
main_other_tools
;;
9)
clear
main_casaos
;;
0)
clear
main_return
;;
*)
clear
ERROR '请输入正确数字 [0-9]'
main_other_tools
;;
esac
}
function main_return() {
local out_tips config_dir
cat /tmp/xiaoya_alist
echo -ne "${INFO} 主界面加载中...${Font}\r"
out_tips=""
if ! curl -s -o /dev/null -m 4 -w '%{time_total}' --head --request GET "$(cat "${DDSREM_CONFIG_DIR}/image_mirror.txt")" &> /dev/null; then
if auto_choose_image_mirror; then
out_tips="${Green}提示:已为您自动配置Docker镜像源地址为: $(cat "${DDSREM_CONFIG_DIR}/image_mirror.txt")${Font}\n"
else
out_tips="${Red}警告:当前环境无法访问Docker镜像仓库,请输入66进入Docker镜像源设置更改镜像源${Font}\n"
fi
fi
if docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/data$" | awk -F: '{print $1}')"
if [ -n "${config_dir}" ]; then
if [ -f "${config_dir}/opentoken_url.txt" ]; then
if [[ "$(cat "${config_dir}/opentoken_url.txt")" == *"nn.ci"* ]] || [[ "$(cat "${config_dir}/opentoken_url.txt")" == *"xhofe.top"* ]]; then
out_tips+="${Red}警告:请立即选择菜单1-4更换阿里云盘Token并更新最新版本小雅,否则可能导致隐私信息泄漏${Font}\n"
fi
fi
fi
fi
# shellcheck disable=SC2154
echo -e "${out_tips}1、安装/更新/卸载 小雅Alist & 账号管理 当前状态:$(judgment_container "${xiaoya_alist_name}")
2、安装/更新/卸载 小雅Emby全家桶 当前状态:$(judgment_container "${xiaoya_emby_name}")
3、安装/更新/卸载 小雅助手(xiaoyahelper) 当前状态:$(judgment_container xiaoyakeeper)
4、安装/更新/卸载 115清理助手 当前状态:$(judgment_container xiaoya-115cleaner)
5、其他工具 | Script info: ${DATE_VERSION} OS: ${_os},${OSNAME},${is64bit}
6、高级配置 | Docker version: ${Blue}${DOCKER_VERSION}${Font} ${IP_CITY}
0、退出脚本 | Thanks: ${Sky_Blue}heiheigui,xiaoyaLiu,Harold,AI老G,monlor,Rik${Font}
——————————————————————————————————————————————————————————————————————————————————"
read -erp "请输入数字 [0-6]:" num
case "$num" in
1)
clear
main_xiaoya_alist
;;
2)
clear
main_xiaoya_all_emby
;;
3)
clear
main_xiaoyahelper
;;
4)
clear
main_xiaoya_115_cleaner
;;
5)
clear
main_other_tools
;;
6)
clear
main_advanced_configuration
;;
66)
clear
choose_image_mirror "main_return"
;;
fuckaliyun)
clear
if ! docker container inspect "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" > /dev/null 2>&1; then
ERROR "当前未安装小雅容器,请先安装小雅容器后重试!"
exit 1
fi
INFO "AliyunPan ありがとう、あなたのせいで世界は爆発する"
config_dir="$(docker inspect --format='{{range $v,$conf := .Mounts}}{{$conf.Source}}:{{$conf.Destination}}{{$conf.Type}}~{{end}}' "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)" | tr '~' '\n' | grep bind | sed 's/bind//g' | grep ":/data$" | awk -F: '{print $1}')"
if [ -n "${config_dir}" ]; then
qrocde_common "阿里云盘 TV Token" "${config_dir}" "/aliyuntvtoken/alitoken2.py"
if [ ! -f "${config_dir}/open_tv_token_url.txt" ] || [ ! -f "${config_dir}/myopentoken.txt" ]; then
ERROR "阿里云盘 TV Token 配置失败!"
exit 1
fi
if ! docker container inspect xiaoya-aliyuntvtoken_connector > /dev/null 2>&1; then
while true; do
INFO "是否自建阿里云盘 TV Token 令牌刷新接口 [Y/n](默认 Y)"
read -erp "INSTALL_TVTOKEN:" INSTALL_TVTOKEN
[[ -z "${INSTALL_TVTOKEN}" ]] && INSTALL_TVTOKEN="Y"
if [[ ${INSTALL_TVTOKEN} == [YyNn] ]]; then
break
else
ERROR "非法输入,请输入 [Y/n]"
fi
done
if [[ ${INSTALL_TVTOKEN} == [Yy] ]]; then
install_xiaoya_aliyuntvtoken_connector "${config_dir}"
else
WARN "请手动配置 ${config_dir}/open_tv_token_url.txt 文件,内容为 TV Token 令牌刷新接口地址"
WARN "配置完成请手动重启小雅容器!"
fi
else
INFO "开始更新小雅容器..."
container_update "$(cat ${DDSREM_CONFIG_DIR}/container_name/xiaoya_alist_name.txt)"
fi
else
ERROR "小雅配置文件目录获取失败咯!请检查小雅容器是否已创建!"
exit 1
fi
return_menu "main_return"
;;
0)
clear
exit 0
;;
*)
clear
ERROR '请输入正确数字 [0-6]'
main_return
;;
esac
}
function first_init() {
INFO "获取系统信息中..."
get_os
CPU_ARCH=$(uname -m)
case $CPU_ARCH in
"x86_64" | *"amd64"*)
DOCKER_ARCH="linux/amd64"
;;
"aarch64" | *"arm64"* | *"armv8"* | *"arm/v8"*)
DOCKER_ARCH="linux/arm64/v8"
;;
*)
DOCKER_ARCH="others"
;;
esac
INFO "CPU_ARCH:${CPU_ARCH} DOCKER_ARCH:${DOCKER_ARCH}"
if [ -f /tmp/run_xiaoya_install_user.txt ]; then
INFO "运行脚本的用户:$(head -n 1 /tmp/run_xiaoya_install_user.txt)"
RUN_USER="$(head -n 1 /tmp/run_xiaoya_install_user.txt)"
GLOBAL_PUID="$(id -u "${RUN_USER}")"
GLOBAL_PGID="$(id -g "${RUN_USER}")"
fi
INFO "获取 IP 地址中..."
CITY="$(curl -fsSL -m 10 -s http://ipinfo.io/json | sed -n 's/.*"city": *"\([^"]*\)".*/\1/p')"
if [ -n "${CITY}" ]; then
IP_CITY="IP City: ${Yellow}${CITY}${Font}"
INFO "获取 IP 地址成功!"
fi
INFO "检查 Docker 版本"
DOCKER_VERSION="$(docker -v | sed "s/Docker version //g" | cut -d',' -f1)"
if [ ! -d ${DDSREM_CONFIG_DIR} ]; then
mkdir -p ${DDSREM_CONFIG_DIR}
fi
# Fix https://github.com/xiaoyaDev/xiaoya-alist/commit/a246bc582393b618b564e3beca2b9e1d40800a5d 中media目录保存错误
if [ -f /xiaoya_alist_media_dir.txt ]; then
mv /xiaoya_alist_media_dir.txt ${DDSREM_CONFIG_DIR}
fi
INFO "初始化容器名称中..."
init_container_name
if [ ! -f ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt ]; then
echo 'false' > ${DDSREM_CONFIG_DIR}/container_run_extra_parameters.txt
fi
if [ ! -f "${DDSREM_CONFIG_DIR}/use_host_7z_command.txt" ]; then
echo 'false' > "${DDSREM_CONFIG_DIR}/use_host_7z_command.txt"
fi
if [ ! -f "${DDSREM_CONFIG_DIR}/auto_clean_metadata_mp4_file.txt" ]; then
echo 'false' > "${DDSREM_CONFIG_DIR}/auto_clean_metadata_mp4_file.txt"
fi
if [ ! -d "${DDSREM_CONFIG_DIR}/data_crep" ]; then
mkdir -p "${DDSREM_CONFIG_DIR}/data_crep"
fi
if [ ! -d "${DDSREM_CONFIG_DIR}/cache_data" ]; then
mkdir -p "${DDSREM_CONFIG_DIR}/cache_data"
fi
if [ ! -f ${DDSREM_CONFIG_DIR}/data_downloader.txt ]; then
if [ "$OSNAME" = "ugos" ] || [ "$OSNAME" = "ugos pro" ]; then
echo 'wget' > ${DDSREM_CONFIG_DIR}/data_downloader.txt
else
echo 'wget' > ${DDSREM_CONFIG_DIR}/data_downloader.txt
fi
fi
if [ ! -f ${DDSREM_CONFIG_DIR}/disk_capacity_detection.txt ]; then
echo 'true' > ${DDSREM_CONFIG_DIR}/disk_capacity_detection.txt
fi
if [ ! -f ${DDSREM_CONFIG_DIR}/xiaoya_connectivity_detection.txt ]; then
echo 'true' > ${DDSREM_CONFIG_DIR}/xiaoya_connectivity_detection.txt
fi
if [ ! -f "${DDSREM_CONFIG_DIR}/default_network.txt" ]; then
if [[ "${OSNAME}" = "macos" ]]; then
echo 'bridge' > "${DDSREM_CONFIG_DIR}/default_network.txt"
else
echo 'host' > "${DDSREM_CONFIG_DIR}/default_network.txt"
fi
fi
INFO "设置 Docker 镜像源中..."
if [ ! -f "${DDSREM_CONFIG_DIR}/image_mirror.txt" ]; then
if ! auto_choose_image_mirror; then
echo 'docker.io' > ${DDSREM_CONFIG_DIR}/image_mirror.txt
fi
fi
if [ ! -f "${DDSREM_CONFIG_DIR}/image_mirror_user.txt" ]; then
touch ${DDSREM_CONFIG_DIR}/image_mirror_user.txt
fi
INFO "清理旧配置文件中..."
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_emby_url.txt ]; then
rm -rf ${DDSREM_CONFIG_DIR}/xiaoya_emby_url.txt
fi
if [ -f ${DDSREM_CONFIG_DIR}/xiaoya_emby_api.txt ]; then
rm -rf ${DDSREM_CONFIG_DIR}/xiaoya_emby_api.txt
fi
if [ ! -f "${DDSREM_CONFIG_DIR}/勿删_小雅周边脚本配置目录" ]; then
touch "${DDSREM_CONFIG_DIR}/勿删_小雅周边脚本配置目录"
fi
if [ -f /tmp/xiaoya_alist ]; then
rm -rf /tmp/xiaoya_alist
fi
if ! curl -sL https://ddsrem.com/xiaoya/xiaoya_alist -o /tmp/xiaoya_alist; then
if ! curl -sL https://fastly.jsdelivr.net/gh/xiaoyaDev/xiaoya-alist@latest/xiaoya_alist -o /tmp/xiaoya_alist; then
curl -sL https://raw.githubusercontent.com/xiaoyaDev/xiaoya-alist/master/xiaoya_alist -o /tmp/xiaoya_alist
if ! grep -q 'alias xiaoya' /etc/profile; then
echo -e "alias xiaoya='bash -c \"\$(curl -sLk https://raw.githubusercontent.com/xiaoyaDev/xiaoya-alist/master/xiaoya_alist)\"'" >> /etc/profile
fi
else
if ! grep -q 'alias xiaoya' /etc/profile; then
echo -e "alias xiaoya='bash -c \"\$(curl -sLk https://fastly.jsdelivr.net/gh/xiaoyaDev/xiaoya-alist@latest/xiaoya_alist)\"'" >> /etc/profile
fi
fi
else
if ! grep -q 'alias xiaoya' /etc/profile; then
echo -e "alias xiaoya='bash -c \"\$(curl -sLk https://ddsrem.com/xiaoya_install.sh)\"'" >> /etc/profile
fi
fi
# 兼容仓库迁移
if grep -q 'DDS-Derek/xiaoya-alist' /etc/profile; then
sedsh 's/DDS-Derek\/xiaoya-alist/xiaoyaDev\/xiaoya-alist/g' /etc/profile
fi
INFO "初始化完成!"
sleep 1
}
function root_need() {
if [[ $EUID -ne 0 ]] && [ "$(uname -s)" != "Darwin" ]; then
ERROR '此脚本必须以 root 身份运行!'
exit 1
fi
if [ $EUID == 0 ] && [ "$(uname -s)" == "Darwin" ]; then
ERROR 'MacOS 运行脚本必须使用非 root 身份运行,脚本会自动提权!'
exit 1
fi
}
clear
INFO "初始化中,请稍等...."
root_need
if [ "$(uname -s)" == "Darwin" ]; then
if ! command -v brew; then
WARN "brew 未安装,脚本尝试自动安装..."
if /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"; then
INFO "brew 安装成功!"
else
ERROR "brew 安装失败,请手动安装!"
exit 1
fi
fi
if ! command -v 7z; then
WARN "p7zip 未安装,脚本尝试自动安装..."
if brew install p7zip; then
INFO "p7zip 安装成功!"
else
ERROR "p7zip 安装失败,请手动安装!"
exit 1
fi
fi
if ! command -v docker; then
ERROR "docker 未安装,请手动安装!"
exit 1
fi
if [[ $EUID -ne 0 ]]; then
if [ -f /tmp/xiaoya_install.sh ]; then
rm -rf /tmp/xiaoya_install.sh
fi
if [ -f /tmp/run_xiaoya_install_user.txt ]; then
rm -rf /tmp/run_xiaoya_install_user.txt
fi
if ! curl -sL https://ddsrem.com/xiaoya/all_in_one.sh -o /tmp/xiaoya_install.sh; then
if ! curl -sL https://fastly.jsdelivr.net/gh/xiaoyaDev/xiaoya-alist@latest/all_in_one.sh -o /tmp/xiaoya_install.sh; then
if ! curl -sL https://raw.githubusercontent.com/xiaoyaDev/xiaoya-alist/master/all_in_one.sh -o /tmp/xiaoya_install.sh; then
ERROR "脚本获取失败!"
exit 1
fi
fi
fi
INFO "脚本获取成功!"
sed -i '' '/^root_need$/d' /tmp/xiaoya_install.sh
who | sed -n "2,1p" | awk '{print $1}' > /tmp/run_xiaoya_install_user.txt
# shellcheck disable=SC2068
if ! sudo bash /tmp/xiaoya_install.sh $@; then
exit 1
fi
exit 0
fi
fi
if [ ! -d "/tmp/xiaoya_alist_tmp" ]; then
mkdir -p /tmp/xiaoya_alist_tmp
fi
for file in "base" "image_mirror" "auto_symlink" "jellyfin" "portainer" "onelist" "casaos" "deprecation"; do
if ! curl -sSLf "https://gitee.com/ddsrem/xiaoya-alist-base/raw/master/${file}.sh" -o "/tmp/xiaoya_alist_tmp/${file}.sh"; then
if ! curl -sSLf "https://raw.githubusercontent.com/xiaoyaDev/xiaoya-alist/refs/heads/master/base/${file}.sh" -o "/tmp/xiaoya_alist_tmp/${file}.sh"; then
ERROR "${file} 基础库获取失败!"
ERROR "请检查是否能访问 gitee.com 或 github.com!"
exit 1
fi
fi
source "/tmp/xiaoya_alist_tmp/${file}.sh"
rm -f "/tmp/xiaoya_alist_tmp/${file}.sh"
INFO "${file} 基础库加载成功!"
done
rm -rf /tmp/xiaoya_alist_tmp
first_init
clear
if [ ! "$*" ]; then
main_return
else
"$@"
fi