Every time I look over at the channels I'm subscribed to in YouTube I have this internal discussion:
- My gosh, how did that list of subscriptions get so big? I sure wish I had a way to trim it down without going through the tedious process of manually unusbscribing.
- I know, I'll write a command line script to manage my YouTube subscriptions!
- But that will take time ... let me just muscle through and manually unsubscribe from channels I don't want to follow any longer.
- (Goes through the process of unsubscribing from two channels)
- Ugh! This is painful. I give up.
- And repeat...
Today, however, I finally broke the cycle! I decided to write a tool that will let me list and delete subscriptions from the command line. This wasn't really a stretch, I've written code that works with the Blogger Data API, so I figured working with the YouTube Data API wouldn't be any more difficult.
Step 1, I created a small command line utility to grant me OAuth access to my YouTube account:
#!/bin/bash
##
## Authenticate with YouTube Data API
##
USAGE="`basename $0` {auth|refresh|token} ctx"
CTX_DIR=$HOME/.youtube_auth
CLIENT_ID=703261074341-e1vpmqq8kh2v9ke0mveve7dakpbobkft.apps.googleusercontent.com
CLIENT_SECRET=uRhAcxywxYZF2bhbx7zVqeML
ctx=default
function usage {
echo "Usage: `basename $0` [-h] [-c context] {init|token}"
exit
}
function age {
modified=`stat -c %X $1`
now=`date +%s`
expr $now - $modified
}
function refresh {
refresh_token=`cat $CTX_DIR/$ctx.refresh_token`
curl -si \
-d client_id=$CLIENT_ID \
-d client_secret=$CLIENT_SECRET \
-d refresh_token=$refresh_token \
-d grant_type=refresh_token \
https://accounts.google.com/o/oauth2/token > $CTX_DIR/$ctx.refresh
grep access_token $CTX_DIR/$ctx.refresh | sed -e 's/.*: "//' -e 's/",//' > $CTX_DIR/$ctx.access_token
}
while getopts :hc: opt ; do
case $opt in
c) ctx=$OPTARG ;;
h) usage ;;
esac
done
shift $(($OPTIND - 1))
cmd=$1 ; shift
mkdir -p $CTX_DIR
case $cmd in
init)
url=`curl -gsi \
-d scope=https://www.googleapis.com/auth/youtube \
-d redirect_uri=urn:ietf:wg:oauth:2.0:oob \
-d response_type=code \
-d access_type=offline \
-d client_id=$CLIENT_ID \
https://accounts.google.com/o/oauth2/v2/auth | \
grep -i Location: | \
sed 's/[lL]ocation: //'`
echo $url
echo -n "Code? "
read code
curl -s \
-d client_id=$CLIENT_ID \
-d client_secret=$CLIENT_SECRET \
-d code=$code \
-d grant_type=authorization_code \
-d redirect_uri=urn:ietf:wg:oauth:2.0:oob \
https://www.googleapis.com/oauth2/v4/token > $CTX_DIR/$ctx.init
grep access_token $CTX_DIR/$ctx.init | sed -e 's/.*: "//' -e 's/",//' > $CTX_DIR/$ctx.access_token
grep refresh_token $CTX_DIR/$ctx.init | sed -e 's/.*: "//' -e 's/"//' > $CTX_DIR/$ctx.refresh_token
echo "Done"
;;
token)
if [ ! -f $CTX_DIR/$ctx.access_token ] ; then
echo "Unknown context: $ctx. Try initing first."
exit
fi
age=`age $CTX_DIR/$ctx.access_token`
if [ $age -gt 3600 ] ; then
refresh
fi
cat $CTX_DIR/$ctx.access_token
;;
*)
usage
esac
Surprisingly, I needed to use different API end points than I used for other curl based Google OAuth apps. I needed to generate the authentication code at https://accounts.google.com/o/oauth2/v2/auth and generate the auth token at https://www.googleapis.com/oauth2/v4/token.
Once I had an authentication token, life was good. I used the usual suspects to power this script. Mainly, curl to make the appropriate web requests and jq to format the resulting JSON in an intelligent way. You'll notice from the script below that if you pass -v to the script, you get the complete JSON output. Man those tools are awesome; if you don't know them well you're missing out.
Here's a sample run of my shiny new script:
$ youtube_tools -a subscriptions|grep -i megan ffVDX-wHSD6NaM3-kGgVug8jUOQIbwozBmWubSPnjtU:Megan Davies # Nothing personal Megan, but we're breaking up: $ youtube_tools -a subscription-delete \ -i `youtube_tools -a subscriptions |grep Megan | cut -d ':' -f 1`
Now that's how you manage YouTube subscriptions!
I'm not quite sure what else I'm going to do with this tool, but given how much I use YouTube for, I won't be surprised if I add to it.
Here's the code for the script, enjoy!
#!/bin/bash
##
## command line tools for working with YouTube.
## See: https://developers.google.com/youtube/v3/docs/
##
API_BASE=https://www.googleapis.com/youtube/v3
AUTH_TOKEN=`youtube_auth token`
if [ -z "$AUTH_TOKEN" ] ; then
echo "`basename $0`: authentication not setup. Run: 'youtube_auth init'"
exit 1
fi
function usage {
echo "Usage: `basename $0` -a {subscriptions|subscription-delete} [-i ID] -v"
exit
}
function filter {
if [ -z "$VERBOSE" ] ; then
jq "$@"
else
cat
fi
}
while getopts ":a:i:v" opt ; do
case $opt in
a) ACTION=$OPTARG ;;
v) VERBOSE=yes ;;
i) ID=$OPTARG ;;
\?) usage ;;
esac
done
function invoke {
curl -s -H "Authorization: Bearer $AUTH_TOKEN" "$@"
}
case $ACTION in
subscriptions)
invoke -G $API_BASE/subscriptions \
-d mine=true \
-d part=snippet \
-d maxResults=50 |
filter -r ' .items[] | .id + ":" + .snippet.title'
;;
subscription-delete)
if [ -z "$ID" ] ; then
echo "Deleting a subscription requires an ID (-i) value"
usage
fi
invoke -X DELETE "$API_BASE/subscriptions?id=$ID"
;;
*)
usage
;;
esac
No comments:
Post a Comment