Skip to content

Instantly share code, notes, and snippets.

@ChrisHeerschap
Last active October 18, 2019 12:12
Show Gist options
  • Save ChrisHeerschap/75fbc25925c2281f2b52c1b1e715853e to your computer and use it in GitHub Desktop.
Save ChrisHeerschap/75fbc25925c2281f2b52c1b1e715853e to your computer and use it in GitHub Desktop.
Zwift scripts
Requirements:
============
I'm not even sure all the requirements, I might miss some of them.
* GNU date from Homebrew
* curl and xmllint - might be part of base MacOS install, or might be XCode. Dunno.
Put both scripts in the same directory - I use the "bin" subdir under my homedir. Call the "zwift" script.
Ride On!
#!/bin/bash
# shellcheck disable=SC1117
# Launcher for Zwift that gives you the option to change world easily.
# Location of the Zwift preferences file
prefs=~/Documents/Zwift/prefs.xml
# Check to see if the previous world is set
prev=$(awk -F '[><]' '/WORLD/ {print $3}' $prefs)
# Set previous to default if I didn't find it in the prefs.xml
if [[ -z $prev ]]
then
prev="Default"
fi
# Get the currently active world
# Requires "zwift-world" script
current=$("${0}-world")
# Display a menu
echo "Choose your Zwift course:"
echo "========================"
echo " 1. Watopia"
echo " 2. Richmond"
echo " 3. London"
echo " 4. New York City"
echo " 5. Innsbruck"
echo " C. Currently active ($current)"
echo " P. Previous ($prev)"
# Initialize an invalid answer
answer='x'
# Loop through the prompt until we get a valid answer
until [[ $answer =~ [1-5CcPp] || -z $answer ]]
do
read -rp "Enter your selection: " answer
done
# Act based on the answer given.
case $answer in
[1-5])
# A valid world has been chosen, use that.
insert="<WORLD>${answer}</WORLD>"
sedcmd="$(echo -e "/WORLD/d; 2a\\ \n\\ ${insert}\n ")"
;;
[cC])
# Go with the currently active Zwift world.
sedcmd='/WORLD/d'
;;
[pP]|'')
# Stick with what I rode last.
sedcmd=''
;;
*)
# This was more useful in the initial debugging of the script
# and shouldn't happen in normal conditions.
echo "How did your special brand of stupid make it this far?"
exit 1
;;
esac
# If we've specified a world, run the command to specify it.
if [[ -n $sedcmd ]]
then
cp ${prefs} ${prefs}.bak
# xmllint is used to test that we create valid XML
if sed "$sedcmd" ${prefs} | xmllint - > ${prefs}.tmp
then
mv ${prefs}.tmp ${prefs}
else
echo "ERROR: couldn't process, exiting."
rm ${prefs}.tmp
mv ${prefs}.bak ${prefs}
exit 1
fi
fi
# Fire up Zwift. For some reason, the "Let's Go" button will require two or three clicks to make it react.
osascript -e 'tell application "Zwift" to activate'
#!/bin/bash
# Thanks to Matt Bafford for finding the web URL for the Zwift map schedule.
SCHEDULE='http://cdn.zwift.com/gameassets/MapSchedule_v2.xml'
# This is the pattern to look for that specifies which worlds are active and when they become active
worldpat='<appointment '
# This requires GNU date which can be installed with Homebrew.
gdate='/usr/local/bin/gdate'
# Check if gdate is installed
if [[ -x $gdate ]]
then
now=$($gdate +%s)
else
echo "ERROR: I need GNU date. Please install with Homebrew"
fi
# Initialize the previous value for the world
prevworld='ERROR'
# Grab the schedule and process the dates
curl -s $SCHEDULE | awk -F '"' "/${worldpat}/ {print \$4, \$2}" | sort | while read -r startdate world
do
# Get the time of the start of this world in epoch seconds
start=$($gdate -d "${startdate}" +%s)
# If the start time hasn't happened yet, then it's the next world
if (( start > now ))
then
# Echo the previous world and break out
echo "$prevworld"
break
fi
# Set the previous world
prevworld="$world"
done
@mbafford
Copy link

Thank you for this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment