Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make script more robust and add linux support #34

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,24 @@ Usage:
Options:
-f --force Force download of picture. This will overwrite
the picture if the filename already exists.
-s --ssl Communicate with bing.com over SSL.
-b --boost <n> Use boost mode. Try to fetch latest <n> pictures.
-q --quiet Do not display log messages.
-n --filename <file name> The name of the downloaded picture. Defaults to
the upstream name.
-p --picturedir <picture dir> The full path to the picture download dir.
Will be created if it does not exist.
[default: $HOME/Pictures/bing-wallpapers/]
Defaults to <home>/<pictures>/bing-wallpapers.
-r --resolution <resolution> The resolution of the image to retrieve.
Supported resolutions: 1920x1200 1920x1080 800x480 400x240
-w --set-wallpaper Set downloaded picture as wallpaper (Only mac support for now).
Supported resolutions:
1920x1200
1920x1080
1366x768
800x480
400x240
default:
1920x1080
-m <market> The market to query. Defaults to en-US.
-w --set-wallpaper Set downloaded picture as wallpaper.
-h --help Show this screen.
--version Show version.
```
Expand Down
66 changes: 66 additions & 0 deletions Tools/lightdm/fetch_pic_of_the_day.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/bin/sh

set -e
set -o pipefail

#
# Copy script to /var/lib/lightdm/bin/ and configure Seat in
# lightdm.conf as follows:
#
# display-setup-script=/var/lib/lightdm/bin/fetch_pic_of_the_day.sh -m de-DE -r 1366x768
#
# Params are passed directly to bing-wallpaper.sh. Modify as you like.
# Make sure $USER_NAME is able to write to $PIC_DIR and $LOGFILE.
#
# $PIC_DIR/$PIC_NAME is a symbolic link to the picture of the day.
# Configure your lightdm greeter accordingly and enjoy!
#

BIN_BASH=/bin/bash
BIN_BING_WP=/usr/bin/bing-wallpaper.sh
USER_NAME=lightdm
PIC_DIR=/usr/share/backgrounds/bing
PIC_NAME=lightdm.jpg
LOGFILE=/tmp/fetch_pic_of_the_day.log

# Only root should call this script!
if [ $(id -u) -ne 0 ]; then
exit 1
fi

CMD=$(cat <<-EOF

echo "################################################################################" >> $LOGFILE
echo "\$(date): Fetching pic of the day from bing.com!" >> $LOGFILE
if [ ! -d "${PIC_DIR}" ]; then
echo "Dir ${PIC_DIR} does not exist! Abort!" >> $LOGFILE
exit 1
fi

${BIN_BING_WP} ${@} -p $PIC_DIR >> $LOGFILE 2>&1

cd "${PIC_DIR}"
if [ -L "${PIC_NAME}" ]; then
WALLPAPER=\$(find . -type f -name "*.jpg" -newermm ${PIC_NAME})
if [ -n "${WALLPAPER}" ]; then
WALLPAPER=\$(find . -type f -name "*.jpg" -newermm ${PIC_NAME} | xargs ls -tr | tail -1)
else
echo "Wallpaper is up-to-date." >> $LOGFILE
fi
else
WALLPAPER=\$(find . -type f -name "*.jpg")
if [ -n "${WALLPAPER}" ]; then
WALLPAPER=\$(find . -type f -name "*.jpg" | xargs ls -tr | tail -1)
else
echo "No wallpaper found." >> $LOGFILE
fi
fi

if [ -n "\${WALLPAPER}" ]; then
echo "Set wallpaper to \${WALLPAPER}." >> $LOGFILE
ln -sf "\${WALLPAPER}" ${PIC_NAME}
fi
EOF
)

su -s "${BIN_BASH}" -c "$CMD" - "${USER_NAME}"
147 changes: 102 additions & 45 deletions bing-wallpaper.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
#!/usr/bin/env bash
# shellcheck disable=SC1117

readonly SCRIPT=$(basename "$0")
readonly VERSION='0.4.0'
readonly RESOLUTIONS=(1920x1200 1920x1080 800x480 400x240)
set -e
set -o pipefail

readonly SCRIPT=${0##*/}
readonly VERSION='0.5.0'
readonly RESOLUTIONS=(1920x1200 1920x1080 1366x768 800x480 400x240)
RESOLUTION="${RESOLUTIONS[1]}"

on_failure()
{
echo "Some error occured!" 1>&2
}
trap on_failure ERR

usage() {
cat <<EOF
Expand All @@ -15,17 +25,20 @@ Usage:
Options:
-f --force Force download of picture. This will overwrite
the picture if the filename already exists.
-s --ssl Communicate with bing.com over SSL.
-b --boost <n> Use boost mode. Try to fetch latest <n> pictures.
-q --quiet Do not display log messages.
-n --filename <file name> The name of the downloaded picture. Defaults to
the upstream name.
-p --picturedir <picture dir> The full path to the picture download dir.
Will be created if it does not exist.
[default: $HOME/Pictures/bing-wallpapers/]
Defaults to $PIC_DIR.
-r --resolution <resolution> The resolution of the image to retrieve.
Supported resolutions: ${RESOLUTIONS[*]}
-w --set-wallpaper Set downloaded picture as wallpaper (Only mac support for now).
Supported resolutions:
$(printf " %s\n" ${RESOLUTIONS[@]})
default:
${RESOLUTION}
-m <market> The market to query. Defaults to en-US.
-w --set-wallpaper Set downloaded picture as wallpaper.
-h --help Show this screen.
--version Show version.
EOF
Expand All @@ -37,15 +50,30 @@ print_message() {
fi
}

transform_urls() {
sed -e "s/\\\//g" | \
sed -e "s/[[:digit:]]\{1,\}x[[:digit:]]\{1,\}/$RESOLUTION/" | \
tr "\n" " "
}
# Lookup some required tools (no core-utils).
TOOLS=( curl xmllint )
if [ $(uname) = "Linux" ]; then
TOOLS[${#TOOLS[@]}]=xsetbg
TOOLS[${#TOOLS[@]}]=xdg-user-dir
else
TOOLS[${#TOOLS[@]}]=osascript
fi

for TOOL in ${TOOLS[@]}; do
if ! (which $TOOL &> /dev/null); then
echo "missing: $TOOL" 1>&2
exit 1
fi
done

# Defaults
PICTURE_DIR="$HOME/Pictures/bing-wallpapers/"
RESOLUTION="1920x1080"
BING_BASE_URL="https://www.bing.com"
BING_ARCHIVE_URL="${BING_BASE_URL}/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=en-US"
PIC_DIR="$HOME/Pictures/bing-wallpapers"
if [ $(uname) = "Linux" ]; then
PIC_DIR="$(xdg-user-dir PICTURES)/bing-wallpapers"
fi
EXTENSION=".jpg"

# Option parsing
while [[ $# -gt 0 ]]; do
Expand All @@ -54,10 +82,17 @@ while [[ $# -gt 0 ]]; do
case $key in
-r|--resolution)
RESOLUTION="$2"
PATTERN=" $RESOLUTION "
if [[ ! " ${RESOLUTIONS[*]} " =~ "$PATTERN" ]]; then
(>&2 printf "Unknown resolution:\n %s\n" $RESOLUTION)
(>&2 printf "Supported resolutions:\n")
(>&2 printf " %s\n" "${RESOLUTIONS[@]}")
exit 1
fi
shift
;;
-p|--picturedir)
PICTURE_DIR="$2"
PIC_DIR="$2"
shift
;;
-n|--filename)
Expand All @@ -67,11 +102,13 @@ while [[ $# -gt 0 ]]; do
-f|--force)
FORCE=true
;;
-s|--ssl)
SSL=true
;;
-b|--boost)
BOOST=$(($2-1))
BOOST=$(($2))
if (( $BOOST < 1 )); then
(>&2 printf "Num of pictures has to be greater than zero.\n")
exit 1
fi
BING_ARCHIVE_URL="${BING_ARCHIVE_URL/&n=1/&n=$BOOST}"
shift
;;
-q|--quiet)
Expand All @@ -84,6 +121,14 @@ while [[ $# -gt 0 ]]; do
-w|--set-wallpaper)
SET_WALLPAPER=true
;;
-m|--market)
if [[ ! "$2" =~ ^[a-z]{2}-[A-Z]{2}$ ]]; then
(>&2 printf "Unknown market.\n")
exit 1
fi
BING_ARCHIVE_URL="${BING_ARCHIVE_URL/&mkt=en-US/&mkt=$2}"
shift
;;
--version)
printf "%s\n" $VERSION
exit 0
Expand All @@ -99,41 +144,53 @@ done

# Set options
[ -n "$QUIET" ] && CURL_QUIET='-s'
[ -n "$SSL" ] && PROTO='https' || PROTO='http'

# Create picture directory if it doesn't already exist
mkdir -p "${PICTURE_DIR}"
mkdir -p "${PIC_DIR}"

# Parse bing.com and acquire picture URL(s)
read -ra urls < <(curl -sL $PROTO://www.bing.com | \
grep -Eo "url\(.*?\)" | \
sed -e "s/url(\([^']*\)).*/http:\/\/bing.com\1/" | \
transform_urls)

if [ -n "$BOOST" ]; then
read -ra archiveUrls < <(curl -sL "$PROTO://www.bing.com/HPImageArchive.aspx?format=js&n=$BOOST" | \
grep -Eo "url\(.*?\)" | \
sed -e "s/url(\([^']*\)).*/http:\/\/bing.com\1/" | \
transform_urls)
urls=( "${urls[@]}" "${archiveUrls[@]}" )
fi
print_message "Downloading: $BING_ARCHIVE_URL"
declare -a PIC_URL_PATHS
read -a PIC_URL_PATHS < <(curl $CURL_QUIET -L "$BING_ARCHIVE_URL" |
xmllint --xpath "//urlBase" - | sed -r "s/<[^>]+>//g" | xargs echo)


for p in "${urls[@]}"; do
if [ -z "$FILENAME" ]; then
filename=$(echo "$p" | sed -e 's/.*[?&;]id=\([^&]*\).*/\1/' | grep -oe '[^\.]*\.[^\.]*$')
PIC_FILE=""
PIC_FILE_AS_WALLPAPER=""

# Load from oldest to newest picture.
# This way pictures can be sorted by modification time.
for (( I=${#PIC_URL_PATHS[@]}; $I>0; I-- )); do
PIC_URL_PATH="${PIC_URL_PATHS[(( $I - 1 ))]}"

# Store last image under given name, if requested.
if (( $I == 1 )) && [ -n "$FILENAME" ]; then
PIC_FILE="$PIC_DIR/${FILENAME}"
else
filename="$FILENAME"
FILENAME_=$(echo "${PIC_URL_PATH%*/}" | sed -r "s/[^A-Za-z0-9_-]+//g")
PIC_FILE="$PIC_DIR/${FILENAME_}_${RESOLUTION}${EXTENSION}"
fi
if [ -n "$FORCE" ] || [ ! -f "$PICTURE_DIR/$filename" ]; then
print_message "Downloading: $filename..."
curl $CURL_QUIET -Lo "$PICTURE_DIR/$filename" "$p"

# Mark last picture as wallpaper, if requested.
if (( $I == 1 )) && [ -n "$SET_WALLPAPER" ] ; then
PIC_FILE_AS_WALLPAPER="$PIC_FILE"
fi

BING_PIC_URL="${BING_BASE_URL}${PIC_URL_PATH}_${RESOLUTION}${EXTENSION}"
if [ -n "$FORCE" ] || [ ! -f "$PIC_FILE" ]; then
print_message "Downloading: $BING_PIC_URL"
curl $CURL_QUIET -Lo "$PIC_FILE" "$BING_PIC_URL"
else
print_message "Skipping: $filename..."
print_message "Skipping: $BING_PIC_URL..."
fi
done

if [ -n "$SET_WALLPAPER" ]; then
/usr/bin/osascript<<END
tell application "System Events" to set picture of every desktop to ("$PICTURE_DIR/$filename" as POSIX file as alias)
END
if [ -n "$PIC_FILE_AS_WALLPAPER" ]; then
if [ $(uname) = "Linux" ]; then
xsetbg -onroot "$PIC_FILE_AS_WALLPAPER"
else
osascript <<EOF
tell application "System Events" to set picture of every desktop to ("$PIC_FILE_AS_WALLPAPER" as POSIX file as alias)
EOF
fi
fi