feat: optional YouTube Music source (cookies volume + wizard step)
Adds a step_youtube wizard prompt (enable + cookies host folder), the @YOUTUBE_VOLUME@ token in templates/compose/backend.yml substituted in compose_gen, a YOUTUBE_ENABLED/cookies env block, ensure_youtube_dir in lifecycle, en/ru strings, and a README step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,9 @@ That's it. The wizard walks you through:
|
||||
domain), or no bundled proxy when you publish ports / run your own
|
||||
8. The first administrator account
|
||||
9. An optional ML service URL
|
||||
10. Metadata enrichment — an optional AcoustID key + contact email
|
||||
11. YouTube Music source — enable search/download, with an optional folder for a
|
||||
yt-dlp `cookies.txt` (mounted into the backend for restricted items)
|
||||
|
||||
Then it generates the config, pulls images, migrates, seeds the admin, starts
|
||||
everything, and waits for the API health check before declaring success.
|
||||
|
||||
@@ -39,6 +39,7 @@ CFG_ADMIN_CREATE="no"; CFG_ADMIN_USER=""; CFG_ADMIN_PASS=""
|
||||
CFG_ML_URL=""
|
||||
CFG_ACOUSTID_KEY=""
|
||||
CFG_MUSICBRAINZ_OWNER_EMAIL=""
|
||||
CFG_YOUTUBE="no"; CFG_YOUTUBE_COOKIES_HOST_PATH="./data/youtube"
|
||||
CFG_JWT_SECRET=""
|
||||
|
||||
# ==========================================================================
|
||||
@@ -195,6 +196,19 @@ step_enrichment() {
|
||||
ui_input "$(t musicbrainz_email_prompt)" "" v_email_opt; CFG_MUSICBRAINZ_OWNER_EMAIL="$UI_VALUE"
|
||||
}
|
||||
|
||||
step_youtube() {
|
||||
ui_title "$(t step_youtube)"
|
||||
ui_dim "$(t youtube_note)"
|
||||
if ui_yesno "$(t youtube_q)" "yes"; then
|
||||
CFG_YOUTUBE="yes"
|
||||
ui_dim "$(t youtube_cookies_note)"
|
||||
ui_input "$(t youtube_cookies_prompt)" "./data/youtube" v_nonempty
|
||||
CFG_YOUTUBE_COOKIES_HOST_PATH="$UI_VALUE"
|
||||
else
|
||||
CFG_YOUTUBE="no"
|
||||
fi
|
||||
}
|
||||
|
||||
access_url() {
|
||||
if [[ "$CFG_WEBUI" == "yes" ]]; then
|
||||
if [[ "$CFG_PROXY" == "yes" ]]; then
|
||||
@@ -222,6 +236,7 @@ step_summary() {
|
||||
printf ' %-12s %s\n' "$(t summary_db):" "$dbl"
|
||||
printf ' %-12s %s\n' "$(t summary_redis):" "$rdl"
|
||||
printf ' %-12s %s\n' "$(t summary_storage):" "$stl"
|
||||
printf ' %-12s %s\n' "$(t summary_youtube):" "$([[ "$CFG_YOUTUBE" == yes ]] && t enabled || t disabled)"
|
||||
printf ' %-12s %s\n' "$(t summary_access):" "$(access_url)"
|
||||
echo
|
||||
ui_yesno "$(t confirm_start)" "yes" || { ui_warn "$(t aborted)"; exit 0; }
|
||||
@@ -232,6 +247,10 @@ step_done() {
|
||||
ui_ok "$(t done_url): $(access_url)"
|
||||
ui_info "$(t done_config): ${ENV_FILE}"
|
||||
[[ "$CFG_ADMIN_CREATE" == "yes" ]] && ui_info "$(t done_admin_login): ${CFG_ADMIN_USER}"
|
||||
if [[ "$CFG_YOUTUBE" == "yes" ]]; then
|
||||
ui_info "$(t done_youtube_title)"
|
||||
ui_dim "$(t done_youtube_cookies "${CFG_YOUTUBE_COOKIES_HOST_PATH}/cookies.txt")"
|
||||
fi
|
||||
ui_dim "$(t done_commands)"
|
||||
}
|
||||
|
||||
@@ -247,6 +266,7 @@ run_wizard() {
|
||||
step_admin
|
||||
step_ml
|
||||
step_enrichment
|
||||
step_youtube
|
||||
|
||||
gen_hex 32; CFG_JWT_SECRET="$SECRET"
|
||||
|
||||
|
||||
+12
@@ -106,6 +106,16 @@ MSG[acoustid_prompt]="AcoustID API key (leave blank to use embedded tags only)"
|
||||
MSG[musicbrainz_note]="MusicBrainz/AcoustID require a contact email in their User-Agent or they may throttle requests."
|
||||
MSG[musicbrainz_email_prompt]="Contact email for MusicBrainz/AcoustID (leave blank to use the project's default)"
|
||||
|
||||
# -- youtube source --------------------------------------------------------
|
||||
MSG[step_youtube]="YouTube Music (search + download)"
|
||||
MSG[youtube_note]="Lets users search YouTube Music and download tracks into the library (via yt-dlp). Search and most downloads work with no setup."
|
||||
MSG[youtube_q]="Enable the YouTube Music source?"
|
||||
MSG[youtube_cookies_note]="Optional: a browser cookies file (Netscape format) lets yt-dlp fetch age/region-restricted items. The folder below is mounted into the backend; drop your cookies.txt in it any time (leave default if unsure)."
|
||||
MSG[youtube_cookies_prompt]="Host folder to mount for the cookies file"
|
||||
MSG[summary_youtube]="YouTube"
|
||||
MSG[done_youtube_title]="YouTube downloads are enabled."
|
||||
MSG[done_youtube_cookies]="For restricted items, place an exported cookies.txt in: %s"
|
||||
|
||||
# -- summary / run ---------------------------------------------------------
|
||||
MSG[summary_title]="Summary (secrets hidden)"
|
||||
MSG[summary_services]="Services"
|
||||
@@ -117,6 +127,8 @@ MSG[summary_access]="Access"
|
||||
MSG[confirm_start]="Generate config and start now?"
|
||||
MSG[embedded]="built-in"
|
||||
MSG[external]="external"
|
||||
MSG[enabled]="enabled"
|
||||
MSG[disabled]="disabled"
|
||||
|
||||
MSG[pull_images]="Pulling images (%s)..."
|
||||
MSG[pull_hint]="If pulls fail with 'unauthorized', run 'docker login git.ollyhearn.ru' first (private registry)."
|
||||
|
||||
+12
@@ -106,6 +106,16 @@ MSG[acoustid_prompt]="API-ключ AcoustID (пусто — только вст
|
||||
MSG[musicbrainz_note]="MusicBrainz/AcoustID требуют контактный email в User-Agent, иначе запросы могут ограничиваться (throttling)."
|
||||
MSG[musicbrainz_email_prompt]="Контактный email для MusicBrainz/AcoustID (пусто — использовать значение по умолчанию)"
|
||||
|
||||
# -- youtube source --------------------------------------------------------
|
||||
MSG[step_youtube]="YouTube Music (поиск + скачивание)"
|
||||
MSG[youtube_note]="Позволяет искать в YouTube Music и скачивать треки в библиотеку (через yt-dlp). Поиск и большинство загрузок работают без настройки."
|
||||
MSG[youtube_q]="Включить источник YouTube Music?"
|
||||
MSG[youtube_cookies_note]="Опционально: файл cookies браузера (формат Netscape) позволяет yt-dlp скачивать контент с возрастными/региональными ограничениями. Папка ниже монтируется в backend; положите cookies.txt в неё в любой момент (если не уверены — оставьте по умолчанию)."
|
||||
MSG[youtube_cookies_prompt]="Папка на хосте для монтирования файла cookies"
|
||||
MSG[summary_youtube]="YouTube"
|
||||
MSG[done_youtube_title]="Скачивание из YouTube включено."
|
||||
MSG[done_youtube_cookies]="Для контента с ограничениями положите экспортированный cookies.txt в: %s"
|
||||
|
||||
# -- summary / run ---------------------------------------------------------
|
||||
MSG[summary_title]="Сводка (секреты скрыты)"
|
||||
MSG[summary_services]="Сервисы"
|
||||
@@ -117,6 +127,8 @@ MSG[summary_access]="Доступ"
|
||||
MSG[confirm_start]="Сгенерировать конфиг и запустить сейчас?"
|
||||
MSG[embedded]="встроенный"
|
||||
MSG[external]="внешний"
|
||||
MSG[enabled]="включено"
|
||||
MSG[disabled]="выключено"
|
||||
|
||||
MSG[pull_images]="Скачивание образов (%s)..."
|
||||
MSG[pull_hint]="Если pull падает с 'unauthorized', выполните 'docker login git.ollyhearn.ru' (приватный регистри)."
|
||||
|
||||
@@ -31,6 +31,13 @@ generate_compose() {
|
||||
webui_ports=" ports:${nl} - \"\${WEBUI_PORT}:80\""
|
||||
fi
|
||||
|
||||
# YouTube cookies volume: mounted into api+worker only when the source is
|
||||
# enabled. The host path comes from .env.deploy (YOUTUBE_COOKIES_HOST_PATH).
|
||||
local youtube_volume=""
|
||||
if [[ "$CFG_YOUTUBE" == "yes" ]]; then
|
||||
youtube_volume=" - \${YOUTUBE_COOKIES_HOST_PATH}:/data/youtube"
|
||||
fi
|
||||
|
||||
# Caddy publish ports: 80/443 with a domain (auto-HTTPS), else plain HTTP.
|
||||
if [[ "$CFG_HTTPS" == "yes" ]]; then
|
||||
caddy_ports=" - \"80:80\"${nl} - \"443:443\""
|
||||
@@ -41,6 +48,7 @@ generate_compose() {
|
||||
# -- assemble ---------------------------------------------------------
|
||||
local backend webui caddy
|
||||
backend="$(_frag backend.yml)"
|
||||
backend="${backend//@YOUTUBE_VOLUME@/$youtube_volume}"
|
||||
backend="${backend//@API_PORTS@/$api_ports}"
|
||||
backend="${backend//@API_DEPENDS@/$api_depends}"
|
||||
backend="${backend//@WORKER_DEPENDS@/$worker_depends}"
|
||||
|
||||
@@ -93,5 +93,24 @@ generate_env() {
|
||||
} >>"$ENV_FILE"
|
||||
fi
|
||||
|
||||
# -- YouTube Music source ---------------------------------------------
|
||||
# COOKIES_HOST_PATH is consumed by the compose volume; COOKIES_PATH is the
|
||||
# in-container path the backend reads (only used when the file is present).
|
||||
if [[ "${CFG_YOUTUBE:-no}" == "yes" ]]; then
|
||||
{
|
||||
echo ""
|
||||
echo "# -- YouTube Music source -----------------------------------------------"
|
||||
echo "YOUTUBE_ENABLED=true"
|
||||
echo "YOUTUBE_COOKIES_HOST_PATH=${CFG_YOUTUBE_COOKIES_HOST_PATH}"
|
||||
echo "YOUTUBE_COOKIES_PATH=/data/youtube/cookies.txt"
|
||||
} >>"$ENV_FILE"
|
||||
else
|
||||
{
|
||||
echo ""
|
||||
echo "# -- YouTube Music source (disabled) ------------------------------------"
|
||||
echo "YOUTUBE_ENABLED=false"
|
||||
} >>"$ENV_FILE"
|
||||
fi
|
||||
|
||||
chmod 600 "$ENV_FILE"
|
||||
}
|
||||
|
||||
+13
-1
@@ -36,6 +36,17 @@ ensure_media_dir() {
|
||||
mkdir -p "$p"
|
||||
}
|
||||
|
||||
ensure_youtube_dir() {
|
||||
# YOUTUBE_COOKIES_HOST_PATH is only present when the YouTube source is
|
||||
# enabled; create the folder so the bind mount has a real host directory
|
||||
# (the user drops cookies.txt into it later).
|
||||
local p
|
||||
p="$(grep -E '^YOUTUBE_COOKIES_HOST_PATH=' "$ENV_FILE" | cut -d= -f2-)"
|
||||
[[ -n "$p" ]] || return 0
|
||||
[[ "$p" = /* ]] || p="${BOOTSTRAP_DIR}/${p#./}"
|
||||
mkdir -p "$p"
|
||||
}
|
||||
|
||||
lifecycle_pull() {
|
||||
ui_info "$(t pull_images "$(grep -E '^MCMA_IMAGE_TAG=' "$ENV_FILE" | cut -d= -f2-)")"
|
||||
ui_dim "$(t pull_hint)"
|
||||
@@ -64,6 +75,7 @@ sys.exit(1)
|
||||
lifecycle_start() {
|
||||
local create_admin="${1:-no}"
|
||||
ensure_media_dir
|
||||
ensure_youtube_dir
|
||||
lifecycle_pull
|
||||
|
||||
local deps; deps="$(backing_services)"
|
||||
@@ -111,7 +123,7 @@ lifecycle_update() {
|
||||
ui_ok "$(t done_title)"
|
||||
}
|
||||
|
||||
lifecycle_up() { ensure_media_dir; dc up -d; }
|
||||
lifecycle_up() { ensure_media_dir; ensure_youtube_dir; dc up -d; }
|
||||
lifecycle_down() { dc down; }
|
||||
lifecycle_logs() { dc logs -f --tail=100; }
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
volumes:
|
||||
- ${MEDIA_HOST_PATH}:${MEDIA_PATH}
|
||||
- transcode_cache:${TRANSCODE_CACHE_PATH}
|
||||
@YOUTUBE_VOLUME@
|
||||
@API_PORTS@
|
||||
@API_DEPENDS@
|
||||
|
||||
@@ -17,4 +18,5 @@
|
||||
volumes:
|
||||
- ${MEDIA_HOST_PATH}:${MEDIA_PATH}
|
||||
- transcode_cache:${TRANSCODE_CACHE_PATH}
|
||||
@YOUTUBE_VOLUME@
|
||||
@WORKER_DEPENDS@
|
||||
|
||||
Reference in New Issue
Block a user