Browse Source

[bin] Add macOS script for setting bing wallpaper

Colin Powell 2 days ago
parent
commit
bbcc16b8f1
1 changed files with 352 additions and 0 deletions
  1. 352 0
      bin/.bin/bing-wallpaper.sh

+ 352 - 0
bin/.bin/bing-wallpaper.sh

@@ -0,0 +1,352 @@
+#!/bin/sh
+PATH=/usr/local/bin:/usr/local/sbin:~/bin:/usr/bin:/bin:/usr/sbin:/sbin
+
+readonly SCRIPT=$(basename "$0")
+readonly VERSION='1.1.1'
+RESOLUTIONS=(1920x1200 1920x1080 1024x768 1280x720 1366x768 UHD)
+MONITOR="0" # 0 means all monitors
+PLIST_FILE="$HOME/Library/LaunchAgents/com.bing-wallpaper-daily-mac-multimonitor"
+AUTO_UPDATE_NAME="default"
+ARGS=$@
+
+usage() {
+cat <<EOF
+Usage:
+  $SCRIPT [options]
+  $SCRIPT -h | --help
+  $SCRIPT --version
+
+Options:
+  enable-auto-update             Enable automatic update of wallpapers every day
+                                 the picture if the filename already exists.
+  disable-auto-update            Disable automatic update of wallpapers every day
+                                 the picture if the filename already exists.
+  info                           Show description of current wallpaper.
+  --auto-update-name <name>      Name of your auto update when enabling/disabling
+                                 Using custom name enables setting multiple automatic update configurations.
+                                 Eg. Set on monitor 1 todays wallpaper and on monitor 2 wallpaper from yesterday                                                           
+  -f --force                     Force download of picture. This will overwrite
+                                 the picture if the filename already exists.
+  -s --ssl                       Communicate with bing.com over SSL.
+  -q --quiet                     Do not display log messages.
+  -c --country <coutry-tag>      Specify market country/region eg. en-US, cs-CZ
+                                 Pictures may be different for markets on some days.
+                                 See full list of countries on https://learn.microsoft.com/en-us/previous-versions/bing/search/dd251064(v=msdn.10)
+  -d --day <number>              Day for which you want to get the picture.
+                                 0 is current day, 1 is yesterday etc.
+                                 Default is 0.
+  -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/]
+  -r --resolution <resolution>   The resolution of the image to retrieve.
+                                 Supported resolutions: ${RESOLUTIONS[*]}
+  --resolutions <resolutions>    The resolutions of the image try to retrieve.
+                                 eg.: --resolutions "1920x1200 1920x1080 UHD"
+  -m --monitor <num>             Set wallpaper only on certain monitor (1,2,3...)
+  --all-desktops-experimental    Set wallpaper on all desktops
+                                 Fixing osascript bug when wallpaper is not set for Desktop 2.
+                                 Known issue: Minimized apps are removed from Dock.
+                                 If something goes wrong delete Library/Application Support/Dock/desktoppicture.db
+                                 and restart your Mac.                    
+  -h --help                      Show this screen.
+  --version                      Show version.
+EOF
+}
+
+create_plist_in_users_agents_folder() {
+    local SCRIPT_PATH=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/$(basename "${BASH_SOURCE:-$0}")
+    local REST_ARGS=$(echo "$ARGS" | sed -e "s/enable-auto-update//")
+    
+    if [ $RUN_USING_NPX ]; then
+        local COMMANDS="<string>source ~/.bashrc && npx --yes bing-wallpaper-daily-mac-multimonitor@latest $REST_ARGS</string>"
+    else
+        local COMMANDS="<string>$SCRIPT_PATH $REST_ARGS</string>"
+    fi
+
+    cat > $PLIST_FILE <<- EOM
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>Label</key>
+    <string>com.bing-wallpaper-daily-mac-multimonitor.plist</string>
+    <key>OnDemand</key>
+    <true/>
+    <key>ProgramArguments</key>
+    <array>
+        <string>/bin/sh</string>
+		<string>-c</string>
+        $COMMANDS
+    </array>
+    <key>EnvironmentVariables</key>
+    <dict>
+        <key>PATH</key>
+        <string>/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin</string>
+    </dict>
+     <key>StandardErrorPath</key>
+    <string>/tmp/bing-wallpaper-daily-mac-multimonitor-plist.err</string>
+    <key>StandardOutPath</key>
+    <string>/tmp/bing-wallpaper-daily-mac-multimonitor-plist.out</string>
+    <key>StartInterval</key>
+    <integer>1800</integer>
+	<key>RunAtLoad</key>
+	<true/>
+</dict>
+</plist>
+EOM
+
+launchctl unload -w $PLIST_FILE 2>/dev/null
+launchctl load -w $PLIST_FILE 
+}
+
+remove_plist_in_users_agents_folder() {
+    launchctl unload -w "$PLIST_FILE" 2>/dev/null
+    rm "$PLIST_FILE"
+}
+
+show_info_text() {
+    # Parse HPImageArchive API and acquire picture BASE URL
+COPYRIGHT=$(cat "$PICTURE_DIR/info.xml" | \
+    grep -Eo "<copyright>.*<\/copyright>")
+COPYRIGHT=$(echo "$COPYRIGHT" | sed -e "s/<copyright>//")
+COPYRIGHT=$(echo "$COPYRIGHT" | sed -e "s/<\/copyright>//")
+echo $COPYRIGHT
+}
+
+print_message() {
+    if [ ! "$QUIET" ]; then
+        printf "%s\n" "$(date): ${1}"
+    fi
+}
+
+download_image_curl () {
+    local RES=$1
+    FILEURLWITHRES="${FILEURL}_${RES}.jpg"
+    echo $FILEURLWITHRES
+    FILENAME=${FILEURLWITHRES/\/th\?id=/}
+    FILENAME_LOCAL="${AUTO_UPDATE_NAME}-${FILENAME}"
+    FILEWHOLEURL="$PROTO://bing.com/$FILEURLWITHRES"
+
+    if [ $FORCE ] || [ ! -f "$PICTURE_DIR/$FILENAME_LOCAL" ]; then
+        find $PICTURE_DIR -type f -iname $AUTO_UPDATE_NAME-\*.jpg -delete
+        print_message "Downloading: $FILENAME..."
+        curl --fail -Lo "$PICTURE_DIR/$FILENAME_LOCAL" "$FILEWHOLEURL"
+        curl --fail -Lo "$PICTURE_DIR/info.xml" "$BING_HP_IMAGE_ARCHIVE_URL"
+        if [ "$?" == "0" ]; then
+            FILEPATH="$PICTURE_DIR/$FILENAME_LOCAL"
+            return
+        fi
+
+        FILEPATH=""
+        return
+    else
+        print_message "Skipping download: $FILENAME_LOCAL..."
+        FILEPATH="$PICTURE_DIR/$FILENAME_LOCAL"
+        DOWNLOAD_SKIPPED=true
+        return
+    fi
+}
+
+set_wallpaper () {
+    local FILEPATH=$1
+    local MONITOR=$2
+
+    if [ "$MONITOR" -ge 1 ] 2>/dev/null; then
+    print_message "Setting wallpaper for monitor: $MONITOR"
+    osascript - << EOF
+        set tlst to {}
+        tell application "System Events"
+            set tlst to a reference to every desktop
+            set picture of item $MONITOR of tlst to "$FILEPATH"
+        end tell
+EOF
+    else
+        osascript -e 'tell application "System Events" to tell every desktop to set picture to "'$FILEPATH'"'
+    fi
+}
+
+set_wallpaper_experimental () {
+    local db_file="Library/Application Support/Dock/desktoppicture.db"
+    local db_path="$HOME/$db_file"
+
+    # Put the image path in the database
+    local sql="insert into data values(\"$FILEPATH\"); "
+    sqlite3 "$db_path" "$sql"
+
+    # Get the index of the new entry
+    local sql="select max(rowid) from data;"
+    local new_entry=$(sqlite3 "$db_path" "$sql")
+    local new_entry=$(echo $new_entry|tr -d '\n')
+
+    # Get all picture ids (monitor/space pairs)
+    local sql="select rowid from pictures;"
+    local pictures_string=$(sqlite3 "$db_path" "$sql")
+
+    local IFS=$'\n'
+    local pictures=($pictures_string)
+
+    # Clear all existing preferences
+    local sql="select max(rowid) from data; delete from preferences; "
+
+    for pic in "${pictures[@]}"
+    do
+        if [ "$pic" ]; then
+            local sql+="insert into preferences (key, data_id, picture_id) "
+            local sql+="values(1, $new_entry, $pic); "
+        fi
+    done
+
+    sqlite3 "$db_path" "$sql"
+
+    killall "Dock"
+}
+
+# Defaults
+PICTURE_DIR="$HOME/Pictures/bing-wallpapers/"
+
+# Option parsing
+while [[ $# -gt 0 ]]; do
+    key="$1"
+
+    case $key in
+        enable-auto-update)
+            ENABLE_AUTOMATIC_UPDATE=true
+            ;;
+        disable-auto-update)
+            DISABLE_AUTOMATIC_UPDATE=true
+            ;;
+        info)
+            INFO=true
+            ;;
+        --auto-update-name)
+            AUTO_UPDATE_NAME="$2"
+            shift
+            ;;
+        -r|--resolution)
+            RESOLUTION="$2"
+            shift
+            ;;
+        -p|--picturedir)
+            PICTURE_DIR="$2"
+            shift
+            ;;
+        -c|--country)
+            COUNTRY="$2"
+            shift
+            ;;
+        -d|--day)
+            DAY="$2"
+            shift
+            ;;
+        -n|--filename)
+            FILENAME="$2"
+            shift
+            ;;
+        -m|--monitor)
+            MONITOR="$2"
+            shift
+            ;;
+        -f|--force)
+            FORCE=true
+            ;;
+        -s|--ssl)
+            SSL=true
+            ;;
+        -q|--quiet)
+            QUIET=true
+            ;;
+        -h|--help)
+            usage
+            exit 0
+            ;;
+        --resolutions)
+            RESOLUTIONS="$2"
+            shift
+            ;;
+        --all-desktops-experimental)
+            EXPERIMENTAL=true
+            ;;
+        --version)
+            printf "%s\n" $VERSION
+            exit 0
+            ;;
+        *)
+            (>&2 printf "Unknown parameter: %s\n" "$1")
+            usage
+            exit 1
+            ;;
+    esac
+    shift
+done
+
+# Set options
+[ $QUIET ] && CURL_QUIET='-s'
+[ $SSL ]   && PROTO='https'   || PROTO='http'
+[ $DAY ]   && IDX=$DAY   || IDX='0'
+BING_HP_IMAGE_ARCHIVE_URL="https://www.bing.com/HPImageArchive.aspx?format=xml&idx=${IDX}&n=1"
+[ $COUNTRY ]   && BING_HP_IMAGE_ARCHIVE_URL="${BING_HP_IMAGE_ARCHIVE_URL}&mkt=${COUNTRY}"
+PLIST_FILE="${PLIST_FILE}-${AUTO_UPDATE_NAME}.plist"
+
+PARENT_COMMAND=$(ps -o comm= $PPID)
+if [[ "$PARENT_COMMAND" == *"npm exec"* ]]; then
+  RUN_USING_NPX=true
+fi
+
+if [ "$ENABLE_AUTOMATIC_UPDATE" ]; then
+# enable update
+create_plist_in_users_agents_folder
+echo "Automatic wallpaper update enabled"
+exit 1
+fi
+
+if [ "$DISABLE_AUTOMATIC_UPDATE" ]; then
+# disable update
+remove_plist_in_users_agents_folder
+echo "Automatic wallpaper update disabled"
+exit 1
+fi
+
+if [ "$INFO" ]; then
+show_info_text
+exit 1
+fi
+
+# Create picture directory if it doesn't already exist
+mkdir -p "${PICTURE_DIR}"
+
+# Parse HPImageArchive API and acquire picture BASE URL
+FILEURL=( $(curl -sL $BING_HP_IMAGE_ARCHIVE_URL | \
+    grep -Eo "<urlBase>.*?</urlBase>") )
+FILEURL=$(echo "$FILEURL" | sed -e "s/<urlBase>//")
+FILEURL=$(echo "$FILEURL" | sed -e "s/<\/urlBase>//")
+
+if [ $RESOLUTION ]; then
+    download_image_curl $RESOLUTION
+    if [ "$FILEPATH" ]; then
+        if [ "$EXPERIMENTAL" ]; then
+            if [ ! "$DOWNLOAD_SKIPPED" ]; then
+                set_wallpaper_experimental $FILEPATH
+            fi
+        else
+            set_wallpaper $FILEPATH $MONITOR
+        fi
+    fi
+    exit 1
+fi
+
+for RESOLUTION in "${RESOLUTIONS[@]}"
+    do
+        download_image_curl $RESOLUTION
+        if [ "$FILEPATH" ]; then
+            if [ "$EXPERIMENTAL" ]; then
+                if [ ! "$DOWNLOAD_SKIPPED" ]; then
+                    set_wallpaper_experimental $
+                fi
+            else
+                set_wallpaper $FILEPATH $MONITOR
+            fi
+            exit 1
+        fi
+    done