Files
universal-merge/core_logic.sh
T

214 lines
8.8 KiB
Bash
Raw 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
#==============================================================================
# Модуль основной логики: поиск файлов, сопоставление, генерация имён
#==============================================================================
declare -a FILE_TRIPLETS
# Функция стала "умной" и проверяет CURRENT_ACTION
logic_prepare_file_lists() {
FILE_TRIPLETS=()
local common_params_ok=true
if [[ -z "$VIDEO_SRC_DIR" || -z "$OUTPUT_BASE_DIR" || -z "$OUTPUT_SERIES_NAME" ]]; then
common_params_ok=false
fi
local video_list_raw
if $common_params_ok; then
mapfile -d '' video_list_raw < <(find "$VIDEO_SRC_DIR" -maxdepth 1 -name "$VIDEO_FILE_PATTERN" -print0 | sort -z)
fi
# РЕЖИМ: СКЛЕЙКА
if [ "$CURRENT_ACTION" == "MERGE" ]; then
if ! $common_params_ok || [[ -z "$AUDIO_SRC_DIR" ]]; then
ui_show_message "Ошибка" "Для склейки должны быть заданы все каталоги (видео, аудио, вывод) и имя сериала."
return 1
fi
if [ ${#video_list_raw[@]} -eq 0 ]; then
ui_show_message "Ошибка" "Видеофайлы по шаблону '$VIDEO_FILE_PATTERN' не найдены."
return 1
fi
local audio_list_raw
mapfile -d '' audio_list_raw < <(find "$AUDIO_SRC_DIR" -name "$AUDIO_FILE_PATTERN" -print0 | sort -z)
if [ ${#audio_list_raw[@]} -eq 0 ]; then
ui_show_message "Ошибка" "Аудиофайлы по шаблону '$AUDIO_FILE_PATTERN' не найдены."
return 1
fi
if [ ${#video_list_raw[@]} -ne ${#audio_list_raw[@]} ]; then
ui_show_message "Ошибка" "Количество видео (${#video_list_raw[@]}) и аудио (${#audio_list_raw[@]}) не совпадает."
return 1
fi
local -a sub_list_raw=()
if [[ -n "$SUB_SRC_DIR" ]]; then
mapfile -d '' sub_list_raw < <(find "$SUB_SRC_DIR" -name "$SUB_FILE_PATTERN" -print0 | sort -z)
if [ ${#sub_list_raw[@]} -eq 0 ]; then
ui_show_message "Ошибка" "Субтитры по шаблону '$SUB_FILE_PATTERN' не найдены."
return 1
fi
if [ ${#video_list_raw[@]} -ne ${#sub_list_raw[@]} ]; then
ui_show_message "Ошибка" "Количество видео (${#video_list_raw[@]}), аудио (${#audio_list_raw[@]}) и субтитров (${#sub_list_raw[@]}) не совпадает."
return 1
fi
fi
for i in "${!video_list_raw[@]}"; do
local video_file="${video_list_raw[$i]}"
local audio_file="${audio_list_raw[$i]}"
local subtitle_file="${sub_list_raw[$i]}"
local output_path
output_path=$(logic_generate_output_name "$video_file") || return 1
FILE_TRIPLETS+=("$video_file"$'\t'"$audio_file"$'\t'"$output_path"$'\t'"$subtitle_file")
done
# РЕЖИМ: СИМЛИНКИ
elif [ "$CURRENT_ACTION" == "SYMLINK" ]; then
if ! $common_params_ok; then
ui_show_message "Ошибка" "Для симлинков должны быть заданы каталог видео, каталог вывода и имя сериала."
return 1
fi
if [ ${#video_list_raw[@]} -eq 0 ]; then
ui_show_message "Ошибка" "Видеофайлы по шаблону '$VIDEO_FILE_PATTERN' не найдены."
return 1
fi
for video_file in "${video_list_raw[@]}"; do
local output_path
output_path=$(logic_generate_output_name "$video_file") || continue
# --- ИСПРАВЛЕНИЕ ЗДЕСЬ: ИСПОЛЬЗУЕМ ЯВНЫЙ ЗАПОЛНИТЕЛЬ ---
# Это гарантирует, что `read` всегда увидит три поля.
local placeholder="__SYMLINK_AUDIO_PLACEHOLDER__"
FILE_TRIPLETS+=("$video_file"$'\t'"$placeholder"$'\t'"$output_path")
done
fi
logic_check_output_paths || return 1
return 0
}
# Уже готовый результат: обычный файл или симлинк (в том числе битый).
# Каталог сюда не входит: это не серия, а ошибка пути.
output_file_exists() {
local path="$1"
[[ -f "$path" || -L "$path" ]]
}
# Одинаковые имена и путь-каталог ломают пропуск: вторая серия увидела бы
# файл, созданный первой, и отчёт засчитал бы её как уже готовую.
logic_check_output_paths() {
local -A seen=()
local triplet video audio output
local -a dir_errors=()
local -a dup_errors=()
for triplet in "${FILE_TRIPLETS[@]}"; do
IFS=$'\t' read -r video audio output <<< "$triplet"
if [[ -d "$output" && ! -L "$output" ]]; then
dir_errors+=("$(basename "$video") → $output")
continue
fi
if [[ -n ${seen["$output"]+x} ]]; then
dup_errors+=("$(basename "${seen[$output]}") и $(basename "$video") → $(basename "$output")")
else
seen["$output"]="$video"
fi
done
if [ ${#dir_errors[@]} -gt 0 ]; then
local text="Путь вывода указывает на каталог, а не на файл:\n\n"
local line
for line in "${dir_errors[@]}"; do
text+="$line\n"
done
ui_show_message "Ошибка" "$text"
return 1
fi
if [ ${#dup_errors[@]} -gt 0 ]; then
local text="Несколько серий получают одно и то же имя:\n\n"
local line
for line in "${dup_errors[@]}"; do
text+="$line\n"
done
ui_show_message "Ошибка" "$text"
return 1
fi
return 0
}
# Вспомогательная функция для генерации имени, чтобы не дублировать код
logic_generate_output_name() {
local video_file="$1"
local video_basename
video_basename=$(basename "$video_file")
if [[ "$video_basename" =~ $EPISODE_NUMBER_REGEX ]]; then
local episode_num
episode_num=$(printf "%02d" "$((10#${BASH_REMATCH[1]}))")
local output_name="$OUTPUT_FILENAME_TEMPLATE"
output_name="${output_name/\{SERIES_NAME\}/$OUTPUT_SERIES_NAME}"
output_name="${output_name/\{SEASON\}/$SEASON_NUMBER}"
output_name="${output_name/\{EPISODE\}/$episode_num}"
echo "${OUTPUT_BASE_DIR}/${output_name}"
return 0
else
ui_show_message "Ошибка Regex" "Не удалось извлечь номер эпизода из файла:\n$video_basename\n\nС помощью регулярного выражения:\n$EPISODE_NUMBER_REGEX"
return 1
fi
}
# Предпросмотр теперь будет работать правильно
logic_show_preview() {
if ! logic_prepare_file_lists; then return 1; fi
if [ ${#FILE_TRIPLETS[@]} -eq 0 ]; then
ui_show_message "Предпросмотр" "Нет файлов для обработки по текущим настройкам."
return
fi
local body=""
local count=1
local skip_count=0
for triplet in "${FILE_TRIPLETS[@]}"; do
IFS=$'\t' read -r video audio output subtitle <<< "$triplet"
body+="$(printf "%02d" $count). \n"
local exists=false
if output_file_exists "$output"; then
exists=true
skip_count=$((skip_count + 1))
fi
if [ "$CURRENT_ACTION" == "MERGE" ]; then
body+=" \ZbВИДЕО:\Zn $(basename "$video")\n"
body+=" \ZbАУДИО:\Zn $(basename "$audio")\n"
if [[ -n "$subtitle" ]]; then
body+=" \ZbСУБТИТРЫ:\Zn $(basename "$subtitle")\n"
fi
body+=" \Zb-> ВЫВОД:\Zn $(basename "$output")\n"
else # SYMLINK
body+=" \ZbИСТОЧНИК:\Zn $(basename "$video")\n"
body+=" \Zb-> ССЫЛКА:\Zn $(basename "$output")\n"
fi
if $exists; then
body+=" \Z3ПРОПУСК:\Zn операция пропущена — файл уже есть\n\n"
else
body+="\n"
fi
count=$((count + 1))
done
local pending=$((${#FILE_TRIPLETS[@]} - skip_count))
local preview_text="РЕЖИМ: $CURRENT_ACTION\n"
preview_text+="К обработке: $pending, пропуск (уже есть): $skip_count\n\n"
preview_text+="$body"
ui_show_message "Предпросмотр" "$preview_text"
}