diff --git a/youtube-api-poking/.gitignore b/youtube-api-poking/.gitignore new file mode 100644 index 0000000..0b40a1f --- /dev/null +++ b/youtube-api-poking/.gitignore @@ -0,0 +1,4 @@ +client_id.json +.env +subscriptions.json +exchange_auth.json diff --git a/youtube-api-poking/create-grant-url b/youtube-api-poking/create-grant-url new file mode 100755 index 0000000..5a733a1 --- /dev/null +++ b/youtube-api-poking/create-grant-url @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -o errexit + +main() { + [[ "${OOM_CLIENT_ID}" ]] || { + echo "Missing \$OOM_CLIENT_ID" + exit 1 + } + + local url='https://accounts.google.com/o/oauth2/auth' + + url="${url}?client_id=${OOM_CLIENT_ID}" + url="${url}&redirect_uri=urn:ietf:wg:oauth:2.0:oob" + url="${url}&scope=https://www.googleapis.com/auth/youtube" + url="${url}&response_type=code&access_type=offline" + + echo "${url}" +} + +main "$@" diff --git a/youtube-api-poking/exchange-auth-code b/youtube-api-poking/exchange-auth-code new file mode 100755 index 0000000..c20029b --- /dev/null +++ b/youtube-api-poking/exchange-auth-code @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -o errexit + +main() { + local single_use_token="${1}" + + [[ "${single_use_token}" ]] || { + echo "Missing single use token arg" + exit 1 + } + + [[ "${OOM_CLIENT_ID}" ]] || { + echo "Missing \$OOM_CLIENT_ID" + exit 1 + } + + [[ "${OOM_CLIENT_SECRET}" ]] || { + echo "Missing \$OOM_CLIENT_SECRET" + exit 1 + } + + curl \ + -X POST \ + -sSL \ + -d "client_id=${OOM_CLIENT_ID}" \ + -d "code=${single_use_token}" \ + -d "client_secret=${OOM_CLIENT_SECRET}" \ + -d 'redirect_uri=urn:ietf:wg:oauth:2.0:oob' \ + -d 'grant_type=authorization_code' \ + 'https://accounts.google.com/o/oauth2/token' +} + +main "$@" diff --git a/youtube-api-poking/functions.bash b/youtube-api-poking/functions.bash new file mode 100644 index 0000000..09e2dfe --- /dev/null +++ b/youtube-api-poking/functions.bash @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -o errexit + +__fetch_access_token() { + local client_id="${1}" + local client_secret="${2}" + local refresh_token="${3}" + local oauth2_token_url="${4}" + : "${oauth2_token_url:=https://accounts.google.com/o/oauth2/token}" + + curl \ + -sSL \ + -X POST \ + -d "client_id=${client_id}" \ + -d "client_secret=${client_secret}" \ + -d "refresh_token=${refresh_token}" \ + -d 'grant_type=refresh_token' \ + "${oauth2_token_url}" \ + | jq -r '.access_token' +} + +__googleapis_http() { + local client_id="${1}" + shift + local client_secret="${1}" + shift + local refresh_token="${1}" + shift + local verb="${1}" + shift + local path="${1}" + shift + + local qs='' + local first=1 + + for param in "${@}"; do + if [[ "${first}" = '1' ]]; then + qs="${param}" + first=0 + continue + fi + qs="${qs}&${param}" + done + + local access_token + access_token="$( + __fetch_access_token \ + "${client_id}" \ + "${client_secret}" \ + "${refresh_token}" + )" + + local curl_opts + if [[ "${DEBUG}" ]]; then + curl_opts=-vvvv + fi + curl \ + -sSL ${curl_opts} \ + -X "${verb}" \ + -H "Authorization: Bearer ${access_token}" \ + "https://www.googleapis.com${path}?${qs}" \ + | jq . +} diff --git a/youtube-api-poking/list-channels b/youtube-api-poking/list-channels new file mode 100755 index 0000000..b523052 --- /dev/null +++ b/youtube-api-poking/list-channels @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -o errexit + +main() { + source "$(dirname "${BASH_SOURCE[0]}")/functions.bash" + + __googleapis_http \ + "${OOM_CLIENT_ID}" \ + "${OOM_CLIENT_SECRET}" \ + "${OOM_YOUTUBE_REFRESH_TOKEN}" \ + GET /youtube/v3/channels \ + part=contentDetails mine=true maxResults=50 +} + +main "$@" diff --git a/youtube-api-poking/list-playlistitems b/youtube-api-poking/list-playlistitems new file mode 100755 index 0000000..00fe456 --- /dev/null +++ b/youtube-api-poking/list-playlistitems @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -o errexit + +main() { + local playlist_id="${1}" + + source "$(dirname "${BASH_SOURCE[0]}")/functions.bash" + + __googleapis_http \ + "${OOM_CLIENT_ID}" \ + "${OOM_CLIENT_SECRET}" \ + "${OOM_YOUTUBE_REFRESH_TOKEN}" \ + GET /youtube/v3/playlistItems \ + part=snippet mine=true maxResults=50 id=${playlist_id} +} + +main "$@" diff --git a/youtube-api-poking/list-playlists b/youtube-api-poking/list-playlists new file mode 100755 index 0000000..c822c1d --- /dev/null +++ b/youtube-api-poking/list-playlists @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -o errexit + +main() { + source "$(dirname "${BASH_SOURCE[0]}")/functions.bash" + + __googleapis_http \ + "${OOM_CLIENT_ID}" \ + "${OOM_CLIENT_SECRET}" \ + "${OOM_YOUTUBE_REFRESH_TOKEN}" \ + GET /youtube/v3/playlists \ + part=contentDetails mine=true maxResults=50 +} + +main "$@" diff --git a/youtube-api-poking/list-subs b/youtube-api-poking/list-subs new file mode 100755 index 0000000..40a60c0 --- /dev/null +++ b/youtube-api-poking/list-subs @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -o errexit + +main() { + source "$(dirname "${BASH_SOURCE[0]}")/functions.bash" + + __googleapis_http \ + "${OOM_CLIENT_ID}" \ + "${OOM_CLIENT_SECRET}" \ + "${OOM_YOUTUBE_REFRESH_TOKEN}" \ + GET /youtube/v3/subscriptions \ + part=snippet mine=true maxResults=50 +} + +main "$@" diff --git a/youtube-api-poking/refresh-token b/youtube-api-poking/refresh-token new file mode 100755 index 0000000..7ec67b1 --- /dev/null +++ b/youtube-api-poking/refresh-token @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -o errexit + +main() { + [[ "${OOM_YOUTUBE_ACCESS_TOKEN}" ]] || { + echo "Missing \$OOM_YOUTUBE_ACCESS_TOKEN" + exit 1 + } + + [[ "${OOM_CLIENT_SECRET}" ]] || { + echo "Missing \$OOM_CLIENT_SECRET" + exit 1 + } + + [[ "${OOM_CLIENT_ID}" ]] || { + echo "Missing \$OOM_CLIENT_ID" + exit 1 + } + + curl \ + -vvvv \ + -X POST \ + -sSL \ + -d client_id="${OOM_CLIENT_ID}" \ + -d client_secret="${OOM_CLIENT_SECRET}" \ + -d refresh_token="${OOM_YOUTUBE_ACCESS_TOKEN}" \ + -d grant_type=refresh_token \ + 'https://accounts.google.com/o/oauth2/token' +} + +main "$@"