Back That Thang Up!
The software app Brewfather is an amazing tool. You can easily build recipes, create equipment profiles, water profiles, keep inventory and connect monitoring devices like iSpindel.
I stumbled upon a problem though. What happens if a recipe mistakenly changes or gets deleted? The only option I could find was to manually download a pdf, BeerXM or Brewfather recipe JSON.
So I decided to put some of my nerdy skills to use and create a script to back up all of our recipes. Anyone can use it, you just need to create an API key.
#!/bin/bash
# MIT License
#
# Copyright (c) 2022 RLG
#
# Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
#
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE.
########################################################
#
# CANNOT USE SH!!!!! NEWLINES NOT FORMED CORRECTLY!!!
#
########################################################
# Environment variable should be set
# Add to ~/.bashrc (or ~/.bash_profile, ~/.shrc, ~/.cshrc, etc.)
# export USERID={super_secret_key}
# export APIKEY={super_secret_key}
# source ~/.bashrc
########################################################
#
# https://docs.brewfather.app/api
#
########################################################
#USERID=xyz123
#APIKEY=1234567890123456789012345678901234567890abcd
BASE64=$(echo -n "$USERID":"$APIKEY" | base64 | tr -d '\r\n');
########################################################
########################################################
# Retrieve batch of json records
get_batch () {
RETVAL=$(curl -X 'GET' \
"https://api.brewfather.app/v2/recipes$1" \
-H "Authorization: Basic $BASE64" \
-H 'accept: application/json' \
-H 'Content-Type: application/json');
echo "$RETVAL";
}
tar_up () {
# Set name file archive
arc_name="Brewfather-$1.tar.gz";
cd "$2" || exit;
tar -czf "$2/$arc_name" "arc/"*;
# Find and remove archives older than 180 days
find "$2/"*.gz -type f -mtime +180 -exec rm {} \;
}
DATENAME=$( date +"%Y-%b-%d" );
DIRPATH="/path/to/Brewfather/directory"
COUNTER=0;
ITERATOR=0;
LASTID="START";
LENGTH="0";
LIMIT=50;
BATCH="$( get_batch '?limit='$LIMIT'&complete=True' )";
# Make temporary directory
mkdir $DIRPATH/arc;
# Stop when empty array return
while [[ "${BATCH}" != '[]' ]];
do
# Get length of batch array
LENGTH="$( echo "$BATCH" | jq 'length' )";
# While LastID is not null and iteration is less than length of array
while [[ -z "${LASTID}" || $ITERATOR -lt $LENGTH ]];
do
# Set last ID
LASTID="$( echo "$BATCH" | jq -r '.['$ITERATOR']._id' )";
# Get name
recipename="$( echo "$BATCH" | jq -r '.['$ITERATOR'].name' )";
# Write contents to file with name
echo "$BATCH" | jq -r '.['$ITERATOR']' >> "${DIRPATH}/arc/$recipename.json";
# Increment
ITERATOR=$(( ITERATOR + 1 ));
COUNTER=$(( COUNTER + 1 ));
done
# Get next batch
ITERATOR=0;
BATCH="$( get_batch '?limit='"$LIMIT"'&complete=True&start_after='"$LASTID" )";
done
tar_up "$DATENAME" "$DIRPATH";
# Remove temporary directory
rm -rf $DIRPATH/arc;
echo $COUNTER "Recipes copied";
Enjoy!