Add files.

This commit is contained in:
Jaidyn Ann 2016-12-11 19:33:57 -06:00
parent f023dc11aa
commit edc7430360
5 changed files with 538 additions and 2 deletions

View File

@ -1,2 +1,78 @@
#Shelltube
Full-featured POSIX shell YouTube client.
Shelltube is a collection of (pretty POSIX) shell scripts to
browse YouTube quickly, efficiently, and without the bloat
most command-line clients require.
Shelltube is written in pure shell; its only dependencies
are any modern shell (pdksh, bash, zsh), curl/wget, and
vlc/mplayer/kaffeine.
Even these dependencies, though, can easily be changed. If,
for example, you don't have vlc, you can just modify a
single line and be good-to-go using another player.
Also, Shelltube doesn't use the YouTube API at all. This
avoids the annoying red-tapey stuff that goes with it-- IDs,
registration, quotas-- but has some disadvantages. We'll
power through the downsides, though! :)
USAGE:
-------
Shelltube is quite simple to use; this tutorial will go over
the usage of the wrapper script, shelltube.sh.
When running the script, you'll see a prompt:
>>
In this prompt you can type any of the following commands:
(!) about View the about page.
(cls) clear Clear the screen.
(dl) download [URL] Download the selected/specified video.
exit Exit Shelltube.
(?) help Display this message.
(md) metadata [URL] Display selected/specified video's MD.
(/) search {term} Perform a search.
(str) stream [URL] Stream the selected/specified video.
(sel) video {URL} Select video based on URL or ID.
In (parenthesis), smaller aliases for the commands are written.
In {curly brackets}, required arguments are written.
In [brackets], optional arguments are written.
You can use Shelltube in one of two ways (or both):
A) By selecting a video and then doing something with it
B) By doing something and specifying the video
Method A entails using either the "video" or "search" command
to select a video, which will then be displayed before the prompt
like so:
$VIDEO_ID_HERE >>
When a video is selected, you use the "download", "stream", or
"metadata" commands without arguments to act on the video.
Method B entails just using the "download", "stream", or
"metadata" commands while using a URL or video ID as an argument.
For example:
>> download $VIDEO_ID_HERE
You could opt to not use this interactive wrapper script and instead
just use the yt-down.sh, yt-search.sh, and yt-metadata.sh scripts
on their own.
They are each pretty simple, and you can read their USAGE messages
at the top of each script.
LICENSING:
-----------
All of ST is released under the ISC license
(https://opensource.org/licenses/ISC)
except for the yt-down.sh script, which is released under the GPLv2
(https://www.gnu.org/licenses/gpl-2.0.html)
CREDIT:
--------
jadedctrl wrote most of ST, but iluaster wrote almost all of
yt-down.sh

127
shelltube.sh Normal file
View File

@ -0,0 +1,127 @@
####################
# Name: shelltube.sh
# Date: 2016-12-11
# Lisc: ISC
# Main: jadedctrl
# Desc: Full-shell YT client that
# avoids the YT API.
#####################
function search() {
output="/tmp/yt-search-$RANDOM"
sh yt-search.sh -i "$1" $output
selected_video=$(cat $output)
metadata
}
function interactive() {
get_input
}
function about() {
echo -e "\033[0;35mShelltube v0.3"
echo -e "\033[0;32mDesc: \033[0;34mYT client written in shell."
echo -e "\033[0;32mMain: \033[0;34mjadedml@openmailbox.org"
echo -e "\033[0;32mLisc: \033[0;34mISC; yt-down.sh & yt-stream.sh GPLv2\033[0m"
}
function metadata() {
sh yt-meta.sh "$selected_video"
}
function download() {
sh yt-down.sh "$selected_video"
}
function stream() {
sh yt-down.sh -s "$selected_video"
}
function get_input() {
printf "\033[0;34m$selected_video \033[0;32m>>\033[0m "
read -r n
if [ "$n" == "help" ] || [ "$n" == "?" ]
then
help
interactive
elif echo "$n" | grep "^search " > /dev/null
then
search "$(echo "$n" | sed 's/search //')"
interactive
elif echo "$n" | grep "^/" > /dev/null
then
search "$(echo "$n" | sed 's^/^^')"
interactive
elif echo "$n" | grep "^/ " > /dev/null
then
search "$(echo "$n" | sed 's^/ ^^')"
interactive
elif echo "$n" | grep "^video " > /dev/null
then
if echo "$n" | grep "youtube.com"
then
selected_video="$(echo "$n" | sed 's/.*watch?v=//')"
else
selected_video="$(echo "$n" | sed 's/sel //')"
fi
metadata
interactive
elif echo "$n" | grep "^sel " > /dev/null
then
if echo "$n" | grep "youtube.com"
then
selected_video="$(echo "$n" | sed 's/.*watch?v=//')"
else
selected_video="$(echo "$n" | sed 's/sel //')"
fi
metadata
interactive
elif [ "$n" == "download" ] || [ "$n" == "dl" ]
then
download
interactive
elif [ "$n" == "metadata" ] || [ "$n" == "md" ]
then
metadata
interactive
elif [ "$n" == "stream" ] || [ "$n" == "str" ]
then
stream
interactive
elif [ "$n" == "about" ] || [ "$n" == "!" ]
then
about
interactive
elif [ "$n" == "clear" ] || [ "$n" == "cls" ]
then
clear
interactive
elif [ "$n" == "exit" ]
then
rm /tmp/yt-*
exit
else
get_input
fi
}
function help() {
echo "about | ! View the about page."
echo "clear | cls Clear the screen."
echo "download | dl Download the selected video."
echo "exit | ctrl+c Exit Shelltube."
echo "help | ? Display this message."
echo "metadata | md Display selected video's metadata."
echo "search | / Perform a search."
echo "stream | str Stream the selected video."
echo "video | sel Select video based on URL or ID."
echo "Note about usage:"
echo "Both 'video ID; download' and 'download ID' are valid."
echo "You don't need to select a video to run commands on it,"
echo "but if you use metadata, download, or stream on an"
echo "unselected video you must specify the ID or URL after the"
echo "command."
}
echo -e "\033[0;35mShelltube v0.3"
interactive

129
yt-down.sh Normal file
View File

@ -0,0 +1,129 @@
#!/bin/sh
#####################
# Name: yt-download.sh
# Date: 2016-12-10
# Lisc: GPLv2
# Auth: iluaster
# Main: jadedctrl
# Desc: Fetches YT videos.
#####################
# Based on https://github.com/iluaster/Youtube_downloader
# Usage: yt-download.sh $video_id
if [ "$1" == "-s" ]
then
stream_mode=1
id=$2
else
stream_mode=0
id=$1
fi
if echo "$id" | grep "youtube.com"
then
id="$(echo $id | sed 's/.*video_id=//')"
elif [ -z $id ]
then
echo "No video specified."
exit 1
else
id="$id"
fi
name="http://www.youtube.com/get_video_info?video_id=$id"
declare -i line=0
function select_option ()
{
echo "Formats:"
for i in $(cat /tmp/video_type_option.txt)
do
line=$((line+1))
echo "${line}. $i"
done
printf "\033[0;32m>>\033[0m "
read -r n
if [ "$n" -le "$line" ];
then
head -n "$n" /tmp/tmp3.txt | tail -n 1 > /tmp/tmp4.txt
else
echo "Input Error!"
line=0
select_option
fi
}
if type "wget" &> /dev/null
then
wget -q "$name" -O "/tmp/${id}_url.txt"
elif type "curl" &> /dev/null
then
curl -s "$name" -o "/tmp/${id}_url.txt"
else
echo "Please install wget or curl."
exit 1
fi
# Cut and filter mp4 url
cp "/tmp/${id}_url.txt" /tmp/tmp2.txt
sed -e 's/&/\n/g' /tmp/tmp2.txt| grep 'url_encoded_fmt_stream_map'> /tmp/tmp3.txt
sed -i -e 's/%2C/,/g' /tmp/tmp3.txt
sed -i -e 's/,/\n/g' /tmp/tmp3.txt
# Print out total video format name and quality
perl -ne 'print "$2,$1\n" if /quality%3D(.*?)%.*video%252F(.*?)(%|\n)/' /tmp/tmp3.txt > /tmp/video_type_option.txt
# If video format name is prior to quality
perl -ne 'print "$1,$2\n" if /video%252F(.*?)%.*quality%3D(.*?)(%|\n)/' /tmp/tmp3.txt >> /tmp/video_type_option.txt
sed -i -e 's/x-flv/flv/g' /tmp/video_type_option.txt
select_option
# Set file extension name variable and video quality variable
extension_name=$(head -n "$n" /tmp/video_type_option.txt | tail -n 1 | cut -d "," -f 1)
quality_name=$(head -n "$n" /tmp/video_type_option.txt | tail -n 1 | cut -d "," -f 2)
sed -i -e 's/%26/\&/g' /tmp/tmp4.txt
sed -i -e 's/&/\n/g' /tmp/tmp4.txt
grep 'http' /tmp/tmp4.txt > /tmp/tmp5.txt
grep 'sig%3D' /tmp/tmp4.txt >> /tmp/tmp5.txt
perl -pe 's/\n//g' /tmp/tmp5.txt | sed -e 's/sig%3D/\&signature%3D/g' > /tmp/tmp6.txt
sed -i -e 's/url%3D//g' /tmp/tmp6.txt
# url decoding
cat /tmp/tmp6.txt | sed -e 's/%25/%/g' -e 's/%25/%/g' -e 's/%3A/:/g' -e 's/%2F/\//g' -e 's/%3F/\?/g' -e 's/%3D/=/g' -e 's/%26/\&/g' > /tmp/tmp7.txt
if [ $stream_mode -eq 1 ]
then
if type "vlc" &> /dev/null
then
vlc $(cat /tmp/tmp7.txt)
elif type "mplayer" &> /dev/null
then
mplayer $(cat /tmp/tmp7.txt)
elif type "kaffeine" &> /dev/null
then
kaffeine $(cat /tmp/tmp7.txt)
else
echo "Please install either vlc, mplayer, or kaffeine."
exit 1
fi
else
if type "wget" &> /dev/null
then
wget --show-progress -qi /tmp/tmp7.txt -O "${id_name}_${quality_name}.${extension_name}"
elif type "curl" &> /dev/null
then
curl -# $(cat /tmp/tmp7.txt) -o "${id_name}_${quality_name}.${extension_name}"
else
echo "Please install wget or curl."
exit 1
fi
fi
rm -f /tmp/tmp[2-7].txt /tmp/${id}_url.txt /tmp/video_type_option.txt

42
yt-meta.sh Normal file
View File

@ -0,0 +1,42 @@
#####################
# Name: yt-meta.sh
# Date: 2016-12-10
# Lisc: ISC
# Main: jadedctrl
# Desc: Fetches metadata about
# a specific YT video.
#####################
# Usage: yt-meta.sh $video_id
if echo "$1" | grep "youtube.com"
then
id="$(echo $1 | sed 's/.*video_id=//')"
elif [ -z $1 ]
then
"No video specified."
exit 1
else
id="$1"
fi
video_file="/tmp/yt-video_$RANDOM"
if type "wget" &> /dev/null
then
wget -q https://youtube.com/watch?v=$id -O $video_file
wget -q https://youtube.com/results?search_query=$id -O $video_file.1
elif type "curl" &> /dev/null
then
curl -s https://youtube.com/watch?v=$id -o $video_file
curl -s https://youtube.com/results?search_query=$id -o $video_file.1
fi
# Now for displaying the metadata
title="$(grep "\"title\":\"" $video_file | sed 's/.*"title":"//' | sed 's/".*//')"
author="$(grep "\"author\":\"" $video_file | sed 's/.*"author":"//' | sed 's/".*//')"
views="$(grep "\"view_count\":\"" $video_file | sed 's/.*"view_count":"//' | sed 's/".*//')"
duration="$(grep "<a href=\"/watch?v=$1" $video_file.1 | sed 's/.*Duration: //' | sed 's/\..*//')"
date="$(grep "datePublished" $video_file | sed 's/.*"datePublished" content="//' | sed 's/".*//')"
echo "$title"
echo "$author | $views | $duration | $date | $1"

162
yt-search.sh Normal file
View File

@ -0,0 +1,162 @@
#####################
# Name: yt-result.sh
# Date: 2016-12-10
# Lisc: ISC
# Main: jadedctrl
# Desc: Search YT videos and display
# in easy-to-read and easy-to
# -parse results
#####################
# Usage: yt-search.sh "$search_string"
# Bloody input...
row=0
if [ "$1" == "-i" ]
then
interactive_mode=1
query="$(echo "$2" | sed 's/ /+/g')"
output="$3"
else
query="$(echo "$arg" | sed 's/ /+/g')"
fi
function get_input() {
printf "\033[0;32m>>>\033[0m "
read -r n
if [ "$n" == "exit" ]
then
exit
fi
test $n -ge 0 &> /dev/null
if [ $? -gt 1 ]
then
echo "Bad input, mate. Type in a valid number or 'exit'."
get_input
elif [ $n -gt 20 ]
then
echo "Out of range. Type in a valid number or 'exit'."
get_input
elif [ $n -gt 0 ] && [ $n -lt 20 ]
then
sed -n ${n}p $temp_file | sed 's/.*<a href="\/watch?v=//' | sed 's/".*//' > $output
else
echo "Bad input, mate. Type in a valid number or 'exit'."
get_input
fi
}
# If Google adds any extra features or changes the webpage
# layout, this script'll break immediately, haha.
# ... But at least we aren't using their API, right?
search_file="/tmp/yt-search_$RANDOM"
if type "wget" &> /dev/null
then
wget -q https://youtube.com/results?search_query=$query -O $search_file
elif type "curl" &> /dev/null
then
curl -s https://youtube.com/results?search_query=$query -o $search_file
fi
# Now for displaying the search results
temp_file="/tmp/yt-result_$RANDOM"
grep "<a href=\"\/watch?v=" $search_file | grep -v "<span class=\"yt-thumb-simple\"" > $temp_file
item_num=0
cat $temp_file | while IFS='' read -r CUR_LINE
do
item_num=$(($item_num+1))
# These tags trip up 'title=' and '" >' queries later on. Strip 'em.
LINE="$(echo $CUR_LINE | sed 's/<span class=\"yt-badge \" >.*//')"
LINE="$(echo $LINE | sed 's/views<\/li>.*//')"
LINE="$(echo $LINE | sed 's/title="Verified"//')"
if [ $row -eq 1 ]
then
color='\033[1;34m'
color2='\033[1;34m'
row=0
elif [ $row -eq 0 ]
then
color='\033[1;31m'
color2='\033[1;31m'
row=1
fi
if echo "$LINE" | grep "View full playlist" > /dev/null
then
type="Playlist"
if [ $interactive_mode -eq 1 ]
then
printf "${color}$item_num. "
fi
title=$(echo "$LINE" | sed 's/.*title="//' | sed 's/".*//')
items=$(echo "$LINE" | sed 's/.*View full playlist (//' | sed 's/).*//')
echo -e "${color}$title"
echo -e "${color2}$type | $items | $itemid"
else
type="Video"
duration=$(echo "$LINE" | sed 's/.*Duration: //' | sed 's/\..*//')
itemid=$(echo "$LINE" | sed 's/.*<a href="\/watch?v=//' | sed 's/".*//')
title=$(echo "$LINE" | sed 's/.* title="//' | sed 's/".*//')
if echo "$LINE" | grep /channel/ > /dev/null
then
# For /channel/ users
author=$(echo "$LINE" | sed 's/.*" >//' | sed 's/<\/a>.*//')
else
# For /user/ users
author=$(echo "$LINE" | sed 's/.*\/user\///' | sed 's/".*//')
fi
if [ $interactive_mode -eq 1 ]
then
if [ $item_num -lt 10 ]
then
printf "${color}$item_num. "
else
printf "${color}$item_num. "
fi
echo -e "${color}$title${color2}"
printf " "
fi
i=0
while [ $i -lt 16 ]
do
i=$((i+1))
char=$(echo $author | cut -c$i)
if [ -z $char ]
then
printf " "
else
printf "$char"
fi
done
printf " | "
i=0
while [ $i -lt 5 ]
do
i=$((i+1))
char=$(echo $duration | cut -c$i)
if [ -z $char ]
then
printf " "
else
printf "$char"
fi
done
printf " | $itemid\n"
fi
done
if [ $interactive_mode -eq 1 ]
then
get_input
fi
rm $temp_file