2 # Usage: get_ytpljson.sh arg1 arg2
3 # Input: posargs: arg1: YouTube playlist ID
5 # Output: file: JSON file
10 yell
() { echo "$0: $*" >&2; } # print script path and all args to stderr
11 die
() { yell
"$*"; exit 111; } # same as yell() but non-zero exit status
12 must
() { "$@" || die
"cannot $*"; } # runs args as command, reports args if command fails
14 # Input: arg1: YouTube playlist ID
15 # arg2: Google API key
16 # arg3: pageToken (optional)
17 # Output: stdout: JSON response from googleapis.com
18 # Depends: curl 7.81.0
21 local PLAYLIST_ID API_KEY PAGE_TOKEN URL
;
23 # Set the playlist ID and API key
29 if [[ $# -lt 2 ]]; then die
"FATAL:Incorrect arg count:$#"; fi;
32 URL
="https://www.googleapis.com/youtube/v3/playlistItems?part=snippet";
35 URL
="$URL""&playlistId=""$PLAYLIST_ID";
38 URL
="$URL""&key=""$API_KEY";
40 # Append page token if it exists
41 if [[ -n "$PAGE_TOKEN" ]]; then
42 URL
="$URL""&pageToken=""$PAGE_TOKEN";
46 #curl -s "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=$PLAYLIST_ID&key=$API_KEY"; # example
48 }; # Stdout: JSON from YouTube v3 API
50 # Input: arg1: json string
53 # Checks if key ".nextPageToken" present
54 if jq
-e '.nextPageToken' < <(printf "%s" "$1") 1>/dev
/random
2>&1; then
60 }; # returns true if '.nextPageToken' present
62 # Input: arg1: json string containing the key 'nextPageToken'
63 # Output: stdout: the value of the first 'nextPageToken' key
64 # exit code: 0: key '.nextPageToken' detected
65 # 1: key '.nextPageToken' not detected
68 if [[ $# -ne 1 ]]; then die
"Incorrect arg count:$#"; fi;
70 if jq
-e '.nextPageToken' < <(printf "%s" "$1") 1>/dev
/random
2>&1; then
71 output
="$(jq -r '.nextPageToken' < <(printf "%s
" "$1") | head -n1)";
72 printf "%s" "$output";
77 }; # stdout: value from key "pageToken"
80 # Depends: bash 5.1.16, GNU Coreutils 8.32 (date)
82 # Ref/Attrib: [1]: "Obtaining authorization credentials" https://developers.google.com/youtube/registering_an_application
83 # [2]: "Implementation: Playlists" https://developers.google.com/youtube/v3/guides/implementation/playlists
84 # [3]: "Implementation: Pagination", https://developers.google.com/youtube/v3/guides/implementation/pagination
90 if [[ $# -ne 2 ]]; then die
"FATAL:Incorrect number of args:$#"; fi;
92 # Set the playlist ID and API key
93 playlistId
="$1"; # See ref [2]
94 apiKey
="$2"; # See ref [1]
96 # Set dynamic variables according to environment
97 out_dir
="$(pwd)"; # output to present working directory
98 out_filename
="$(date +%Y%m%dT%H%M%S%z)"_
"$playlistId"..playlist_items.json
;
99 out_path
="$out_dir"/"$out_filename";
101 # Make initial curl request to the YouTube Data API
102 response
="$(get_response "$playlistId" "$apiKey")";
105 # if check_next_page "$response"; then
106 # yell "DEBUG:nextPageToken detected";
109 # Make follow-up requests. See ref [3]
111 while check_next_page
"$response"; do
112 # Get page token from response
113 pageToken
="$(get_next_page "$response")";
115 response
="$(get_response "$playlistId" "$apiKey" "$pageToken")";
117 out_list
+=("$response");
120 if [[ $n -gt $max_api_calls ]]; then die
"FATAL:Too many API calls:$n"; fi;
125 printf "%s\n" "${out_list[@]}" > "$out_path";
128 yell
"STATUS:Performed $n API calls."
129 out_lc
="$(printf "%s
\n" "${out_list[@]}" | wc -l)";
130 yell
"STATUS:Wrote $out_lc lines to $out_path";
132 # Use jq to extract the publishedAt field for each playlist item
133 #PUBLISHED_AT=$(echo "$response" | jq -r '.items[].snippet.publishedAt')
139 # Author: Steven Baltakatei Sandoval