loader image

Reply To: How to Stop Ad Blocker Detection on Websites Like YouTube

What makes us different from other similar websites? Forums Tech How to Stop Ad Blocker Detection on Websites Like YouTube Reply To: How to Stop Ad Blocker Detection on Websites Like YouTube

#8216
thumbtak
Moderator

Option H added, and some other fixes, that blocked downloads.

#!/bin/bash

# Function to type text character by character for a cool visual effect
type_text() {
text="$1"
for ((i=0; i<${#text}; i++)); do
echo -n "${text:$i:1}"
sleep 0.05 # Adjust this value to change the typing speed
done
echo "" # Add a newline at the end
}

# ----------------------------------------------------------------------
# --- yt-dlp Update Check ---
# ----------------------------------------------------------------------

update_yt_dlp() {
if command -v "yt-dlp" &> /dev/null; then
read -p "A new version of yt-dlp may be available. Do you want to check for updates? (y/n) " update_choice
if [[ "$update_choice" =~ ^[Yy]$ ]]; then
echo "Checking for and installing updates..."
# Check if yt-dlp was installed via pip
if command -v "pip" &> /dev/null && pip freeze | grep "yt-dlp" &> /dev/null; then
pip install -U yt-dlp
else
# Fallback to the self-update command
yt-dlp -U
fi

if [ $? -eq 0 ]; then
echo "yt-dlp updated successfully!"
else
echo "Failed to update yt-dlp."
fi
fi
fi
}

# ----------------------------------------------------------------------
# --- Dependency Checks with Installation Prompts ---
# ----------------------------------------------------------------------

# Function to safely install a tool
install_tool() {
local tool_name="$1"
local install_cmd="$2"
local snap_install="$3"

# First, check if the tool is already installed
if command -v "$tool_name" &> /dev/null; then
echo "'$tool_name' is already installed."
return 0
fi # <--- FIX: Corrected syntax from '}' to 'fi'

# If not, prompt the user for installation
echo "The '$tool_name' tool is required for this script."
read -p "Do you want to install it now? (y/n) " install_choice

if [[ "$install_choice" =~ ^[Yy]$ ]]; then
echo "Installing $tool_name..."
if [ -n "$snap_install" ]; then
sudo snap install "$snap_install"
else
sudo $install_cmd
fi

# Check if the installation was successful
if [ $? -eq 0 ]; then
echo "'$tool_name' installed successfully!"
# Add a small delay and re-check to ensure the shell updates
sleep 1
if ! command -v "$tool_name" &> /dev/null; then
echo "Warning: '$tool_name' was installed but not found in PATH. Please open a new terminal or run 'source ~/.bashrc'."
return 1
fi
return 0
else
echo "Failed to install '$tool_name'. Please install it manually."
return 1
fi
else
echo "Skipping '$tool_name' installation. Some features may not work."
return 1
fi
}

# ----------------------------------------------------------------------
# --- Cookie Flag Builder Function ---
# ----------------------------------------------------------------------
# Helper to generate the cookie flags string based on user input
get_cookie_flags() {
local use_cookies_choice="$1"
local browser_name="$2"
local profile_name="$3"
local cookie_flags=""

if [[ "$use_cookies_choice" =~ ^[Yy]$ ]]; then
# Aggressively clean and lowercase the browser name
local clean_browser_name
clean_browser_name=$(echo "$browser_name" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr '[:upper:]' '[:lower:]')

if [[ -n "$profile_name" ]]; then
# FIX: Removed internal quotes to prevent passing literal quotes to yt-dlp
cookie_flags="--cookies-from-browser ${clean_browser_name}:${profile_name}"
else
# FIX: Removed internal quotes to prevent passing literal quotes to yt-dlp
cookie_flags="--cookies-from-browser ${clean_browser_name}"
fi
fi
echo "$cookie_flags"
}

# ----------------------------------------------------------------------
# --- yt-dlp Command Builder Function (Now expects pre-built cookie flags) ---
# ----------------------------------------------------------------------
build_yt_dlp_command() {
local url="$1"
local output_template="$2"
local download_audio="$3" # 'y' or 'n'
local extra_options="$4"
local print_filename_flag="$5" # '--print filename' or ''
local cookie_flags="$6" # New: Pre-built cookie flags

# The command now includes the cookie flags at the start
local YTDLP_CMD="yt-dlp $cookie_flags \"$url\""

# RESTORING USER-AGENT and other robustness flags to bypass 403 errors.
YTDLP_CMD="$YTDLP_CMD --user-agent \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36\" --no-check-certificate"

if [[ "$download_audio" =~ ^[Yy]$ ]]; then
YTDLP_CMD="$YTDLP_CMD -x --audio-format mp3 -o '$output_template'"
echo "Got it! We'll download the audio in MP3 format." >&2 # Output to stderr
else
# Default to best video/audio combination
YTDLP_CMD="$YTDLP_CMD -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best' -o '$output_template'"
echo "Downloading the best quality video (MP4 preferred)." >&2 # Output to stderr
fi

if [[ -n "$extra_options" ]]; then
YTDLP_CMD="$YTDLP_CMD $extra_options"
fi

# Append the filename print flag if requested
if [[ -n "$print_filename_flag" ]]; then
YTDLP_CMD="$YTDLP_CMD $print_filename_flag"
fi

echo "$YTDLP_CMD" # Only this line is printed to stdout and captured by $()
}

# ----------------------------------------------------------------------
# --- CORE DOWNLOAD FUNCTION (Updated to accept cookie flags) ---
# ----------------------------------------------------------------------
run_single_download() {
local url="$1"
local temp_output_template="$2"
local download_audio_choice="$3"
local interactive_mode="$4" # 'y' for [s], 'n' for [h]
local extra_options="$5" # Passed in
local cookie_flags="$6" # Passed in

# Check if we need the complex print filename logic (only if template contains %(ext)s)
local print_filename_flag=""
if [[ "$temp_output_template" =~ "%(ext)s" ]]; then
print_filename_flag="--print filename"
fi

# Build the command string (passing cookie flags)
YTDLP_CMD=$(build_yt_dlp_command "$url" "$temp_output_template" "$download_audio_choice" "$extra_options" "$print_filename_flag" "$cookie_flags")

echo ""
echo "$SEPARATOR" | lolcat
echo "Your final command is ready:"
echo "$YTDLP_CMD"
echo "$SEPARATOR" | lolcat
echo ""

if [[ "$interactive_mode" == "y" ]]; then
read -p "Ready to download? (y/n) " execute_choice
if [[ ! "$execute_choice" =~ ^[Yy]$ ]]; then
return 1 # Download cancelled
fi
fi

echo "Starting download..."

# Simple execution for fixed names (Used in [s] and [h])
# $YTDLP_CMD contains the cookie flags which expand to two arguments
eval "$YTDLP_CMD"
export FINAL_DOWNLOAD_STATUS=$?
export FINAL_DOWNLOAD_FILENAME="$temp_output_template"

if [ $FINAL_DOWNLOAD_STATUS -ne 0 ]; then
echo "An error occurred during the download."
# Clean up partial files using the known fixed name
rm -f "${temp_output_template}.part"
return 1
fi

echo "Download finished!"
return 0 # Download successful
}

# ----------------------------------------------------------------------
# --- Main Script Logic and Dependency Management ---
# ----------------------------------------------------------------------

# Run update check first
update_yt_dlp

echo "Checking for required dependencies..."
if ! command -v "snap" &> /dev/null; then
install_tool "snapd" "apt install snapd"
else
echo "'snapd' is already installed."
fi
install_tool "figlet" "apt install figlet"
install_tool "lolcat" "" "lolcat"
install_tool "yt-dlp" "apt install yt-dlp"
install_tool "mpv" "apt-get install -y mpv" # Install mpv for Option [h]
install_tool "smplayer" "apt-get install -y smplayer" "smplayer" # Keep smplayer for Option [s]

# At this point, all required tools should be installed or the user declined.
for cmd in yt-dlp figlet lolcat; do
if ! command -v "$cmd" &> /dev/null; then
type_text "Error: '$cmd' is not installed. Exiting."
exit 1
fi
done

# Check for at least one media player
if ! command -v "smplayer" &> /dev/null && ! command -v "mpv" &> /dev/null; then
type_text "Error: Neither 'smplayer' nor 'mpv' is installed. Please install at least one. Exiting."
exit 1
fi

# --- Script Configuration ---
SEPARATOR="---------------------------------------------------"
echo "$SEPARATOR" | lolcat
figlet "YTDLP" | lolcat
echo "$SEPARATOR" | lolcat

# Define a configuration file to save settings
CONFIG_FILE=".yt-dlp_config"

# ----------------------------------------------------------------------
# --- Function: Download and Play from a Playlist File (P/A/D logic) ---
# ----------------------------------------------------------------------

download_and_play_playlist() {
read -p "Enter the name of the text file with the links: " file_name

if [ ! -f "$file_name" ]; then
echo "Error: File '$file_name' not found."
return
fi

local use_cookies_choice
local browser_name=""
local profile_name=""
local cookie_flags=""

read -p "Do these videos require browser authentication (cookies)? (y/n) " use_cookies_choice

# --- COOKIE INTERACTION FOR [p] (Playlist mode) ---
if [[ "$use_cookies_choice" =~ ^[Yy]$ ]]; then
echo "Select a browser for cookies:"
local options=("Chrome" "Firefox" "Brave" "Edge")
select browser_name_temp in "${options[@]}"; do
if [[ -n "$browser_name_temp" ]]; then
browser_name="$browser_name_temp"
break
else
echo "Invalid selection. Please choose a number from the list."
fi
done
read -p "Enter profile name (e.g., 'Default') or leave blank: " profile_name
cookie_flags=$(get_cookie_flags "$use_cookies_choice" "$browser_name" "$profile_name")
fi
# --------------------------------------------------

mkdir -p playlist

echo "Starting download and play session from '$file_name'..."

while IFS= read -r url; do
if [ -n "$url" ]; then
echo "$SEPARATOR" | lolcat
echo "Processing video from URL: $url"

# Use the command builder, passing cookie flags
YTDLP_CMD=$(build_yt_dlp_command "$url" "playlist/%(title)s.%(ext)s" "n" "" "" "$cookie_flags")

echo "Executing: $YTDLP_CMD"
eval "$YTDLP_CMD"

if [ $? -eq 0 ]; then
echo "Download successful."

# Finding the file by last modified time is the most reliable way when using %(title)s.%(ext)s
video_file=$(find playlist -type f -mtime -1m -printf '%T@ %p\n' 2>/dev/null | sort -n | tail -1 | cut -d' ' -f2-)

if [ -n "$video_file" ] && [ -f "$video_file" ]; then
echo "Playing: $(basename "$video_file")"
# Default to smplayer here, as this is the standard playlist mode
if command -v "smplayer" &> /dev/null; then
smplayer -close-after-media-ended "$video_file"
elif command -v "mpv" &> /dev/null; then
mpv "$video_file"
fi

read -p "Finished playing. Do you want to delete this video and remove the link from the file? (y/n) " delete_choice
if [[ "$delete_choice" =~ ^[Yy]$ ]]; then
rm "$video_file"
sed -i.bak "\@^$url$@d" "$file_name"
echo "Deleted video and removed link from $file_name."
else
echo "Skipped deletion and link removal."
fi
else
echo "Could not reliably find the downloaded video file."
fi
else
echo "Download failed for URL: $url"
fi
fi
done < "$file_name"

echo "$SEPARATOR" | lolcat
echo "Playlist session complete."
}

add_url_to_playlist() {
read -p "Please paste the YouTube URL you want to add to a playlist: " url
if [[ -z "$url" ]]; then
type_text "No URL provided. Exiting."
return
fi

LAST_PLAYLIST_FILE="playlist.txt"
if [ -f "$CONFIG_FILE" ]; then
LAST_PLAYLIST_FILE=$(grep "^LAST_PLAYLIST_FILE=" "$CONFIG_FILE" | cut -d'=' -f2-)
if [ -z "$LAST_PLAYLIST_FILE" ]; then
LAST_PLAYLIST_FILE="playlist.txt"
fi
fi

read -p "Enter the name of the playlist file to add the link to (default: $LAST_PLAYLIST_FILE): " playlist_file_input

if [ -z "$playlist_file_input" ]; then
playlist_file="$LAST_PLAYLIST_FILE"
else
playlist_file="$playlist_file_input"
fi

echo "$url" >> "$playlist_file"
type_text "URL added to $playlist_file"

echo "LAST_PLAYLIST_FILE=$playlist_file" > "$CONFIG_FILE"
}

# ----------------------------------------------------------------------
# --- Function: Download, Auto-Play, and Delete Loop ([h] Logic) ---
# ----------------------------------------------------------------------
hybrid_stream_loop() {
# The temporary fixed filename placeholder
local temp_filename="taksshack.com.mp4"
local MAX_RETRIES=10
local RETRY_DELAY=10

# Ensure mpv is installed, since this option relies on it for direct playback
if ! command -v "mpv" &> /dev/null; then
echo "Error: The [h] option requires 'mpv'. Please install it."
return 1
fi

while true; do
echo "$SEPARATOR" | lolcat
read -p "Please paste the YouTube URL you want to download and play (or type 'q' to exit): " url

if [[ "$url" =~ ^[Qq]$ ]]; then
break
elif [[ -z "$url" ]]; then
echo "No URL provided. Please try again."
continue
fi

# --- INTERACTION FOR [h] (Cookie and Extra Options) ---
local use_cookies_choice
local browser_name=""
local profile_name=""
local cookie_flags=""

read -p "Do you want to use a browser for authentication (cookies)? (y/n) " use_cookies_choice

# Follow-up questions for cookie details
if [[ "$use_cookies_choice" =~ ^[Yy]$ ]]; then
echo "Select a browser for cookies:"
local options=("Chrome" "Firefox" "Brave" "Edge")
select browser_name_temp in "${options[@]}"; do
if [[ -n "$browser_name_temp" ]]; then
browser_name="$browser_name_temp"
break
else
echo "Invalid selection. Please choose a number from the list."
fi
done
read -p "Enter profile name (e.g., 'Default') or leave blank: " profile_name
# Build the cookie flags immediately
cookie_flags=$(get_cookie_flags "$use_cookies_choice" "$browser_name" "$profile_name")
fi

read -p "Any other yt-dlp options (e.g., --verbose)? " extra_options
if [[ "$extra_options" == "n" ]]; then
extra_options=""
fi
# -------------------------------

# 1. Get the actual final filename, which includes the correct extension
# FIX: Now includes $cookie_flags to authenticate the filename lookup
local original_filename
# $cookie_flags is unquoted here, correctly expanding to "--cookies-from-browser chrome" (two arguments)
original_filename=$(yt-dlp --get-filename -o '%(title)s.%(ext)s' $cookie_flags "$url" 2>/dev/tty)
local status=$?

# Trim leading/trailing whitespace just in case (important if yt-dlp spits out newlines)
original_filename=$(echo "$original_filename" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')

if [ $status -ne 0 ] || [ -z "$original_filename" ]; then
echo "Error: Could not determine the original filename/extension for the URL (yt-dlp exit code: $status). Aborting URL."
continue
fi

# 2. Download Loop with Retries
local RETRY_COUNT=1
local DOWNLOAD_SUCCESS=0

while [ $RETRY_COUNT -le $MAX_RETRIES ]; do
echo "$SEPARATOR" | lolcat
echo "--- Download Attempt $RETRY_COUNT of $MAX_RETRIES ---"

# Run the core download function (passing cookie flags)
run_single_download "$url" "$temp_filename" "n" "n" "$extra_options" "$cookie_flags"

if [ $? -eq 0 ]; then
DOWNLOAD_SUCCESS=1
break # Exit the retry loop on success
else
echo "Download failed. Waiting $RETRY_DELAY seconds before retrying..."
sleep $RETRY_DELAY
RETRY_COUNT=$((RETRY_COUNT + 1))
fi
done

if [ $DOWNLOAD_SUCCESS -eq 1 ]; then
# 3. Download was successful. Check if the placeholder file exists.
if [ -f "$temp_filename" ]; then

# 4. ATOMIC RENAME: Rename the placeholder to the actual name/extension.
local final_video_file="$original_filename"
mv "$temp_filename" "$final_video_file"

echo "$SEPARATOR" | lolcat
echo "Launching player (mpv) fullscreen and stretched for: $final_video_file"

# 5. Play the correctly named file using direct mpv with full screen and forced stretch
mpv --fullscreen --no-keepaspect --no-keepaspect-window "$final_video_file"

echo "Playback session ended. Auto-deleting file."

# 6. Auto-delete the final file
rm -f "$final_video_file"
echo "Temporary file deleted: $final_video_file"
else
echo "Error: Download was reported successful but the final file could not be located at the expected placeholder ($temp_filename)."
rm -f "${temp_filename}.part"
fi
else
echo "$SEPARATOR" | lolcat
echo "Download failed after $MAX_RETRIES attempts. Moving to next URL or exiting loop."
fi

echo "$SEPARATOR" | lolcat
echo "Operation complete."
echo "$SEPARATOR" | lolcat

read -p "Do you want to process another URL? (y/n) " play_again_choice
if [[ ! "$play_again_choice" =~ ^[Yy]$ ]]; then
break
fi
done
}

# ----------------------------------------------------------------------
# --- Single Download and Play/Save ([s] Logic) ---
# ----------------------------------------------------------------------
single_download_and_save() {
read -p "Please paste the YouTube URL you want to download: " url

# --- INTERACTION FOR [s] ---
local use_cookies_choice
local browser_name=""
local profile_name=""
local cookie_flags=""

read -p "Do you want to use a browser for authentication? (y/n) " use_cookies_choice

# Follow-up questions for cookie details
if [[ "$use_cookies_choice" =~ ^[Yy]$ ]]; then
echo "Select a browser for cookies:"
local options=("Chrome" "Firefox" "Brave" "Edge")
select browser_name_temp in "${options[@]}"; do
if [[ -n "$browser_name_temp" ]]; then
browser_name="$browser_name_temp"
break
else
echo "Invalid selection. Please choose a number from the list."
fi
done
read -p "Enter profile name (e.g., 'Default') or leave blank: " profile_name
# Build the cookie flags immediately
cookie_flags=$(get_cookie_flags "$use_cookies_choice" "$browser_name" "$profile_name")
fi

read -p "Any other yt-dlp options (e.g., --verbose)? " extra_options
if [[ "$extra_options" == "n" ]]; then
extra_options=""
fi
# ---------------------------

# Prompt for audio
read -p "Do you want to download just the audio? (y/n) " download_audio_choice

# Get original filename early to use for saving later (using cookie flags for authentication)
local original_filename
original_filename=$(yt-dlp --get-filename -o '%(title)s.%(ext)s' $cookie_flags "$url")
local temp_filename="taksshack.com.mp4"

# Run the core download function in interactive mode ("y"), passing cookie details
run_single_download "$url" "$temp_filename" "$download_audio_choice" "y" "$extra_options" "$cookie_flags"

if [ $? -eq 0 ]; then
# Download was successful

read -p "Do you want to play the downloaded media? (y/n) " play_choice
if [[ "$play_choice" =~ ^[Yy]$ ]]; then
if command -v "smplayer" &> /dev/null; then
smplayer "$temp_filename"
elif command -v "mpv" &> /dev/null; then
mpv "$temp_filename"
else
echo "Cannot play: Neither smplayer nor mpv found."
fi
fi

# Check the actual extension for saving
if [[ "$download_audio_choice" =~ ^[Yy]$ ]]; then
# If audio was downloaded, the final file is mp3, rename the original_filename variable
original_filename="${original_filename%.*}.mp3"
else
# For video, rename the placeholder to the original name/extension
local final_video_file="$original_filename"
mv "$temp_filename" "$final_video_file"
temp_filename="$final_video_file" # Update the reference for cleanup

# Reset original_filename to the correct name/extension for the prompt
original_filename="$final_video_file"
fi

read -p "Do you want to save the file as '$original_filename'? (y/n) " save_choice
if [[ "$save_choice" =~ ^[Yy]$ ]]; then
# If video, it's already renamed and saved. If audio, mv from temp_filename (which is taksshack.com.mp4)
if [[ "$download_audio_choice" =~ ^[Yy]$ ]]; then
mv "taksshack.com.mp4" "$original_filename"
fi
echo "File saved as '$original_filename'"
else
rm "$temp_filename"
echo "File deleted."
fi
fi

echo ""
echo "$SEPARATOR" | lolcat
echo "Operation complete."
echo "$SEPARATOR" | lolcat
}

# ----------------------------------------------------------------------
# --- Main Script Execution ---
# ----------------------------------------------------------------------

type_text "Welcome to the yt-dlp interactive downloader!"
echo "https://taksshack.com"
echo ""

echo "Please choose an option:"
echo " [a] Add a single video to a playlist file (after downloading)"
echo " [p] Run and play a list of videos from a file"
echo " [s] Download a single video and ask to play/save it"
echo " [d] Add a single URL to a playlist file (without downloading)"
echo " [h] Download, Auto-Play, and Delete (Uses full download progress as buffer) ⭐ NEW"
read -p "Your choice (a/p/s/d/h): " main_choice

if [[ "$main_choice" =~ ^[Pp]$ ]]; then
download_and_play_playlist
elif [[ "$main_choice" =~ ^[Aa]$ ]]; then
add_url_to_playlist
elif [[ "$main_choice" =~ ^[Dd]$ ]]; then
add_url_to_playlist
elif [[ "$main_choice" =~ ^[Ss]$ ]]; then
single_download_and_save
elif [[ "$main_choice" =~ ^[Hh]$ ]]; then
hybrid_stream_loop
fi
  • This reply was modified 3 weeks, 1 day ago by thumbtak. Reason: Retry added to option H if you get a 403 error
  • This reply was modified 3 weeks, 1 day ago by thumbtak. Reason: Fixed logic related to option H and using cookies
TAKs Shack
Wishing you and yours a very happy Thanksgiving!
This is default text for notification bar