#!/bin/bash show_help() { # echo "Usage: `basename $0` [--no-abort-on-found] [--parallel] [--custom-grep-search|-c ]" echo "Usage: $(basename $0) [--help|-h] [--filter-mode|-f]" echo "Options:" echo " --help | -h (optional) Display script's help text" echo " --filter-mode | -f (optional) The script iterate over the files of a selected folder and store the ones that should be deleted" echo " --urls | -u (optional) List of urls to iterate with preview. Separation by comma (,)" echo " Also use -i to make the script ask which folder to use for every url passed" } filter_mode=false urls_list_arg="" interactive_mode=false while [ "$#" -gt 0 ]; do case "$1" in --help | -h) show_help exit ;; --filter-mode | -f) filter_mode=true shift ;; --urls | -u) urls_list_arg="$2" shift ;; -i) interactive_mode=true shift 2 ;; *) shift ;; esac done commands_to_check=(gallery-dl gdl.sh feh xdotool) commands_not_found=() for command in ${commands_to_check[@]}; do if ! command -v "$command" &>/dev/null; then commands_not_found+=("$command") fi done if [ ${#commands_not_found[@]} -ne 0 ]; then echo 'The following commands are necessary in order to run the script, but were not found:' for command in ${commands_not_found[@]}; do echo " \"$command\"" done exit 1 fi furry_commission_ideas_path=/mnt/e/clouds/nextcloud/furry-downloads # furry_commission_ideas_path=/mnt/e/home/documents-unsorted/data-hoarding/furry-downloads # furry_commission_ideas_path=/mnt/e/home/downloads/furry-downloads furry_commission_ideas_urls_filename="urls.txt" scripts_path=/home/cloud/git/personal-devboot/scripts/shell if [ ! -d $furry_commission_ideas_path ]; then echo "[ERROR] The images folder was not found (\"$furry_commission_ideas_path\")" exit 1 fi if [ ! -d $scripts_path ]; then echo "[ERROR] The scripts folder was not found (\"$scripts_path\")" exit 1 fi convert_csv_to_array() { csv_arg=$1 res_arr=$(echo $csv_arg | tr ',' "\n") echo $res_arr } read_command() { message=$@ read -p "${message}: " read_response echo $read_response } input_media_url() { read_command_message="Please inform a URL" media_url=$(read_command $read_command_message) while [ -z "$media_url" ]; do media_url=$(read_command $read_command_message) done # remove trailing slashes media_url=$(sed 's:/*$::' <<<"$media_url") echo "$media_url" } urls_list=() fill_urls_list_array() { if [ ! -z "$urls_list_arg" ]; then urls_list=($(convert_csv_to_array "$urls_list_arg")) else if ! $filter_mode; then media_url=$(input_media_url) urls_list=("${media_url}") fi fi } fill_urls_list_array cd $furry_commission_ideas_path input_create_folder() { read -p "[INFO] Please inform a name for the new folder: " new_foldername echo "$new_foldername" } selected_folders=() input_selected_folders_and_fill_selected_folders_variable() { read_command_message="Please select a folder (separation by comma)" selected_options_arg=$(read_command $read_command_message) while [ -z "$selected_options_arg" ]; do selected_options_arg=$(read_command $read_command_message) done selected_options=($(convert_csv_to_array "$selected_options_arg")) if [ "$selected_options_arg" == 'n' ]; then new_folder_input_message="Please create a new folder" new_foldername=$(read_command $new_folder_input_message) while [ -z "$new_foldername" ]; do new_foldername=$(read_command $new_folder_input_message) done mkdir --parents "$new_foldername" selected_folders+=("$new_foldername") else for selected_option in ${selected_options[@]}; do selected_folder=${existing_folders[$selected_option]} if [ -z "$selected_folder" ]; then echo "" echo "A selected option is not valid ('$selected_option')" echo "Exiting..." exit 1 fi selected_folders+=("$selected_folder") done fi } show_folder_selection_list_and_fill_selected_folder_variable() { should_colored_output=true if $should_colored_output; then # Define color codes for up to 6 levels color_reset="\033[0m" color_level_1="\033[1;34m" # Blue for the first level color_level_2="\033[1;32m" # Green for the second level color_level_3="\033[1;36m" # Cyan for the third level color_level_4="\033[1;33m" # Yellow for the fourth level color_level_5="\033[1;35m" # Magenta for the fifth level color_level_6="\033[1;31m" # Red for the sixth level # Array of colors to apply to subfolder levels colors=("$color_level_1" "$color_level_2" "$color_level_3" "$color_level_4" "$color_level_5" "$color_level_6") if [ -z "$selected_folder" ]; then printf "\n" echo "[INFO] Folders:" for ((i = 0; i < ${#existing_folders[@]}; i++)); do foldername=${existing_folders[$i]} # Split the foldername by slashes and color each part IFS='/' read -ra parts <<<"$foldername" colored_foldername="${colors[0]}${parts[0]}${color_reset}" for j in "${!parts[@]}"; do if [ $j -gt 0 ]; then # Apply colors cyclically based on the depth level color_index=$((j % ${#colors[@]})) colored_foldername+="/${colors[$color_index]}${parts[$j]}${color_reset}" fi done echo -e " $i) $colored_foldername" # Use -e flag for echo done echo " n) (create a new folder)" printf "\n" input_selected_folders_and_fill_selected_folders_variable while [ -z "$selected_folders" ]; do input_selected_folders_and_fill_selected_folders_variable done fi else if [ -z "$selected_folder" ]; then printf "\n" echo "[INFO] Folders:" for ((i = 0; i < ${#existing_folders[@]}; i++)); do foldername=${existing_folders[$i]} echo " $i) $foldername" done echo " n) (create a new folder)" printf "\n" input_selected_folders_and_fill_selected_folders_variable while [ -z "$selected_folders" ]; do input_selected_folders_and_fill_selected_folders_variable done fi fi } existing_folders=() fill_existing_folders_array() { ignore_paths=("artists" "kinks" "ideas") ignore_paths_depth_2=("artists") ignore_paths_depth_last=("no-source" ".bsky.social" "old" "mine") find_command="find * -type d" for path in "${ignore_paths[@]}"; do find_command+=" -not -path $path" done for path in "${ignore_paths_depth_2[@]}"; do find_command+=" -not -path $path/\*" done for path in "${ignore_paths_depth_last[@]}"; do find_command+=" -not -path *$path" done find_command+=" 2>/dev/null" existing_folders=($(eval $find_command)) if [ -z "${existing_folders}" ]; then echo "" echo "[INFO] There are no folders in the 'furry-commission-ideas' folder." new_foldername=$(input_create_folder) while [ -z "$new_foldername" ]; do new_foldername=$(input_create_folder) done mkdir --parents "$new_foldername" selected_folder="$new_foldername" fi } function confirm() { while true; do read -n 1 yn case $yn in [Yy]*) return 0 ;; [Nn]*) return 1 ;; [Uu]*) return 2 ;; [Cc]*) exit ;; *) echo "Please answer YES, NO, or CANCEL." ;; esac done } escape_string() { local input="$1" local escaped="" # Iterate over each character in the input string while IFS= read -r -n1 char; do case "$char" in ' ' | '\' | '$' | '`' | '!' | '&' | '|' | ';' | '<' | '>' | '"' | "'" | '*' | '?' | '[' | ']' | '{' | '}' | '(' | ')' | '#') escaped="${escaped}\\${char}" ;; *) escaped="${escaped}${char}" ;; esac done <<<"$input" echo "$escaped" } feh_command() { feh_arg=$1 # eval "feh --geometry 1280x1440+1280+0 --auto-zoom --scale-down $eval_string &" eval "feh --geometry 1200x1250+1308+28 --auto-zoom --scale-down $feh_arg &" } filter_mode_steps() { files=() eval_string='' for file in ./*; do if [[ "$file" != *.png && "$file" != *.jpeg && "$file" != *.jpg ]]; then continue fi files+=("$file") eval_string+=$(escape_string "$file") eval_string+=' ' done feh_command "$eval_string" files_to_delete=() files_count=${#files[@]} for ((i = 0; i < files_count; )); do file="${files[$i]}" file="${file#./}" echo "" echo "($((i + 1))/${files_count}) File: $file" echo -n "Should this file be deleted? (y/n): " confirm confirm_result=$? should_undo=false case $confirm_result in 0) if [[ ! ${files_to_delete[@]} =~ $file ]]; then files_to_delete+=("$file") fi ;; 1) ;; 2) if ((i - 1 < 0)); then echo "" echo "" echo "Can't undo because this is the first image" continue else ((i--)) xdotool search --name feh key p files_to_delete=("${files_to_delete[@]/$file/}") continue fi ;; esac xdotool search --name feh key n ((i++)) done echo "" pkill feh # debug if false; then echo "Files to be deleted:" for ((i = 0; i < ${#files_to_delete[@]}; i++)); do file="${files_to_delete[$i]}" echo " $file" done echo "" exit 0 fi for ((i = 0; i < ${#files_to_delete[@]}; i++)); do file="${files_to_delete[$i]}" rm "$file" filename_escaped=$(escape_string "${file}") sed -i "/$filename_escaped/d" urls.txt done } get_information_from_gallery_dl_media() { url=$1 information=$2 tmp_file=$(mktemp --quiet) gallery-dl --list-keyword "$url" >$tmp_file information=$(grep -A1 "$information" "$tmp_file" | tail -n1 | sed 's/^[ \t]*//;s/[ \t]*$//') echo $information } unsucessful_downloads=() generate_random_string_with_suffix() { suffix=$1 random_string=$(cat /dev/urandom | tr -cd 'a-f0-9' | head -c 32) random_string+=".${suffix}" echo $random_string } get_extension_from_filename() { fullfile=$1 filename=$(basename -- "$fullfile") extension="${filename##*.}" echo $extension } image_download_steps() { url_to_download=$1 tmp_dir="/tmp" should_download_at_least_once=false for folder in "${selected_folders[@]}"; do cd "${furry_commission_ideas_path}/${folder}" if [ -f "$furry_commission_ideas_urls_filename" ] && grep -qE "$url_to_download" -i "$furry_commission_ideas_urls_filename"; then echo "" echo "[INFO] The folder informed already has the URL informed" echo " URL: ${url_to_download}" echo " Folder: ${folder}" continue fi should_download_at_least_once=true done if ! $should_download_at_least_once; then return fi echo "" echo "Download starting..." downloaded_images=$(gallery-dl --directory ${tmp_dir} $url_to_download) if [[ $? -ne 0 ]]; then unsucessful_downloads+="$url_to_download" return fi echo "Download finished." # for downloaded_image_temp_path in "${downloaded_images[@]}"; do while read -r downloaded_image_temp_path; do if [ "$downloaded_image_temp_path" == '#' ]; then continue fi for folder in "${selected_folders[@]}"; do cd "${furry_commission_ideas_path}/${folder}" file_extension=$(get_extension_from_filename "$downloaded_image_temp_path") final_temp_filepath_md5=($(md5sum "$downloaded_image_temp_path")) final_filename="${final_temp_filepath_md5}.${file_extension}" cp "$downloaded_image_temp_path" ./${final_filename} echo "$final_filename,$url_to_download" >>$furry_commission_ideas_urls_filename done rm "$downloaded_image_temp_path" done < <(echo "$downloaded_images") } fill_existing_folders_array is_url_string() { str=$1 url_regex='(https?)://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]' media_url_is_url=true if [[ ! $str =~ $url_regex ]]; then media_url_is_url=false fi echo "$media_url_is_url" } if $filter_mode; then show_folder_selection_list_and_fill_selected_folder_variable filter_mode_steps else for url in "${urls_list[@]}"; do while [ "$(is_url_string $url)" == "false" ]; do echo "" echo "The provided URL is not a valid URL." echo " Invalid URL: ${url}" echo "Please input a valid URL." url=$(input_media_url) done show_folder_selection_list_and_fill_selected_folder_variable image_download_steps "${url}" done fi if [ ! -z "${unsucessful_downloads}" ]; then echo "" echo "There were unsucessful downloads:" for url in "${unsucessful_downloads}"; do echo " ${url}" done fi