Skip to content

Instantly share code, notes, and snippets.

@genedelisa
Last active September 7, 2020 03:41
Show Gist options
  • Save genedelisa/8bb67f2ece03a1bd73bfea4904b0b3fe to your computer and use it in GitHub Desktop.
Save genedelisa/8bb67f2ece03a1bd73bfea4904b0b3fe to your computer and use it in GitHub Desktop.
zsh script to grab cat images from Reddit. One random, All from a subreddit, optionally download them, and optionally view them via QuickLook.
#!/usr/bin/env zsh
# -*- mode: shell-script -*-
#
# Time-stamp: "Last Modified 2020-05-22 14:43:23 by Gene De Lisa, genedelisa"
#
# File: ~/dotfiles/.zsh/scripts/
# Gene De Lisa
# gene@rockhoppertech.com
# http://rockhoppertech.com/blog/
# grab a random images from a cat sub and view it via quicklook preview
# catimgreddit --quicklook
#
# grab a random images from specified sub and view it via quicklook preview
#catimgreddit --quicklook -s aww
#
# to view the image right in iterm2, use --imgcat instead of --quicklook
# download images into the current directory
# catimgreddit --downloadall --keep -s aww
#
# see
# https://www.reddit.com/dev/api/
# http://github.com/reddit/reddit/wiki/API
# command line check
# curl -s -H ${USER_AGENT} "https://www.reddit.com/r/Cats/new.json?sort=new&t=day&limit=2" | jq '.'
################################################################################
[[ $(uname) != "Darwin" ]] && print "$0 must be run on macOS" && return -1
(( ! $+commands[curl] )) && {print "You need curl to be installed. Try using brew."; exit 1;}
# -R reset zsh options
# -L options LOCAL_OPTIONS, LOCAL_PATTERNS and LOCAL_TRAPS will be set
emulate -LR zsh
function message {
# if non zero
#[[ -n ${is_verbose} ]] && print Using $sr
#(( ${+is_verbose} )) && print is verbose test
if [[ ${is_verbose} == "true" ]]; then
print -P "%B%F{green}${@}%f%b"
fi
}
function errormessage {
if [[ ${is_verbose} == "true" ]]; then
print -P "%B%F{red}Error:%f%b ${@}" 1>&2
fi
}
typeset -gx REDDIT_IMG_DOWNLOAD_DIR
#REDDIT_IMG_DOWNLOAD_DIR=${REDDIT_IMG_DOWNLOAD_DIR:-$HOME/Pictures/cats}
REDDIT_IMG_DOWNLOAD_DIR=${REDDIT_IMG_DOWNLOAD_DIR:-$PWD}
allcats=($(cat ${ZSH_SCRIPT:h}/cat-subreddits))
ignoresubreddits=(
CatGifs
KittenGifs
CatReactionGifs
CatSpotting
Meow_Irl
Kitties
#CatReddit
#CatVideos
)
subreddits=(
Cats
CatPics
Kitten
Kittens
LookAtMyCat
Cat
Kitty
CatPictures
MaineCoon
MaineCoons
SupermodelCats
)
# use_imgcat=
# use_quicklook=true
# is_verbose=
typeset -a filters
filters=(top
best
hot
new
random
rising)
filter=top
sort=top
sorttimeslice=week
imgurl=
typeset -a imageurls
function grab {
if [[ ${sr} == "random" ]]; then
sr=${subreddits[$(( $RANDOM % ${#subreddits[@]} + 1 ))]}
message "Using random subreddit $sr"
else
message "Using specified subreddit $sr"
fi
requesturl="https://www.reddit.com/r/${sr}/${filter}.json?sort=${sort}&t=${sorttimeslice}&limit=${limit}"
message ${requesturl}
USER_AGENT="User-Agent: cli:zsh:v0.1.0 (by /u/yomama)"
json=$(curl -s -H ${USER_AGENT} --connect-timeout 5 -A '/u/yomama' ${requesturl})
# json=$(echo -n "$json" | tr -d '[:cntrl:]' | jq '(.)' )
#message "$json"
# extract the urls
typeset -a urls
for u in $(printf "%s" $json | jq -r '.data.children[] | .data.url'); do
urls+=$u
done
# get the image urls
for url in ${urls}; do
# print ${url}
# print ${url:e}
# bmp? tiff? webp? raw?
if [[ $url =~ .*\.(jpg|jpeg|png|gif)$ ]]; then
imageurls+=${url}
message "image url \'${url}\'"
fi
done
if [[ ${#imageurls[@]} == 0 ]]; then
errormessage no images in subreddit $sr
exit 1
fi
if [[ ${downloadall} == "true" ]]; then
message download all
print ${#imageurls}
for imgurl in ${imageurls}; do
message downloading $imgurl to ${REDDIT_IMG_DOWNLOAD_DIR}
curl -sO ${imgurl}
[[ $? -ne 0 ]] && {errormessage "curl barfed while downloading ${imgurl}"; exit 1}
[[ ${REDDIT_IMG_DOWNLOAD_DIR} != ${PWD} ]] && {mv ${imgurl:t} ${REDDIT_IMG_DOWNLOAD_DIR};}
done
exit 0
else
imgurl=${imageurls[$(( $RANDOM % ${#imageurls[@]} + 1 ))]}
message "random image url: ${imgurl}"
message "downloading \'${imgurl}\'"
curl -sO ${imgurl}
[[ $? -ne 0 ]] && {errormessage "curl barfed while downloading ${imgurl}"; exit 1}
fi
show
}
#imgurl=$(echo -n $imgurl | sed 's/[[:cntrl:]]*//g;s/\\n//g')
function show {
# [[ ${use_imgcat} ]] && print usimg imgcat ${use_imgcat}
# [[ ${use_quicklook} ]] && print using quicklook ${use_quicklook}
sleep 1
if [[ ${use_quicklook} == "true" ]]; then
# qlmanage is chatty. stfu.
message "ql showing ${imgurl:t}"
qlmanage -p ${imgurl:t} >/dev/null 2>&1
fi
if [[ ${use_imgcat} == "true" ]]; then
~/.iterm2/imgcat ${imgurl:t}
fi
}
################################################################################
# If a command has a non-zero exit status, execute the ZERR trap, if set, and exit
# setopt err_return
# setopt err_exit
# setopt localtraps
# trapzerr() {
# print ""
# print "trapped zerr" >&2
# }
trap_abort() {
if [[ ${downloadall} == "true" ]]; then
exit 0
fi
local file=${imgurl:t}
if [[ -n ${keep_downloaded} ]]; then
message keeping downloaded files
message ${file}
return
fi
if [[ -e $file ]]; then
message "moving ${file} to trash"
mv ${file} ~/.Trash
fi
}
trap 'trap_abort' ABRT HUP INT QUIT TERM EXIT
################################################################################
function usage {
cat <<EOF
Usage: ${ZSH_SCRIPT:t} [arguments]
Arguments:
-h or --help Print the usage information
-d or --debug Debug. Turns on xtrace
-v or --verbose Verbose
-q or --quicklook Use quicklook preview
-i or --imgcat Use iterm imgcat
-k or --keep Do not delete downloaded files
-z or --downloadall Download all
-s or --subreddit Use specific subreddit (e.g. a non cat one. But why?)
-l num or --limit num limit the number of responses
If you specify --keep, the images will be stored in REDDIT_IMG_DOWNLOAD_DIR (pwd by default)
EOF
exit 0
}
[[ $# -lt 1 ]] && {usage}
################################################################################
function exitIfNotMacos {
[[ $(uname) != "Darwin" ]] && {print "${ZSH_SCRIPT:t} must be run on macOS" && return -1}
return 0
}
################################################################################
function parse {
# -R reset zsh options
# -L options LOCAL_OPTIONS, LOCAL_PATTERNS and LOCAL_TRAPS will be set
emulate -LR zsh
setopt localoptions
# define arrays to hold the options
local -a help verbose debug limitopt ql imgcat subredditopt downloadopt keepopt getnew
if zparseopts -D -E -- \
d=debug -debug=debug \
v=verbose -verbose=verbose \
z=downloadopt -downloadall=downloadopt \
q=ql -quicklook=ql \
i=imgcat -imgcat=imgcat \
h=help -help=help \
n=getnew -new=getnew \
k=keepopt -keep=keepopt \
l:=limitopt -limit:=limitopt \
s:=subredditopt -subreddit:=subredditopt
then
[[ -n ${help} ]] && usage;
[[ -n ${verbose} ]] && {is_verbose=true;}
[[ -n ${debug} ]] && setopt xtrace
[[ -n ${imgcat} ]] && {use_imgcat=true;}
[[ -n ${ql} ]] && {use_quicklook=true;}
[[ -n ${downloadopt} ]] && {downloadall=true;}
[[ -n ${keepopt} ]] && {keep_downloaded=true;}
[[ -n ${getnew} ]] && {
filter=new
sort=new
sorttimeslice=day
}
if [[ ${#limitopt} -ge 2 ]]; then
limit=${limitopt[2]}
else
limit=100
fi
message Using a limit of ${limit}
if [[ ${#subredditopt} -ge 2 ]]; then
sr=${subredditopt[2]}
else
sr=random
fi
message Using subreddit ${sr}
# be strict
# [[ ${#limitopt} -lt 2 ]] &&
# {print "Missing required option: --limit num"; return 1}
else
rs=$?
errormessage "zparseopts wasn't happy!" $? >&2
return 1
fi # zparseopts
# the -D flag removed the options
# print the rest of the command line: "$@"
# save them for other functions
nonflag_args="$@"
#[[ -n ${list} ]] && list ${nonflag_args}
return 0
}
################################################################################
# "$*" always expands to something, even without arguments
parse "$@"
grab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment