add files
This commit is contained in:
parent
cb876e3864
commit
05b375a14a
27
LICENSE
Normal file
27
LICENSE
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright © 2016, Björn Busse and contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Björn Busse nor the
|
||||||
|
names of contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY Björn Busse ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL Björn Busse BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
BIN
not_really_into_pokemon.png
Normal file
BIN
not_really_into_pokemon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
285
xkcdlock
Executable file
285
xkcdlock
Executable file
@ -0,0 +1,285 @@
|
|||||||
|
#!/usr/bin/env rbash
|
||||||
|
|
||||||
|
# xkcd_lock v1
|
||||||
|
#
|
||||||
|
# A wrapper around i3lock to display xkcd images on the lock screen
|
||||||
|
#
|
||||||
|
# Note that 'latest' needs an internet connection for the download!
|
||||||
|
# If the download fails it falls back to a specific hard-coded image
|
||||||
|
#
|
||||||
|
# Builtin is a function to download all images.
|
||||||
|
#
|
||||||
|
# Dependencies: rbash, i3lock, xrandr, awk, curl
|
||||||
|
#
|
||||||
|
# © 2016 Björn Busse (see also: LICENSE)
|
||||||
|
# bbusse@baerlin.eu
|
||||||
|
#
|
||||||
|
# Thanks to Randall Patrick Munroe! BTC 1FhCLQK2ZXtCUQDtG98p6fVH7S6mxAsEey
|
||||||
|
# Thanks to Michael Stapelberg for an awesome window manager - i3
|
||||||
|
#
|
||||||
|
# TODO:
|
||||||
|
# - make sure we do not exceed screen boundaries in x and y
|
||||||
|
# - add tooltip overlay and xkcd number
|
||||||
|
# - parallelize downloads
|
||||||
|
|
||||||
|
[[ "$TRACE" ]] && set -x
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
readonly SCRIPT_NAME=$(basename $0)
|
||||||
|
|
||||||
|
# screensaver executable
|
||||||
|
LOCK_BIN="i3lock"
|
||||||
|
# verbosity
|
||||||
|
VERBOSE=0
|
||||||
|
# "latest" or "random"
|
||||||
|
IMG_CHOICE="random"
|
||||||
|
# path to images
|
||||||
|
IMG_PATH="${HOME}/Pictures/xkcd_comics"
|
||||||
|
# default / fallback image
|
||||||
|
IMG_DEFAULT="not_really_into_pokemon.png"
|
||||||
|
# background colour
|
||||||
|
BG_COLOUR="white"
|
||||||
|
|
||||||
|
DOWNLOAD_DISCLAIMER="\nThe downloaded images will end up in your current working directory.\n\
|
||||||
|
Since we are using restricted bash, we can not change path.\n\
|
||||||
|
Use '-y' instead of '-d' to really start the download to the current working directory.\n"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
if (( 1=="${VERBOSE}" )); then
|
||||||
|
echo "$@" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
logger -p user.notice -t $SCRIPT_NAME "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo "$@" >&2
|
||||||
|
logger -p user.error -t $SCRIPT_NAME "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# does not work with restricted bash (bash -r/rbash)
|
||||||
|
get_script_path() {
|
||||||
|
echo $(dirname $(readlink -f $0))
|
||||||
|
}
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
printf "\n xkcd_lock v1\n\n\
|
||||||
|
Available options are:\n\n \
|
||||||
|
-d download images to current working directory\n \
|
||||||
|
-h show this help\n \
|
||||||
|
-i show specific image file - overrides '-m'\n \
|
||||||
|
-l lock program: one of i3lock/swaylock\n \
|
||||||
|
-m latest|random default: random\n \
|
||||||
|
-v be verbose\n\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
xkcd_get_latest_image() {
|
||||||
|
if [[ -z $(which curl) ]]; then
|
||||||
|
error "Could not find curl to get latest image"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Looking for latest image"
|
||||||
|
local img_url=$(curl -s http://xkcd.com/index.html | \
|
||||||
|
awk '/Image URL \(for hotlinking\/embedding\): / {print $5}' | \
|
||||||
|
awk 'BEGIN{FS="<";} {print $1}')
|
||||||
|
|
||||||
|
if [[ -z $img_url ]]; then
|
||||||
|
error "Can not download latest image, using fallback image"
|
||||||
|
local img_fn="${IMG_DEFAULT}"
|
||||||
|
else
|
||||||
|
log "Downloading: $img_url"
|
||||||
|
curl -sO --max-time 6 "$img_url"
|
||||||
|
|
||||||
|
if [[ 0="$?" ]]; then
|
||||||
|
local img_fn=$(echo "$img_url" | awk 'BEGIN{FS="/";} {print $5}')
|
||||||
|
else
|
||||||
|
error "Can not download latest image, using fallback image"
|
||||||
|
local img_fn="${IMG_DEFAULT}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$img_fn"
|
||||||
|
}
|
||||||
|
|
||||||
|
xkcd_get_img_name() {
|
||||||
|
echo $(echo "$img_url_hotlink" | awk 'BEGIN{FS="/";} {print $5}')
|
||||||
|
}
|
||||||
|
|
||||||
|
xkcd_get_all_images() {
|
||||||
|
VERBOSE="1"
|
||||||
|
|
||||||
|
if [[ -z $(which curl) ]]; then
|
||||||
|
error "Could not find curl to download images"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Looking for latest image"
|
||||||
|
local nimg_latest=$(curl -s http://xkcd.com/index.html | \
|
||||||
|
awk '/Permanent link to this comic: / {print $6}' | \
|
||||||
|
awk 'BEGIN{FS="/";} {print $4}')
|
||||||
|
|
||||||
|
log "Found: $nimg_latest"
|
||||||
|
|
||||||
|
for ((i=1; i<=$nimg_latest; i++)); do
|
||||||
|
local img_url_hotlink=$(xkcd_get_hotlink_url $i)
|
||||||
|
local img_name=$(xkcd_get_img_name $img_url_hotlink)
|
||||||
|
|
||||||
|
if [[ -e "$img_name" ]]; then
|
||||||
|
log "$img_name exists. Skipping download"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Downloading ${i} ${img_url_hotlink} (${img_name})"
|
||||||
|
local r=$(curl -sO $img_url_hotlink)
|
||||||
|
log "Success: $r"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo 0
|
||||||
|
}
|
||||||
|
|
||||||
|
xkcd_get_hotlink_url() {
|
||||||
|
local url="http://xkcd.com/$i"
|
||||||
|
local url_hotlink="$(curl -sL $url | awk '/Image URL \(for hotlinking\/embedding\): / {print $5}')"
|
||||||
|
echo $url_hotlink
|
||||||
|
}
|
||||||
|
|
||||||
|
get_nscreens() {
|
||||||
|
local nscreens=$(xrandr -q | awk '/ connected/ {count++} END {print count}')
|
||||||
|
echo "$nscreens"
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_get_smallest_resolution() {
|
||||||
|
local res=$(xrandr -q | awk '/*/ {print $1}' \
|
||||||
|
| awk 'BEGIN{FS="x";} NR==1 || $1<min {line=$0; min=$1}; END {print line}')
|
||||||
|
|
||||||
|
echo "$res"
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_get_highest_resolution() {
|
||||||
|
local res=$(xrandr -q | awk '/*/ {print $1}' \
|
||||||
|
| awk 'BEGIN{FS="x";} NR==1 || $1>max {line=$0; max=$1}; END {print line}')
|
||||||
|
|
||||||
|
echo "$res"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_random_image() {
|
||||||
|
local img_fn="$(find $IMG_PATH -type f | shuf -n 1)"
|
||||||
|
|
||||||
|
if ! [[ -e "$img_fn" ]]; then
|
||||||
|
error "Could not find image to display"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$img_fn"
|
||||||
|
}
|
||||||
|
|
||||||
|
resize_image() {
|
||||||
|
local tmp_file=$(mktemp)
|
||||||
|
|
||||||
|
log "Resizing $img_fn to $res and saving image to $tmp_file"
|
||||||
|
convert -adaptive-resize $res $img_fn $tmp_file
|
||||||
|
|
||||||
|
if ! [[ -e "$tmp_file" ]]; then
|
||||||
|
error "Could not find resized image"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$tmp_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
center_image() {
|
||||||
|
local tmp_file=$(mktemp)
|
||||||
|
|
||||||
|
log "Centering $tmp_file and saving image to $tmp_file"
|
||||||
|
convert $tmp_file_r -gravity center -background $BG_COLOUR -extent $res $tmp_file
|
||||||
|
|
||||||
|
if ! [[ -e "$tmp_file" ]]; then
|
||||||
|
error "Could not find centered image"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$tmp_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_image() {
|
||||||
|
local res=$(screen_get_highest_resolution)
|
||||||
|
|
||||||
|
local tmp_file_r=$(resize_image $img_fn $res)
|
||||||
|
local tmp_file_c=$(center_image $tmp_file_r $res)
|
||||||
|
|
||||||
|
echo "$tmp_file_c"
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_lock() {
|
||||||
|
local img_fn_final=$(prepare_image $img_fn)
|
||||||
|
|
||||||
|
log "Locking screen with $img_fn"
|
||||||
|
$LOCK_BIN -i $img_fn_final
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local locker=$(which $LOCK_BIN)
|
||||||
|
local OPTIND
|
||||||
|
|
||||||
|
while getopts "h?i:l:vm:dy" opt; do
|
||||||
|
case "$opt" in
|
||||||
|
d)
|
||||||
|
printf "%s${DOWNLOAD_DISCLAIMER}"
|
||||||
|
printf "%s\nCurrent working directory: ${PWD}\n\n"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
h|\?)
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
i)
|
||||||
|
local img_fn="${OPTARG}"
|
||||||
|
local r=$(screen_lock $img_fn)
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
l)
|
||||||
|
if [[ "sway"="${OPTARG}" ]]; then
|
||||||
|
LOCK_BIN="swaylock"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
m)
|
||||||
|
IMG_CHOICE="${OPTARG}"
|
||||||
|
;;
|
||||||
|
v)
|
||||||
|
VERBOSE=1
|
||||||
|
;;
|
||||||
|
y)
|
||||||
|
r=$(xkcd_get_all_images)
|
||||||
|
exit 0
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! [[ -d "$IMG_PATH" ]]; then
|
||||||
|
error "Image directory does not exist: $IMG_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $(which xrandr) ]]; then
|
||||||
|
error "Could not find xrandr to determine screen size"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$locker" ]]; then
|
||||||
|
error "Could not find screen locker: $lock_bin"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $(which convert) ]]; then
|
||||||
|
error "Could not find $convert_bin \nYou need imagick"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$IMG_CHOICE" in
|
||||||
|
"latest") local img_fn=$(xkcd_get_latest_image);;
|
||||||
|
"random") local img_fn=$(get_random_image);;
|
||||||
|
esac
|
||||||
|
|
||||||
|
screen_lock $img_fn
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
Loading…
Reference in New Issue
Block a user