Last active
November 18, 2018 09:53
-
-
Save GoesuZuegs/45c8da1e8f14c2187cb59e827ae1bf2e to your computer and use it in GitHub Desktop.
YouTube in the terminal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
if [ $EUID -ne 0 ] | |
then | |
echo "This script must be run as root!" | |
exit 1 | |
fi | |
INSTALL_DIR=/opt/ytgo/ | |
mkdir -p $INSTALL_DIR | |
cd $INSTALL_DIR | |
curl -L https://gist.github.com/GoesuZuegs/45c8da1e8f14c2187cb59e827ae1bf2e/raw/ytgo.sh > ytgo | |
chmod +x ytgo | |
if ! [[ "$PATH" =~ (^|:)"${INSTALL_DIR}"(:|$) ]] | |
then | |
echo -e "\n" >> /etc/profile | |
echo $"export PATH=\$PATH:${INSTALL_DIR}" >> /etc/profile | |
source /etc/profile | |
fi | |
# yay -Syu html-xml-utils | |
echo "The script was sucessfully installed!" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# YouTube in the terminal | |
VIDEOS_FOLDER=~/Videos/ | |
MUSIC_FOLDER=~/Music/ | |
youtube_audio () { | |
if [ -z "$1" ] | |
then | |
exit 1 | |
fi | |
tmpdir=$( mktemp -d ) | |
youtube-dl --no-check-certificate --no-playlist --format bestaudio --extract-audio --audio-format mp3 --o "$tmpdir/%(title)s.%(id)s.%(ext)s" "$1" | |
( cd "$tmpdir" && find . -name \*.mp3 -exec mv "{}" "$MUSIC_FOLDER" \; ) | |
rm -rf "$tmpdir" | |
echo -e "\n" | |
} | |
if [ "$1" = audio ] | |
then | |
youtube_audio "$2" | |
fi | |
youtube_video () { | |
if [ -z "$1" ] | |
then | |
exit 1 | |
fi | |
tmpdir=$( mktemp -d ) | |
youtube-dl --no-check-certificate --no-playlist --recode-video mkv --o "$tmpdir/%(title)s.%(id)s.%(ext)s" "$1" | |
( cd "$tmpdir" && find . -name \*.mkv -exec mv "{}" "$VIDEOS_FOLDER" \; ) | |
rm -rf "$tmpdir" | |
echo -e "\n" | |
} | |
if [ "$1" = video ] | |
then | |
youtube_video "$2" | |
fi | |
youtube_playlist () { | |
if [ -z "$2" ] | |
then | |
echo -e "No URL given!\n" | |
exit 1 | |
fi | |
if [ -n "$1" ] | |
then | |
mode="$1" | |
else | |
read -rp "Mode [v = video | a = audio]: " -n 1 mode | |
fi | |
if [ "$mode" = v ] | |
then | |
tmpdir=$( mktemp -d ) | |
youtube-dl --no-check-certificate --yes-playlist --recode-video mkv --o "$tmpdir/%(playlist_title)s %(playlist_id)s/%(playlist_index)s %(title)s.%(id)s.%(ext)s" "$2" | |
( cd "$tmpdir" && find . -name \*.mkv -exec mv "{}" "$VIDEOS_FOLDER" \; ) | |
rm -rf "$tmpdir" | |
elif [ "$mode" = a ] | |
then | |
tmpdir=$( mktemp -d ) | |
youtube-dl --no-check-certificate --yes-playlist --format bestaudio --extract-audio --audio-format mp3 --o "$tmpdir/%(playlist_title)s %(playlist_id)s/%(playlist_index)s %(title)s.%(id)s.%(ext)s" "$2" | |
( cd "$tmpdir" && find . -name \*.mp3 -exec mv "{}" "$MUSIC_FOLDER" \; ) | |
rm -rf "$tmpdir" | |
else | |
echo -e "Invalid mode!\n" | |
exit 1 | |
fi | |
echo -e "\n" | |
exit 0 | |
} | |
if [ "$1" = playlist ] | |
then | |
youtube_playlist "$2" | |
fi | |
youtube_search_handle_result () { | |
kind="$1" | |
if [ -z "$kind" ] | |
then | |
echo -e "No kind given!\n" | |
exit 1 | |
fi | |
url="$2" | |
if [ -z "$url" ] | |
then | |
echo -e "No URL given!\n" | |
exit 1 | |
fi | |
if [ "$kind" = video ] | |
then | |
read -rp "Mode [a = audio | s = stream | v = video | b = both | f = firefox]: " -n 1 mode | |
echo -e "\n" | |
if [ "$mode" = a ] | |
then | |
youtube_audio "$url" | |
read -rp "Play now? (y/n) " -n 1 play_now | |
echo -e "\n" | |
if [ "$play_now" = y ] | |
then | |
audio_file=$( find $MUSIC_FOLDER -name *.$3.mp3 -print -quit ) | |
mpv "$audio_file" | |
exit 0 | |
fi | |
elif [ "$mode" = s ] | |
then | |
mpv "$url" | |
elif [ "$mode" = v ] | |
then | |
youtube_video "$url" | |
read -rp "Play now? (y/n) " -n 1 play_now | |
echo -e "\n" | |
if [ "$play_now" = y ] | |
then | |
video_file=$( find $VIDEOS_FOLDER -name *.$3.mkv -print -quit ) | |
mpv "$video_file" | |
exit 0 | |
fi | |
elif [ "$mode" = b ] | |
then | |
youtube_audio "$url" | |
youtube_video "$url" | |
elif [ "$mode" = f ] | |
then | |
(firefox "$url" &) | |
else | |
echo -e "Invalid mode!\n" | |
exit 1 | |
fi | |
elif [ "$kind" = playlist ] | |
then | |
read -rp "Mode [f = firefox | v = video | a = audio]: " -n 1 mode | |
echo -e "\n" | |
if [ "$mode" = f ] | |
then | |
(firefox "$url" &) | |
elif [ "$mode" = v ] | |
then | |
youtube_playlist v "$url" | |
elif [ "$mode" = a ] | |
then | |
youtube_playlist a "$url" | |
else | |
echo -e "Invalid mode!\n" | |
exit 1 | |
fi | |
elif [ "$kind" = channel ] | |
then | |
read -rp "Mode [f = firefox]: " -n 1 mode | |
echo -e "\n" | |
if [ "$mode" = f ] | |
then | |
(firefox "$url" &) | |
else | |
echo -e "Invalid mode!\n" | |
exit 1 | |
fi | |
else | |
echo -e "Invalid kind!\n" | |
exit 1 | |
fi | |
exit 0 | |
} | |
# https://www.w3.org/Tools/HTML-XML-utils/ | |
youtube_search () { | |
echo -e "\nSearching on YouTube...\n" | |
page=$( curl -s -G \ | |
--data-urlencode "search_query=$1" \ | |
"https://www.youtube.com/results" \ | |
) | |
tmpfile=$( mktemp ) | |
echo "$page" > "$tmpfile" | |
normalized=$( hxnormalize -l 64 -x "$tmpfile" ) | |
rm "$tmpfile" | |
num_results=$( echo "$normalized" | hxselect -c ".num-results" ) | |
echo -e "There are ${num_results,,}\n" | |
tmpfile=$( mktemp ) | |
echo "$normalized" | hxselect \ | |
"#results ol.item-section > li > .yt-lockup" \ | |
> "$tmpfile" | |
items=$( hxnormalize -x "$tmpfile" ) | |
rm "$tmpfile" | |
declare -a kinds | |
declare -a urls | |
declare -a ids | |
for c in `seq 1 5`; | |
do | |
tmpfile=$( mktemp ) | |
echo "$items" | hxselect "body > :nth-child($c)" > "$tmpfile" | |
item=$( hxnormalize -l 256 -x "$tmpfile" ) | |
rm "$tmpfile" | |
kind="" | |
classes=$( echo "$item" | hxselect -c "body > div::attr(class)" ) | |
if [[ "$classes" = *"yt-lockup-video"* ]] | |
then | |
kind="video" | |
elif [[ "$classes" = *"yt-lockup-playlist"* ]] | |
then | |
kind="playlist" | |
elif [[ "$classes" = *"yt-lockup-channel"* ]] | |
then | |
kind="channel" | |
fi | |
if [ -z "$kind" ] | |
then | |
continue | |
fi | |
kinds[$c]="$kind" | |
urls[$c]=$( echo "$item" | hxselect -c ".yt-lockup-title a::attr(href)" ) | |
title=$( echo "$item" | hxselect -c ".yt-lockup-title a::attr(title)" ) | |
title=${title//[^[:ascii:]]/} | |
title=$( echo "$title" | recode html..utf-8 ) | |
if [ "$kind" = "video" ] || [ "$kind" = "playlist" ] | |
then | |
by=$( echo "$item" | hxselect -c ".yt-lockup-byline a" ) | |
verified=$( echo "$item" | hxselect -c ".yt-lockup-byline span::attr(title)" ) | |
elif [ "$kind" = "channel" ] | |
then | |
verified=$( echo "$item" | hxselect -c ".yt-lockup-title > a > span::attr(title)" ) | |
fi | |
if [ "$verified" = "Verified" ] | |
then | |
verified=" \e[95m[V]\e[0m" | |
else | |
verified="" | |
fi | |
if [ "$kind" = "video" ] | |
then | |
ids[$c]=$( echo "$item" | hxselect -c ".yt-lockup-video::attr(data-context-item-id)" ) | |
when=$( echo "$item" | hxselect -c ".yt-lockup-meta-info > :first-child" ) | |
when=${when,,} | |
num_views=$( echo "$item" | hxselect -c ".yt-lockup-meta-info > :last-child" ) | |
num_views="${num_views% views}" | |
duration=$( echo "$item" | hxselect -c ".video-time" ) | |
echo -e "\e[4m$c.\e[0m \e[93m${title}\e[0m\n Video by \e[96m${by}\e[0m${verified} ${when} \e[96m${num_views}\e[0m views ${duration}" | |
elif [ "$kind" = "playlist" ] | |
then | |
ids[$c]=$( echo "$item" | hxselect -c "li[data-action=play-now]::attr(data-list-id)" ) | |
by=$( echo "$item" | hxselect -c ".yt-lockup-byline a" ) | |
if [ -z "$by" ] | |
then | |
by="YouTube" | |
fi | |
num_videos=$( echo "$item" | hxselect -c ".formatted-video-count-label > b" ) | |
echo -e "\e[4m$c.\e[0m \e[93m${title}\e[0m\n Playlist by \e[96m${by}\e[0m${verified} with \e[96m${num_videos}\e[0m videos" | |
elif [ "$kind" = "channel" ] | |
then | |
ids[$c]=$( echo "$item" | hxselect -c "button[data-channel-external-id]::attr(data-channel-external-id)" ) | |
num_videos=$( echo "$item" | hxselect -c ".yt-lockup-meta-info > :first-child" ) | |
num_videos="${num_videos% videos}" | |
num_subscribers=$( echo "$item" | hxselect -c ".yt-subscriber-count::attr(title)" ) | |
echo -e "\e[4m$c.\e[0m \e[93m${title}\e[0m\n Channel${verified} with \e[96m${num_videos}\e[0m videos and \e[96m${num_subscribers}\e[0m subscribers" | |
fi | |
echo -e "\n" | |
done | |
read -rp "Choose [1 - 5]: " -n 1 choice | |
echo -e "\n" | |
if [ -n "$choice" ] && [ $choice -gt 0 ] && [ $choice -lt 6 ] | |
then | |
if [ -n "${ids[$choice]}" ] | |
then | |
if [ "${kinds[$choice]}" = video ] | |
then | |
url="https://www.youtube.com/watch?v=${ids[$choice]}" | |
elif [ "${kinds[$choice]}" = playlist ] | |
then | |
url="https://www.youtube.com/playlist?list=${ids[$choice]}" | |
elif [ "${kinds[$choice]}" = channel ] | |
then | |
url="https://www.youtube.com/channel/${ids[$choice]}/" | |
fi | |
else | |
url="https://www.youtube.com${urls[$choice]}" | |
fi | |
echo -e "${kinds[$choice]^}: ${ids[$choice]}\n\n${url}\n" | |
youtube_search_handle_result "${kinds[$choice]}" "$url" "${ids[$choice]}" | |
fi | |
unset urls | |
} | |
if [ "$1" = search ] || [ "$1" = s ] | |
then | |
if [ -n "$2" ] | |
then | |
youtube_search "$2" | |
else | |
read -erp "Query: " -n 64 query | |
youtube_search "$query" | |
fi | |
fi | |
if [ $# -eq 0 ] || [ "$1" = help ] ; then | |
echo "Usage:" | |
echo "s | search = Seach youtube" | |
echo "video [URL] = Download video" | |
echo "audio [URL] = Download audio" | |
echo "playlist [URL] = Download playlist" | |
echo "You need 'html-xml-utils', 'youtube-dl', 'recode' and 'mpv' from the AUR for this to work." | |
echo "Install with: yay -Syu html-xml-utils youtube-dl recode mpv" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment