mirror of
https://github.com/iv-org/youtube-utils.git
synced 2024-10-01 03:45:35 -04:00
Add a basic YT API utility script
(made in bash) This utility script is intended for research on the innertube API so the developper can query the API without having to compile invidious nor need to copy-paste the same commands over and over.
This commit is contained in:
parent
6931797a9f
commit
b51609a2df
337
scripts/yt-api-helper.sh
Executable file
337
scripts/yt-api-helper.sh
Executable file
@ -0,0 +1,337 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
|
||||||
|
|
||||||
|
print_help()
|
||||||
|
{
|
||||||
|
echo "Usage: yt-api-helper -i [-c <client>] [-e <endpoint>]"
|
||||||
|
echo "Usage: yt-api-helper -e <endpoint> -d <data>"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -c,--client Client to use. Pass 'help' to this option to get"
|
||||||
|
echo " the list of supported clients"
|
||||||
|
echo " -d,--data Raw data to send to the API"
|
||||||
|
echo " -e,--endpoint Youtube endpoint to request. Pass 'help' to this"
|
||||||
|
echo " option to get the list of supported endpoints"
|
||||||
|
echo " -h,--help Show this help"
|
||||||
|
echo " -i,--interactive Run in interactive mode"
|
||||||
|
echo " -o,--output Print output to file instead of stdout"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
print_clients()
|
||||||
|
{
|
||||||
|
echo "Available clients:"
|
||||||
|
echo "web"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_endpoints()
|
||||||
|
{
|
||||||
|
echo "Available endpoints:"
|
||||||
|
echo "browse"
|
||||||
|
echo "browse-continuation"
|
||||||
|
echo "next"
|
||||||
|
echo "next-continuation"
|
||||||
|
echo "player"
|
||||||
|
echo "resolve"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
is_arg()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
-c|--client) true;;
|
||||||
|
-d|--data) true;;
|
||||||
|
-e|--endpoint) true;;
|
||||||
|
-h|--help) true;;
|
||||||
|
-i|--interactive) true;;
|
||||||
|
-o|--output) true;;
|
||||||
|
*) false;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parameters init
|
||||||
|
#
|
||||||
|
|
||||||
|
interactive=false
|
||||||
|
|
||||||
|
client_option=""
|
||||||
|
endpoint_option=""
|
||||||
|
|
||||||
|
data=""
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Interactive client selection
|
||||||
|
#
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
# Exit if no more arguments to parse
|
||||||
|
if [ $# -eq 0 ]; then break; fi
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
-c|--client)
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ $# -eq 0 ] || $(is_arg "$1"); then
|
||||||
|
echo "Error: missing argument after -c/--client"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
client_option=$1
|
||||||
|
;;
|
||||||
|
|
||||||
|
-d|--data)
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ $# -eq 0 ] || $(is_arg "$1"); then
|
||||||
|
echo "Error: missing argument after -d/--data"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
data=$1
|
||||||
|
;;
|
||||||
|
|
||||||
|
-e|--endpoint)
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ $# -eq 0 ] || $(is_arg "$1"); then
|
||||||
|
echo "Error: missing argument after -e/--endpoint"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
endpoint_option=$1
|
||||||
|
;;
|
||||||
|
|
||||||
|
-h|--help)
|
||||||
|
print_help
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
-i|--interactive)
|
||||||
|
interactive=true
|
||||||
|
;;
|
||||||
|
|
||||||
|
-o|--output)
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ $# -eq 0 ] || $(is_arg "$1"); then
|
||||||
|
echo "Error: missing argument after -o/--output"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
output="$1"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Error: unknown argument '$1'"
|
||||||
|
return 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Input validation
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ ! -z "$data" ]; then
|
||||||
|
# Can't pass data in interactive mode
|
||||||
|
if [ $interactive = true ]; then
|
||||||
|
echo "Error: -d/--data can't be used with -i/--interactive"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Can't pass client in non-interactive mode (must be part of data)
|
||||||
|
if [ ! -z $client_option ]; then
|
||||||
|
echo "Error: -c/--client can't be used with -d/--data"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Endpoint must be given if non-interactive mode
|
||||||
|
if [ -z $endpoint_option ]; then
|
||||||
|
echo "Error: In non-interactive mode, an endpoint must be passed with -e/--endpoint"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$data" ] && [ $interactive = false ]; then
|
||||||
|
# Data must be given if non-interactive mode
|
||||||
|
echo "Error: In non-interactive mode, data must be passed with -d/--data"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$output" ] && [ $interactive = true ]; then
|
||||||
|
printf "\nIt is recommended to use --output in interactive mode.\nContinue? [y/N]: "
|
||||||
|
read confirm
|
||||||
|
|
||||||
|
if [ -z $confirm ]; then confirm="n"; fi
|
||||||
|
|
||||||
|
case $confirm in
|
||||||
|
[Yy]|[Yy][Ee][Ss]) ;;
|
||||||
|
*) return 0;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client selection
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ -z $client_option ]; then
|
||||||
|
printf "Enter a client to use [web]: "
|
||||||
|
read client_option
|
||||||
|
|
||||||
|
if [ -z $client_option ]; then client_option="web"; fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $client_option in
|
||||||
|
help)
|
||||||
|
print_clients
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
web)
|
||||||
|
apikey="AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"
|
||||||
|
client_name="WEB"
|
||||||
|
client_vers="2.20210330.08.00"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Error: Unknown client '$client_option'"
|
||||||
|
echo ""
|
||||||
|
print_clients
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Endpoint selection
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ -z $endpoint_option ]; then
|
||||||
|
printf "Enter an endpoint to request []: "
|
||||||
|
read endpoint_option
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $endpoint_option in
|
||||||
|
help)
|
||||||
|
print_endpoints
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
browse)
|
||||||
|
endpoint="youtubei/v1/browse"
|
||||||
|
|
||||||
|
if [ $interactive = true ]; then
|
||||||
|
printf "Enter browse ID [UCXuqSBlHAE6Xw-yeJA0Tunw]: "
|
||||||
|
read browse_id
|
||||||
|
|
||||||
|
if [ -z $browse_id ]; then browse_id="UCXuqSBlHAE6Xw-yeJA0Tunw"; fi
|
||||||
|
partial_data="\"browseId\":\"${browse_id}\""
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
browse-cont*|browse-tok*)
|
||||||
|
endpoint="youtubei/v1/browse"
|
||||||
|
|
||||||
|
if [ $interactive = true ]; then
|
||||||
|
printf "Enter continuation token []: "
|
||||||
|
read token
|
||||||
|
|
||||||
|
if [ -z $toekn ]; then echo "Error: token required"; return 1; fi
|
||||||
|
partial_data="\"continuation\":\"${token}\""
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
player|next)
|
||||||
|
endpoint="youtubei/v1/$endpoint_option"
|
||||||
|
|
||||||
|
if [ $interactive = true ]; then
|
||||||
|
printf "Enter video ID [dQw4w9WgXcQ]: "
|
||||||
|
read vid
|
||||||
|
|
||||||
|
if [ -z $vid ]; then vid="dQw4w9WgXcQ"; fi
|
||||||
|
partial_data="\"videoId\":\"${vid}\""
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
next-cont*|next-tok*)
|
||||||
|
endpoint="youtubei/v1/next"
|
||||||
|
|
||||||
|
if [ $interactive = true ]; then
|
||||||
|
printf "Enter continuation token []: "
|
||||||
|
read token
|
||||||
|
|
||||||
|
if [ -z $toekn ]; then echo "Error: token required"; return 1; fi
|
||||||
|
partial_data="\"continuation\":\"${token}\""
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
resolve)
|
||||||
|
endpoint="navigation/resolve_url"
|
||||||
|
|
||||||
|
if [ $interactive = true ]; then
|
||||||
|
printf "Enter URL []: "
|
||||||
|
read url
|
||||||
|
|
||||||
|
if [ -z $url ]; then echo "Error: URL required"; return 1; fi
|
||||||
|
partial_data="\"url\":\"${url}\""
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Error: Unknown endpoint '$endpoint_option'"
|
||||||
|
echo ""
|
||||||
|
print_clients
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Interactive language/region selection
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ $interactive = true ]; then
|
||||||
|
printf "Enter content language (hl) [en]: "
|
||||||
|
read hl
|
||||||
|
|
||||||
|
printf "Enter content region (gl) [US]: "
|
||||||
|
read gl
|
||||||
|
|
||||||
|
if [ -z $hl ]; then hl="en"; fi
|
||||||
|
if [ -z $gl ]; then gl="US"; fi
|
||||||
|
|
||||||
|
client="\"clientName\":\"${client_name}\",\"clientVersion\":\"${client_vers}\",\"hl\":\"${hl}\",\"gl\":\"${gl}\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Final command
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ $interactive = true ]; then
|
||||||
|
data="{\"context\":{\"client\":{$client}},$partial_data}"
|
||||||
|
|
||||||
|
# Basic debug
|
||||||
|
echo "sending:"
|
||||||
|
echo "$data" | sed 's/{/{\n/g; s/}/\n}/g; s/,/,\n/g'
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
url="https://www.youtube.com/${endpoint}?key=${apikey}"
|
||||||
|
|
||||||
|
# Headers
|
||||||
|
hdr_ct='Content-Type: application/json; charset=utf-8'
|
||||||
|
hdr_ua='User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0'
|
||||||
|
|
||||||
|
# Default to STDOUT if no output file was given
|
||||||
|
if [ -z "output" ]; then output='-'; fi
|
||||||
|
|
||||||
|
# Run!
|
||||||
|
curl --compressed -o "$output" -H "$hdr_ct" -H "$hdr_ua" --data "$data" "$url"
|
Loading…
Reference in New Issue
Block a user