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

#8221
thumbtak
Moderator

A 403 error often means YouTube is blocking your IP address or rejecting your existing connection/cookies. I’ve updated the script to include two aggressive flags to help bypass this issue:

  1. --force-ipv4: Instructs yt-dlp to only use IPv4, which can sometimes bypass IPv6-related blocks.
  2. Aria2c Downloader: I’ve integrated checks for the faster external downloader, Aria2c, and set it to use 16 connections (--max-connection-per-server=16). This helps with multi-part downloads and often improves connection resilience, which can mitigate 403 issues during a download.

Full Script with the 403 Bypass Fixes Applied

#!/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 (FIXED SYNTAX)
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 # <--- CORRECTED: Closing the 'if' statement with '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
# Try apt-get if it's the primary install method
if command -v "apt-get" &> /dev/null; then
sudo apt-get update && sudo apt-get install -y "$tool_name"
elif command -v "apt" &> /dev/null; then
sudo apt update && sudo apt install -y "$tool_name"
else
sudo $install_cmd
fi
fi

# Check if the installation was successful
if [ $? -eq 0 ]; then
echo "'$tool_name' installed successfully!"
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
}

# ----------------------------------------------------------------------
# --- Tor Management Functions ---
# ----------------------------------------------------------------------

# Global variables
TOR_STARTED_BY_SCRIPT=0
TOR_PID=""
TOR_AGGRESSIVE_MODE="n" # Global to track if we skip the Android spoof for max quality

start_tor() {
if ! command -v "tor" &> /dev/null; then
echo "Tor is not installed. Skipping Tor proxy."
return 1
fi

read -p "Do you want to use the Tor network for this operation (anonymity/bypassing geo-blocks)? (y/n) " use_tor_choice

if [[ "$use_tor_choice" =~ ^[Yy]$ ]]; then
echo ""
echo "Tor Quality Mode Selection:"
echo " [1] High-Quality (Aggressive): Tries for 4K/1080p, but risks the '403 Forbidden' error."
echo " [2] Reliable (Safe): Guarantees bypass of '403 Forbidden', but often limits quality to 720p/480p."
read -p "Select mode (1 or 2): " mode_choice

if [[ "$mode_choice" == "1" ]]; then
TOR_AGGRESSIVE_MODE="y"
echo "Mode: High-Quality (Aggressive) selected. Proceeding to start Tor..."
else
TOR_AGGRESSIVE_MODE="n"
echo "Mode: Reliable (Safe) selected. Proceeding to start Tor..."
fi

echo "Attempting to start Tor in the background (SOCKS5 on 127.0.0.1:9050)..."
# Check if Tor is already running (e.g., via system service)
if pgrep -x "tor" > /dev/null; then
echo "Tor is already running. Will use existing instance."
TOR_STARTED_BY_SCRIPT=0
return 0
fi

# Start Tor as a background process, redirecting output to /dev/null
tor &
TOR_PID=$!
sleep 5 # Wait for Tor to bootstrap

if kill -0 $TOR_PID 2>/dev/null; then
echo "Tor started successfully (PID: $TOR_PID)."
TOR_STARTED_BY_SCRIPT=1
return 0
else
echo "Failed to start Tor. Falling back to direct connection."
TOR_STARTED_BY_SCRIPT=0
return 1
fi
fi
# If Tor is not used, reset aggressive mode just in case
TOR_AGGRESSIVE_MODE="n"
return 1
}

stop_tor() {
if [ "$TOR_STARTED_BY_SCRIPT" -eq 1 ] && [ -n "$TOR_PID" ]; then
echo "Stopping Tor process (PID: $TOR_PID)..."
kill "$TOR_PID" 2>/dev/null
if [ $? -eq 0 ]; then
echo "Tor stopped."
else
echo "Could not stop Tor gracefully. It may have already exited."
fi
fi
# Reset mode after stopping
TOR_AGGRESSIVE_MODE="n"
}

# ----------------------------------------------------------------------
# --- 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
cookie_flags="--cookies-from-browser ${clean_browser_name}:${profile_name}"
else
cookie_flags="--cookies-from-browser ${clean_browser_name}"
fi
fi
echo "$cookie_flags"
}

# ----------------------------------------------------------------------
# --- CONSOLIDATED INTERACTION FUNCTION ---
# ----------------------------------------------------------------------
# Prompts for cookies, Tor, and extra options in a single block.
# Outputs:
# - cookie_flags (string)
# - extra_options (string)
# - tor_enabled (global TOR_STARTED_BY_SCRIPT is set)
# - tor_aggressive (global TOR_AGGRESSIVE_MODE is set)
get_user_options() {
local __cookie_flags_out=$1
local __extra_options_out=$2

local use_cookies_choice="n"
local browser_name=""
local profile_name=""
local cookie_flags=""
local extra_options=""

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

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

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

# 3. TOR INTERACTION (Sets globals TOR_STARTED_BY_SCRIPT and TOR_AGGRESSIVE_MODE)
start_tor # This function handles the prompting and starting of Tor

# Set the output variables using nameref/indirect reference
eval "$__cookie_flags_out=\"$cookie_flags\""
eval "$__extra_options_out=\"$extra_options\""
}

# ----------------------------------------------------------------------
# --- yt-dlp Command Builder Function ---
# ----------------------------------------------------------------------
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"
local tor_enabled="$7" # 'y' or 'n'
local tor_aggressive="$8" # 'y' or 'n'

local YTDLP_CMD="yt-dlp"

# --- Tor Proxy and 403/Quality Fix Integration ---
if [[ "$tor_enabled" =~ ^[Yy]$ ]]; then
YTDLP_CMD="$YTDLP_CMD --proxy socks5://127.0.0.1:9050"

if [[ "$tor_aggressive" == "n" ]]; then
# Reliable Mode: Use the Android spoof to bypass the 403 check, but quality is limited
YTDLP_CMD="$YTDLP_CMD --extractor-args \"youtube:player-client=android\""
echo "Tor proxy (Reliable Mode: Android spoof active)." >&2
else
# Aggressive Mode: Do NOT use the Android spoof to maximize quality
echo "Tor proxy (Aggressive Mode: Max Quality attempted)." >&2
fi
fi
# -----------------------------------------

# Add Cookies and URL
YTDLP_CMD="$YTDLP_CMD $cookie_flags \"$url\""

# --- Robustness Flags: Referer, Retries, User-Agent ---
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\""
YTDLP_CMD="$YTDLP_CMD --no-check-certificate"
YTDLP_CMD="$YTDLP_CMD --extractor-retries 5"
YTDLP_CMD="$YTDLP_CMD --referer https://www.youtube.com/"
# --------------------------------------------------------

# --- Download Engine Logic ---
if [[ -n "$extra_options" ]] && command -v "aria2c" &> /dev/null; then
YTDLP_CMD="$YTDLP_CMD --force-ipv4 --external-downloader aria2c --external-downloader-args \"aria2c:--max-connection-per-server=16\""
echo "Using aria2c for download robustness." >&2
else
YTDLP_CMD="$YTDLP_CMD --force-ipv4"
echo "Using internal yt-dlp download for stability." >&2
fi
# -----------------------------

if [[ "$download_audio" =~ ^[Yy]$ ]]; then
# Audio download
YTDLP_CMD="$YTDLP_CMD -x --audio-format mp3 -o '$output_template'"
echo "Downloading audio in MP3 format." >&2
else
# Video download: Highest Quality Resilient String
YTDLP_CMD="$YTDLP_CMD -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/bestvideo+bestaudio/best[ext=mp4]/best' -k -o '$output_template'"
echo "Downloading the HIGHEST reliable quality video and audio (MP4 preferred)." >&2
fi

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

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

echo "$YTDLP_CMD"
}

# ----------------------------------------------------------------------
# --- CORE DOWNLOAD FUNCTION ---
# ----------------------------------------------------------------------
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 others
local extra_options="$5"
local cookie_flags="$6"
local tor_enabled="$7" # Passed in
local tor_aggressive="$8" # Passed in

local print_filename_flag=""
if [[ "$temp_output_template" =~ "%(ext)s" ]]; then
print_filename_flag="--print filename"
fi

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

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

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

echo "Starting download..."

# Execute the command
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 (Exit Code: $FINAL_DOWNLOAD_STATUS)."
# Clean up temporary part files
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_tool "smplayer" "apt-get install -y smplayer" "smplayer"
install_tool "aria2c" "apt-get install -y aria2"
install_tool "tor" "apt-get install -y tor"

# Check for essential tools
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: Get Filename (Direct Connection) ---
# ----------------------------------------------------------------------
# This function is run BEFORE Tor is started to get the best info
get_info_direct() {
local url="$1"
local cookie_flags="$2"
local download_audio_choice="$3"

local filename_template=""
local format_string=""

if [[ "$download_audio_choice" =~ ^[Yy]$ ]]; then
# For audio, we look for the best audio stream and set filename to mp3
filename_template='%(title)s.mp3'
format_string="bestaudio[ext=m4a]/bestaudio"
else
# For video, we look for the best video/audio streams and set filename to mp4
filename_template='%(title)s.mp4'
# Resilient format string used to determine the final filename extension
format_string="bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best"
fi

local original_filename
# Use yt-dlp to output the determined filename using the best format string
original_filename=$(yt-dlp --get-filename -o "$filename_template" -f "$format_string" $cookie_flags "$url" 2>/dev/null)
original_filename=$(echo "$original_filename" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')

if [ -z "$original_filename" ]; then
echo "Error: Could not determine original filename via direct connection." >&2
return 1
fi

# Returning only the filename. The download command uses the static, resilient format string.
echo "$original_filename"
return 0
}
# ----------------------------------------------------------------------

# ----------------------------------------------------------------------
# --- Function: Download and Play from a Playlist File ([l] 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 cookie_flags=""
local extra_options=""

echo "$SEPARATOR" | lolcat

# Use consolidated option getter (Tor is global, will be available)
get_user_options "cookie_flags" "extra_options"

local tor_enabled="n"
local tor_aggressive="n"
if [ "$TOR_STARTED_BY_SCRIPT" -eq 1 ] || pgrep -x "tor" > /dev/null; then
tor_enabled="y"
tor_aggressive="$TOR_AGGRESSIVE_MODE"
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"

# 1. Get info directly
local info
info=$(get_info_direct "$url" "$cookie_flags" "n")
local status=$?

if [ $status -ne 0 ]; then
echo "Warning: Could not determine final filename. Skipping URL."
continue
fi

# Use the command builder, passing all options
YTDLP_CMD=$(build_yt_dlp_command "$url" "playlist/%(title)s.%(ext)s" "n" "$extra_options" "" "$cookie_flags" "$tor_enabled" "$tor_aggressive")

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

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

# Finding the downloaded file based on modification time
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")"
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"
# Safely remove the URL line from the 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"

# Stop Tor after the playlist finishes
stop_tor

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"
}

# ----------------------------------------------------------------------
# --- Download, Play, and Add to Playlist ([a] Logic) ---
# ----------------------------------------------------------------------
download_play_and_add_to_playlist() {
local temp_filename="taksshack.com.mp4"
local MAX_RETRIES=10
local RETRY_DELAY=10

if ! command -v "mpv" &> /dev/null; then
echo "Error: This option requires 'mpv' for playback. Please install it."
return 1
fi # <-- FIXED: This was the missing 'fi'

# --- INPUT/COOKIE/TOR SECTION ---
echo "$SEPARATOR" | lolcat
read -p "Please paste the YouTube URL you want to download and add to a playlist: " url

if [[ -z "$url" ]]; then
echo "No URL provided. Aborting."
return
fi

local cookie_flags=""
local extra_options=""

# Use consolidated option getter
get_user_options "cookie_flags" "extra_options"

local tor_enabled="n"
local tor_aggressive="n"
if [ "$TOR_STARTED_BY_SCRIPT" -eq 1 ] || pgrep -x "tor" > /dev/null; then
tor_enabled="y"
tor_aggressive="$TOR_AGGRESSIVE_MODE"
fi
# -------------------------------

# 1. Get info directly
local info
info=$(get_info_direct "$url" "$cookie_flags" "n")
local status=$?
local original_filename=""

if [ $status -eq 0 ]; then
# original_filename is retrieved
original_filename="$info"
else
echo "Error: Could not determine original filename. Aborting URL."
stop_tor
return
fi

# 2. Download Loop
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 (Tor: $tor_enabled) ---"

# Run the core download function, passing Tor flag and aggressive mode
run_single_download "$url" "$temp_filename" "n" "n" "$extra_options" "$cookie_flags" "$tor_enabled" "$tor_aggressive"

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

# Stop Tor once download attempts are complete
stop_tor

if [ $DOWNLOAD_SUCCESS -eq 1 ]; then
# 3. Download successful: Rename, Play, and Add to Playlist

if [ -f "$temp_filename" ]; then
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"

mpv --fullscreen --no-keepaspect --no-keepaspect-window "$final_video_file"

echo "Playback session ended."

# --- Add to Playlist Logic ---
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"
# -----------------------------

read -p "Do you want to delete the downloaded file '$final_video_file' now? (y/n) " delete_choice
if [[ "$delete_choice" =~ ^[Yy]$ ]]; then
rm -f "$final_video_file"
echo "File deleted."
else
echo "File saved as '$final_video_file'."
fi

else
echo "Error: Download was reported successful but the final file could not be located."
fi
else
echo "$SEPARATOR" | lolcat
echo "Download failed after $MAX_RETRIES attempts. Cannot proceed to play or add to playlist."
fi

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

# ----------------------------------------------------------------------
# --- Quick View / Live Stream Logic ([p] and [t]) ---
# ----------------------------------------------------------------------
# This function is now used for both [p] (quick D/P/D) and [t] (streaming)
hybrid_stream_loop() {
local temp_filename="taksshack.com.mp4"
local MAX_RETRIES=10
local RETRY_DELAY=10
local requested_action="$1" # 'stream' or 'download'

if ! command -v "mpv" &> /dev/null; then
echo "Error: This option requires 'mpv' for playback. Please install it."
return 1
fi

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

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

# --- INPUT/COOKIE/TOR SECTION ---
local cookie_flags=""
local extra_options=""

get_user_options "cookie_flags" "extra_options"

local tor_enabled="n"
local tor_aggressive="n"
if [ "$TOR_STARTED_BY_SCRIPT" -eq 1 ] || pgrep -x "tor" > /dev/null; then
tor_enabled="y"
tor_aggressive="$TOR_AGGRESSIVE_MODE"
fi
# -------------------------------

# ======================================================================
# --- LIVE STREAMING LOGIC ([t] option) ---
# ======================================================================
if [[ "$requested_action" == "stream" ]]; then
echo "Attempting to extract streaming URL and pipe directly to mpv (Bypassing download)..."

# Use the Tor/Cookie flags if enabled. Use -f 'best' and -g to get the stream URL.
local STREAM_CMD="yt-dlp -f 'best' -g $cookie_flags \"$url\" $extra_options"

# Add Tor/Proxy if enabled.
if [[ "$tor_enabled" =~ ^[Yy]$ ]]; then
STREAM_CMD="$STREAM_CMD --proxy socks5://127.0.0.1:9050"

if [[ "$tor_aggressive" == "n" ]]; then
STREAM_CMD="$STREAM_CMD --extractor-args \"youtube:player-client=android\""
echo "Using Reliable (Safe) mode for streaming (may limit quality)." >&2
else
echo "Using Aggressive (High-Quality) mode for streaming." >&2
fi
fi

echo "Extraction Command: $STREAM_CMD"

# Execute yt-dlp to get the URL, and pipe it directly to MPV
local FINAL_STREAM_CMD="mpv --fullscreen --no-keepaspect --no-keepaspect-window \"\$($STREAM_CMD)\""

echo "Launching player: $FINAL_STREAM_CMD"
eval "$FINAL_STREAM_CMD"

if [ $? -ne 0 ]; then
echo "Error: Failed to extract stream URL or MPV failed to play the stream."
fi

stop_tor # Stop Tor after streaming is complete

# ======================================================================
# --- QUICK VIEW DOWNLOAD LOGIC ([p] option) ---
# ======================================================================
elif [[ "$requested_action" == "download" ]]; then
echo "Starting download/play/delete cycle..."

# 1. Get info directly
local info
info=$(get_info_direct "$url" "$cookie_flags" "n")
local status=$?
local original_filename=""

if [ $status -eq 0 ]; then
original_filename="$info"
else
echo "Error: Could not determine original filename. Aborting URL."
stop_tor
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 (Tor: $tor_enabled) ---"

# Run the core download function, passing Tor flag and aggressive mode
run_single_download "$url" "$temp_filename" "n" "n" "$extra_options" "$cookie_flags" "$tor_enabled" "$tor_aggressive"

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

stop_tor # Stop Tor once download attempts are complete

if [ $DOWNLOAD_SUCCESS -eq 1 ]; then
# 3. Play and Delete
if [ -f "$temp_filename" ]; then
local final_video_file="$original_filename"
mv "$temp_filename" "$final_video_file"

echo "$SEPARATOR" | lolcat
echo "Launching player (mpv) for: $final_video_file"
mpv --fullscreen --no-keepaspect --no-keepaspect-window "$final_video_file"

echo "Playback session ended. Auto-deleting 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."
rm -f "${temp_filename}.part"
fi
else
echo "$SEPARATOR" | lolcat
echo "Download failed after $MAX_RETRIES attempts."
fi
fi # End of Stream/Download choice

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

# --- INPUT/COOKIE/TOR SECTION ---
local cookie_flags=""
local extra_options=""

get_user_options "cookie_flags" "extra_options"

local tor_enabled="n"
local tor_aggressive="n"
if [ "$TOR_STARTED_BY_SCRIPT" -eq 1 ] || pgrep -x "tor" > /dev/null; then
tor_enabled="y"
tor_aggressive="$TOR_AGGRESSIVE_MODE"
fi
# -------------------------------

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

# 1. Get info directly
local info
info=$(get_info_direct "$url" "$cookie_flags" "$download_audio_choice")
local status=$?
local original_filename=""

if [ $status -eq 0 ]; then
original_filename="$info"
else
echo "Error: Could not determine original filename. Aborting URL."
stop_tor
return
fi

local temp_filename="taksshack.com.mp4"

# Run the core download function in interactive mode ("y"), passing Tor flag and aggressive mode
run_single_download "$url" "$temp_filename" "$download_audio_choice" "y" "$extra_options" "$cookie_flags" "$tor_enabled" "$tor_aggressive"

# Stop Tor once download is complete
stop_tor

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

# Rename the placeholder to the actual name/extension
local final_file_name="$original_filename"
mv "$temp_filename" "$final_file_name"
temp_filename="$final_file_name" # Update the reference for cleanup

read -p "Do you want to save the file as '$final_file_name'? (y/n) " save_choice
if [[ "$save_choice" =~ ^[Yy]$ ]]; then
echo "File saved as '$final_file_name'"
else
rm "$temp_filename"
echo "File deleted."
fi
fi

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

# ----------------------------------------------------------------------
# --- Main Script Execution (FINAL MENU) ---
# ----------------------------------------------------------------------

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

echo "Please choose a single URL mode (Tor/Cookies optional for all):"
echo " [s] Standard Download: Download, Play, and Choose to Save (Interactive)"
echo " [a] Add to Queue: Download, Play, and Auto-Save URL to Playlist File"
echo " [p] Quick View: Download, Auto-Play, and Auto-Delete"
echo " [t] Live Stream: Stream directly with MPV (No Download/Save)"

echo ""
echo "Or choose a list/management mode:"
echo " [l] Process List: Download, Play, and Manage URLs from a File (Playlist Mode)"
echo " [d] Add URL: Quickly add a URL to a Playlist File (No Download)"

read -p "Your choice (s/a/p/t/l/d): " main_choice

if [[ "$main_choice" =~ ^[Ll]$ ]]; then
download_and_play_playlist
elif [[ "$main_choice" =~ ^[Aa]$ ]]; then
download_play_and_add_to_playlist
elif [[ "$main_choice" =~ ^[Pp]$ ]]; then
hybrid_stream_loop "download"
elif [[ "$main_choice" =~ ^[Tt]$ ]]; then
hybrid_stream_loop "stream"
elif [[ "$main_choice" =~ ^[Dd]$ ]]; then
add_url_to_playlist
elif [[ "$main_choice" =~ ^[Ss]$ ]]; then
single_download_and_save
fi
  • This reply was modified 3 weeks ago by thumbtak. Reason: Fixed option A
  • This reply was modified 3 weeks ago by thumbtak. Reason: Tor Option added
  • This reply was modified 3 weeks ago by thumbtak. Reason: Stream option added and improved tor network video quality, by adding a new option
  • This reply was modified 3 weeks ago by thumbtak. Reason: Improved menu structure
TAKs Shack
Wishing you and yours a very happy Thanksgiving!
This is default text for notification bar