Skip to content

Instantly share code, notes, and snippets.

@onli
Created April 23, 2017 14:22
Show Gist options
  • Save onli/a002cfbc623a950df0e7cae643b0b317 to your computer and use it in GitHub Desktop.
Save onli/a002cfbc623a950df0e7cae643b0b317 to your computer and use it in GitHub Desktop.
izulu with KDE plasma detection
#!/bin/bash
# izulu - Change the wallpaper according to the weather
#
# Copyright (C) 2009 Malte Paskuda
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
# get current weather
# $1: city to look for, or latitude
# $2 longitude, not needed if $1 was a city
# return: current weather
getWeather() {
echo "$WEATHER_DATA" | jq -r '.currently.icon' # -r makes jq not put " around the string, which is important for the later ifs
}
# fill WEATHER_DATA with weather API result. NOTE: Always run this at top level, not in a subshell
# $1: city or latitude
# $2: longitude, not needed if $1 was a city
# return: Weather api data (currently JSON)
fillWeatherData() {
if [ -n "$LATITUDE" ];then
local url="http://izulu.onli-blogging.de/forecast/$LATITUDE/$LONGITUDE"
else
local url="http://izulu.onli-blogging.de/forecast/$CITY"
fi
WEATHER_DATA=$(wget -q -O - "$url")
}
# map forecast-code to one of the icons
chooseForecastIcon() {
forecast="$1"
case "$forecast" in
"cloudy")
echo "forecast_cloud"
;;
"partly-cloudy-day"|"partly-cloudy-night")
echo "forecast_sunnycloud"
;;
"rain")
echo "forecast_rain"
;;
"clear-day"|"clear-night")
echo "forecast_sun"
;;
"snow" | "sleet")
echo "forecast_snow"
;;
"thunderstorm")
echo "forecast_thunderstorm"
;;
"wind")
echo "forecast_wind" # TODO: Add forecast image icon
;;
"fog")
echo "forecast_fog" # TODO: Add forecast image icon
;;
esac
}
# set the wallpaper according to the weather
# $1: current weather
chooseWallpaper() {
local weather="$1"
case "$weather" in
# Sun:
"clear-day" | "clear-night")
setWallpaper "clear" "gen_sun"
;;
# Clouds:
"partly-cloudy-day" | "partly-cloudy-night")
setWallpaper "partly_cloudy" "gen_cloud"
;;
"cloudy")
setWallpaper "cloudy" "gen_cloud"
;;
# "Rain")
"rain")
setWallpaper "rain" "gen_rain"
;;
# "Hail")
"hail")
setWallpaper "hail" "gen_rain"
;;
# "Thunderstorm")
"thunderstorm")
setWallpaper "thunderstorm" "gen_thunder"
;;
# Snow:
"sleet")
setWallpaper "sleet" "gen_snow"
;;
"snow")
setWallpaper "snow" "gen_snow"
;;
# Wind:
"wind")
setWallpaper "windy" "gen_wind"
;;
"tornado")
setWallpaper "tornado" "gen_wind"
;;
# Misc:
"fog")
setWallpaper "fog" "gen_misc"
;;
*)
setWallpaper "cloudy" "gen_cloud" #TODO: set a placeholder image here
;;
esac
}
#Choose the wallpaper
#$1: the image for the specific state
#$2: the image for the generic state, fallback
#$3: If set to anything, random-mode will not be triggered
setWallpaper() {
local specific="$1"
local generic="$2"
local random_override="$3"
if [[ -n "$current" ]];then
if [ "$current" == "$specific" ];then
if [ ! "$TEMPERATURE" == "TRUE" ] && [ ! "$SWISS_RADAR" == "TRUE" ] && [ ! "$GERMAN_RADAR" == "TRUE" ] && [ ! "$RADAR" == "TRUE" ];then
#no dynamic features, so no change necessary
return
fi
fi
fi
current="$specific"
if [ "$RANDOMLY" == "TRUE" ] && [[ -z "$random_override" ]];then
random_image=$(cycleWallpaper "$specific" "$generic")
if [[ -n "$random_image" ]];then
setImage "$random_image"
return
fi
fi
if isNight;then
specific="$specific"_night
generic="$generic"_night
fi
if [[ -e "$HOME"/.izulu/"$specific" ]];then
setImage "$HOME"/.izulu/"$specific"
else
if [[ -e /usr/share/izulu/"$specific" ]];then
setImage /usr/share/izulu/"$specific"
else
if [[ -e "$HOME"/.izulu/"$generic" ]];then
setImage "$HOME"/.izulu/"$generic"
else
setImage /usr/share/izulu/"$generic"
fi
fi
fi
}
# set the Wallpaper
# $1 the wallpaperfile
setImage() {
local tmpimage=$(mktemp)
# store for later merge - and to be able to write
cp "$1" "$tmpimage"
if [ "$PREVIEW" == "TRUE" ];then
for i in {0..4};do
# merge preview-icons with background-image
local forecast=$(echo "$WEATHER_DATA" | jq -r '.daily.data['$i'].icon')
local icon=$(chooseForecastIcon "$forecast")
local tmpicon=$(mktemp)
cp "/usr/share/izulu/$icon" "$tmpicon"
local day=$(date -d @$(echo "$WEATHER_DATA" | jq -r '.daily.data['$i'].time') "+%A")
convert "$tmpicon" -gravity South -fill '#c0bfbd' -font DejaVu-Sans-Condensed -background '#0000' -pointsize 16 -splice 0x24 -annotate +0+2 "${day:0:3}" "$tmpicon"
# at least +20 y height to be above typical taskbar
convert -depth 8 -gravity SouthEast -geometry +$((330-(i+1)*64))+20 "$tmpimage" "$tmpicon" -composite "$tmpimage"
done
fi
if [ "$TEMPERATURE" == "TRUE" ];then
local temperature=$(echo "$WEATHER_DATA" | jq -r '.currently.temperature')
# yql is only giving us fahrenheit values, so we have to convert it into a sane unit
convert -gravity "$TEMPERATURE_GRAVITY" "$tmpimage" -font DejaVu-Sans-Condensed -pointsize 36 -fill '#c0bfbd' -background '#0000' -annotate "$TEMPERATURE_MARGIN" "${temperature%.*}°C" "$tmpimage"
fi
addRadar "$tmpimage"
cp "$tmpimage" "$HOME"/.izulu/izulucurrent
rm "$tmpimage"
${WPCOMMAND/PLACEHOLDER/"$HOME/.izulu/izulucurrent"} &
osdNotify "$(echo "$WEATHER_DATA" | jq -r '.currently.summary')"
}
addRadar() {
local tmpimage="$1"
if [ "$SWISS_RADAR" == "TRUE" ];then
addSwissImage "$tmpimage" warning radar
return
fi
if [ "$GERMAN_RADAR" == "TRUE" ];then
addGermanImage "$tmpimage"
return
fi
if [ "$RADAR" == "TRUE" ];then
if contains "${RADAROPTIONS[*]}" "germany";then
local country="DE"
elif contains "${RADAROPTIONS[*]}" "swiss";then
local country="CH"
else
local country=$(getCountry)
fi
if ! contains "${RADAROPTIONS[*]}" "radar" && ! contains "${RADAROPTIONS[*]}" "warning";then
local options=("warning" "radar")
else
local options=()
for image in ${RADAROPTIONS[*]};do
if [ "$image" == "radar" ] || [ "$image" == "warning" ];then
options[${#options[*]}]="$image"
fi
done
fi
if [ "$country" == "DE" ];then
addGermanImage "$tmpimage" ${options[*]}
elif [ "$country" == "CH" ];then
addSwissImage "$tmpimage" ${options[*]}
fi
fi
}
addGermanImage() {
local i=0
local tmpimage="$1"
local radarimage=$(mktemp)
wget -O - -q ftp://ftp.dfd.dlr.de/put/wetterbilder/Central_Europe/image1.jpg > "$radarimage"
#grab germany from the image of europe:
convert "$radarimage" -crop 650x900+274+120 "$radarimage"
convert "$radarimage" -resize 178 "$radarimage"
composite -gravity SouthEast -geometry +2+128 "$radarimage" "$tmpimage" "$tmpimage"
rm "$radarimage"
}
addSwissImage() {
local i=0
local tmpimage="$1"
for image in $*;do
let i++
if [ "$image" == "warning" ];then
local wetteralarm=$(mktemp)
wget -O - -q http://www.wetteralarm.ch/uploads/tx_namicswawetterkarte/bilder/wetterkarten/all_klein.jpg > "$wetteralarm"
convert "$wetteralarm" -resize 178 "$wetteralarm"
if [[ $i -eq 2 ]];then
composite -gravity SouthEast -geometry +2+128 "$wetteralarm" "$tmpimage" "$tmpimage"
else
composite -gravity SouthEast -geometry +2+245 "$wetteralarm" "$tmpimage" "$tmpimage"
fi
rm "$wetteralarm"
fi
done
}
contains() {
list=("$1")
element="$2"
if [ "$(echo ${list[*]} | grep "$element")" == "" ];then
return 1
else
return 0
fi
}
# send onscreen-notfication if weather changed
# $1: message, new weather-state
osdNotify() {
if [ "$OSD" == "TRUE" ];then
if [[ -z "$last_state" ]] || [ "$last_state" != "$1" ];then
if command -v notify-send > /dev/null;then
notify-send "izulu" "$(gettext "$1")"
else
echo "notify-send not installed, but osd via -o requested." \
"Install libnotify-bin to use the osd."
fi
fi
last_state="$1"
fi
}
#choose randomly a wallpaper
#$1: wallpaper-category
#return: wallpaper to set
cycleWallpaper() {
local specific="$1"
local generic="$2"
local randomdir=""
case "$generic" in
"gen_sun")
randomdir="$RANDOMSUNDIR"
;;
"gen_cloud")
randomdir="$RANDOMCLOUDDIR"
;;
"gen_rain")
randomdir="$RANDOMRAINDIR"
;;
"gen_snow")
randomdir="$RANDOMSNOWDIR"
;;
*)
randomdir="$RANDOMMISCDIR"
;;
esac
if [[ -z "$randomdir" ]];then
flickrimg=$(getFlickrImage "$generic")
if [[ -z "$flickrimg" ]];then
setWallpaper "$specific" "$generic" "TRUE"
return 1
else
echo "$flickrimg"
return 0
fi
fi
# The IFS set to \n enables files with spaces
OLD_IFS=$IFS
IFS=$'\n'
# this gets all image files in randomdir and subdirs. The ${} around $randomdir is necessary to evaluate variables like ~
pictures=($(echo -e "$(find ${randomdir} -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image' | sed s"#.*\($randomdir.*\):.*#\1#"g | sort)"))
IFS=$OLD_IFS
chosen=$(shuf -i1-${#pictures[@]} -n1)
echo "${pictures[$chosen]}"
}
getFlickrImage() {
local generic="$1"
# flickriver sorts the flickr groups images randomly for us
local riverurl=""
case "$generic" in
"gen_sun")
riverurl="http://www.flickriver.com/groups/982364@N21/pool/random/"
;;
"gen_cloud")
riverurl="http://www.flickriver.com/groups/clouds-mildness/pool/random/"
;;
"gen_rain")
riverurl="http://www.flickriver.com/groups/387174@N22/pool/random/"
;;
"gen_snow")
riverurl="http://www.flickriver.com/groups/snow_pictures/pool/random/"
;;
"gen_wind")
riverurl="http://www.flickriver.com/groups/1159117@N24/pool/random/"
;;
*)
# misc, mainly fog
riverurl="http://www.flickriver.com/groups/fabulousfog/pool/random/"
;;
esac
local flickrpage=$(wget -O - --quiet $(wget -O - "$riverurl" --quiet | grep "class=\"noborder\" target=\"_blank\".*http://www.flickr.com/photos" | sed 's#.*href=\"\([^\"]*\)\".*#\1#g' | uniq | shuf -n 1))
local imagesizes=$(echo -e "$flickrpage" | grep modelExport: | tr "}" "\n")
for size in "k" "o" "h" "l";do
# not all flickr images provide every size, so we try to get the best one
# It is nicer to prefer a size with a specific width, that is why Original is not first
local imageurl=$(echo -e "$imagesizes" | grep "\"$size\"" | sed -e 's#.*\(c[0-9].staticflickr.com.*\).*"#https://\1#g' -e 's#\\##g' -e 's#\".*##')
if [[ -n "$imageurl" ]];then
break
fi
done
if [[ -z "$imageurl" ]];then
return 1
fi
if [[ -z "$FLICKRTMP" ]];then
FLICKRTMP=$(mktemp)
fi
if wget -O "$FLICKRTMP" "$imageurl" --quiet;then
echo "$FLICKRTMP"
else
return 1
fi
}
# Return true if we know it is night, and user did ctivate the night mode
# This will only work well if the local time is in the same timezone as the detected place
isNight() {
current_time=$(date "+%s")
sunrise=$(echo "$WEATHER_DATA" | jq -r '.daily.data[0].sunriseTime')
sunset=$(echo "$WEATHER_DATA" | jq -r '.daily.data[0].sunsetTime')
return $(echo "(! $current_time < $sunrise || $current_time > $sunset)" | bc -l)
}
#determine the city via the geoip-api
getCity() {
ipApiLookup=$(wget -O - -q "http://freegeoip.net/xml/")
local city=$(echo "$ipApiLookup" | xml_grep --text_only '/Response/City')
if command -v notify-send >/dev/null;then
notify-send -u low "izulu" "$city"
fi
echo $city
}
#determine the country via the geoip-api
getCountry() {
ipApiLookup=$(wget -O - -q "http://freegeoip.net/xml/")
local country=$(echo "$ipApiLookup" | xml_grep --text_only '/Response/CountryCode')
echo $country
}
#check in which environment we run to select a command to set a wallpaper
getWPCommand() {
#partly taken from xdg-open
if [ x"$DESKTOP_SESSION" = x"ubuntu" ] || [ x"$DESKTOP_SESSION" = x"ubuntu-2d" ];then
gsettings set org.gnome.desktop.background picture-options "stretched"
echo "gsettings set org.gnome.desktop.background picture-uri file://PLACEHOLDER"
elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ] || [ x"$DESKTOP_SESSION" = x"gnome" ];then
if command -v gnome-about > /dev/null; then
echo "gconftool --type string -s /desktop/gnome/background/picture_filename PLACEHOLDER"
else
gsettings set org.gnome.desktop.background picture-options "stretched"
echo "gsettings set org.gnome.desktop.background picture-uri file://PLACEHOLDER"
fi
elif [ x"$XDG_CURRENT_DESKTOP" = x"MATE" ];then
gsettings set org.mate.background picture-options "stretched"
echo "gsettings set org.mate.background picture-filename PLACEHOLDER"
elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then
echo "xfdesktop --reload PLACEHOLDER"
elif [ x"$XDG_CURRENT_DESKTOP" = x"KDE" ];then
echo "qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript 'var allDesktops = desktops();print (allDesktops);for (i=0;i<allDesktops.length;i++) {d = allDesktops[i];d.wallpaperPlugin = "org.kde.image";d.currentConfigGroup = Array(\"Wallpaper\", \"org.kde.image\", \"General\");d.writeConfig(\"Image\", \"file:///file://PLACEHOLDER\")}'"
elif command -v Esetroot > /dev/null; then
echo "Esetroot -scale PLACEHOLDER"
elif command -v feh > /dev/null; then
echo "feh --bg-scale --no-fehbg PLACEHOLDER"
elif command -v display > /dev/null; then
echo "display -window root PLACEHOLDER"
else
echo "gconftool --type string -s /desktop/gnome/background/picture_filename PLACEHOLDER"
fi
}
checkConfig() {
if [[ ! -d "$HOME/.izulu/" ]];then
mkdir "$HOME/.izulu/"
fi
if [[ ! -e "$HOME/.izulu/config" ]];then
echo "WPCOMMAND=\"\" #command to set the wallpaper
CITY=\"\"
LATITUDE=\"\"
LONGITUDE=\"\"
WIND=\"\"
SWISS_RADAR=\"\"
RANDOMSUNDIR=\"\" #Directories with pictures to randomly pick one
RANDOMCLOUDDIR=\"\"
RANDOMRAINDIR=\"\"
RANDOMSNOWDIR=\"\"
RANDOMMISCDIR=\"\"" > "$HOME/.izulu/config"
fi
}
readConfig() {
source "$HOME"/.izulu/config
}
# set default variables
TEMPERATURE_GRAVITY="SouthWest"
TEMPERATURE_MARGIN="+10+20"
checkConfig
readConfig
#read arguments
while [[ $# -gt 0 ]] ; do
parm="$1"
shift
case "$parm" in
-c | --city)
CITY="$1"
;;
-l | --latitude)
LATITUDE="${1%:*}"
LONGITUDE="${1#*:}"
;;
-d | --daemon)
DAEMON=TRUE
;;
-i | --interval)
INTERVAL="$1"
if [[ "$INTERVAL" -lt 900 ]];then
INTERVAL=900
fi
;;
-r | --random)
RANDOMLY=TRUE
;;
-n | --night)
NIGHT=TRUE
;;
-o | --osd)
OSD=TRUE
;;
-p | --preview)
PREVIEW=TRUE
;;
-t | --temperature)
TEMPERATURE=TRUE
;;
-w | --wind)
WIND=TRUE
;;
-tg | --temperature-gravity)
TEMPERATURE_GRAVITY="$1"
;;
-tm | --temperature-margin)
TEMPERATURE_MARGIN="$1"
;;
-co | --compat)
if [[ "$1" -eq "unity" ]];then
TEMPERATURE_GRAVITY="NorthEast"
TEMPERATURE_MARGIN="+10+40"
fi
;;
-gr | --german-radar)
GERMAN_RADAR=TRUE
;;
-sr | --swiss-radar)
SWISS_RADAR=TRUE
;;
-rd | --radar)
RADAR=TRUE
RADAROPTIONS=()
for option in $*;do
if [ "${option:0:1}" == "-" ];then
#this option doesn't belongs to the radarswitch anymore
break
else
RADAROPTIONS[${#RADAROPTIONS[*]}]="$option"
shift
fi
done
;;
--help)
echo "-c city, --city city:
Set the city with the relevant weather, e.g Berlin.
-l LAT:LON, --latitude LAT:LON:
Give the current position as latitude and longitude
-d, -daemon:
Enable daemon-mode, check the weather every 15 minutes.
-gr, --german-radar
Shortcut: All german rader images.
-i interval, --interval interval:
Specify a custom check-interval when in daemon-mode, e.g. 900 (seconds, also the minimun).
-n, --night:
Set another wallpaper at night.
-o, --osd:
Send a notification when weather changes.
-p, --preview
Add images showing the weather forecast.
-r, --random:
Choose the wallpaper randomly. If no directory is named in the config, it will try to get a fitting image from flickr.
-rd [warning|radar] [warning|radar] [germany|swiss], --radar [warning|radar] [warning|radar] [germany|swiss]:
Show a warning and/or a radarimage for a country. Wetteralarm (www.wetteralarm.ch) and Rain-Radar (meteoschweiz.admin.ch) for Switzerland, official warnings (http://www.dwd.de/) and a satellite-image (http://www.dlr.de/) for Germany.
-sr, --swiss-radar
Shortcut: All swiss rader images.
-t, --temperature
Show the temperature.
-tg gravity, --temperature-gravity gravity
Set the gravity anchor of the temperature display. Possible choices are NorthWest, North, NorthEast, West, Center, East, SouthWest, South, SouthEast. See also http://www.imagemagick.org/script/command-line-options.php#gravity
-tm margin, --temperature-margin margin
Set the margin the temperature display shall have from the screen borders. The format for margin is +x+y, for example '+10+30'.
-co desktop, --compat desktop
Set several default parameters for compatibility with the defaults of a specific desktop environment. The sole possible value for desktop so far is 'unity', and it will move the temparature display to the upper right corner."
exit 0
;;
--version)
echo "izulu 1.1"
exit 0
;;
esac
done
TEXTDOMAIN="izulu"
TEXTDOMAINDIR="/usr/share/locale/"
export TEXTDOMAIN
export TEXTDOMAINDIR
if [ "$WPCOMMAND" == "" ];then
WPCOMMAND="$(getWPCommand)"
fi
if [ "$CITY" == "" -a -z "$LATITUDE" ];then
CITY="$(getCity)"
if [ "$CITY" == "" ];then
echo "Error: Your location is not discoverable. Please specify a city with 'izulu -c cityname' or with 'izulu -l LAT:LON'." >&2
exit 1
fi
fi
fillWeatherData
chooseWallpaper "$(getWeather)"
#daemon-mode
daemon() {
while true;do
if [[ -z "$INTERVAL" ]];then
INTERVAL=3600
fi
sleep $INTERVAL
fillWeatherData
chooseWallpaper "$(getWeather)"
done
}
if [ "$DAEMON" == "TRUE" ];then
daemon
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment