web/scripts/deploy-ebook-to-www
2019-06-20 16:21:26 -05:00

235 lines
8.2 KiB
Bash
Executable file

#!/bin/bash
usage(){
fmt <<EOF
DESCRIPTION
Deploy a Standard Ebook source repository to the web.
USAGE
deploy-ebook-to-www [-v,--verbose] [-g,--group GROUP] [--webroot WEBROOT] [--weburl WEBURL] DIRECTORY [DIRECTORY...]
DIRECTORY is a bare source repository.
GROUP is a groupname. Defaults to "se".
WEBROOT is the path to your webroot. Defaults to "/standardebooks.org".
WEBURL is the URL the website is served on. Defaults to "https://standardebooks.org".
EOF
exit
}
die(){ printf "\033[0;7;31mError:\033[0m %s\n" "${1}" 1>&2; exit 1; }
require(){ command -v "$1" > /dev/null 2>&1 || { suggestion=""; if [ -n "$2" ]; then suggestion=" $2"; fi; die "$1 is not installed.${suggestion}"; } }
# End boilerplate
verbose="false"
group="se"
webRoot="/standardebooks.org"
webUrl="https://standardebooks.org"
if [ $# -eq 0 ]; then
usage
fi
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
usage ;;
-v|--verbose)
verbose="true"
shift 1
;;
-g|--group)
[ -n "$2" ] || die "Group cannot be empty."
group="$2"
shift 2
;;
--webroot)
[ -n "$2" ] || die "Web root can't be empty."
webRoot="$2"
shift 2
;;
--weburl)
[ -n "$2" ] || die "Web URL can't be empty."
webUrl="$2"
shift 2
;;
*) break ;;
esac
done
if ! [ "$(getent group "${group}")" ]; then
die "Group ${group} does not exist. Either use --group or create the group."
fi
if ! [ -d "${webRoot}" ]; then
die "${webRoot} does not exist or is not a directory."
fi
# Check for dependencies
require "convert" "Try: apt-get install imagemagick"
require "rsvg-convert" "Try: apt-get install librsvg2-bin"
require "git" "Try: apt-get install git"
require "php" "Try: apt-get install php-cli"
require "se" "Read: https://github.com/standardebooks/tools"
scriptsDir="$(dirname "$(readlink -f "$0")")"
if ! [ -x "${scriptsDir}"/reset-php-fpm-opcache ]; then
die "\"${scriptsDir}\"/reset-php-fpm-opcache is not an executable file."
fi
if ! [ -f "${scriptsDir}"/generate-opds.php ]; then
die "\"${scriptsDir}\"/generate-opds.php\" is not a file or could not be found."
fi
if ! [ -f "${scriptsDir}"/generate-rss.php ]; then
die "\"${scriptsDir}\"/generate-rss.php\" is not a file or could not be found."
fi
mkdir -p "${webRoot}"/www/images/covers/
for dir in "$@"
do
if [ "${dir}" = "" ]; then
continue
fi
repoDir=$(realpath "${dir%/}")
baseName=$(basename "${repoDir}")
if [ "${baseName}" = ".git" ]; then
continue
fi
if [ ! -d "${repoDir}" ]; then
die "Invalid repo root: ${repoDir}"
fi
if ! pushd "${repoDir}" > /dev/null; then
echo "Couldn't cd into ${repoDir}. Skipping."
continue
fi
if [ "${verbose}" = "true" ]; then
printf "Entering %s\n" "${repoDir}"
fi
if git show HEAD:src/epub/content.opf | grep --quiet --extended-regexp "<dc:date>1900-01-01T00:00:00Z</dc:date>"; then
printf "Looks like a draft ebook, skipping\n"
continue
fi
webDir=$(git show HEAD:src/epub/content.opf | grep --only-matching --extended-regexp "<dc:identifier id=\"uid\">url:https://standardebooks.org/ebooks/[^<]+<\/dc:identifier>" | sed --regexp-extended "s/<[^>]+?>//g" | sed --regexp-extended "s/^url:https:\/\/standardebooks.org\/ebooks\/?//")
if [ "${webDir}" = "" ]; then
die "Empty webdir!"
fi
workDir=$(mktemp -d)
imgWorkDir=$(mktemp -d)
webDir="${webRoot}/www/ebooks/${webDir}"
if [ "${verbose}" = "true" ]; then
printf "Generating cover image for web ... "
fi
urlSafeIdentifier=$(git show HEAD:src/epub/content.opf | grep --only-matching --extended-regexp "<dc:identifier id=\"uid\">url:https://standardebooks.org/ebooks/[^<]+<\/dc:identifier>" | sed --regexp-extended "s/<[^>]+?>//g" | sed --regexp-extended "s|url:https://standardebooks.org/ebooks/||g" | sed --regexp-extended "s|/|_|g")
# Build the hero image for individual ebook pages
git show HEAD:images/cover.jpg > "${imgWorkDir}/${urlSafeIdentifier}.jpg"
cp "${imgWorkDir}/${urlSafeIdentifier}.jpg" "${imgWorkDir}/${urlSafeIdentifier}@2x.jpg"
# Resize and crop the image to 2156 width, 720 height, and starting at the coords 0,1078
convert -resize "1078" -crop "1078x359+0+539" -sampling-factor 4:2:0 -strip -quality 75 -colorspace RGB -interlace JPEG "${imgWorkDir}/${urlSafeIdentifier}.jpg" "${imgWorkDir}/${urlSafeIdentifier}-hero.jpg"
convert -resize "2156" -crop "2156x718+0+1078" -sampling-factor 4:2:0 -strip -quality 75 -colorspace RGB -interlace JPEG "${imgWorkDir}/${urlSafeIdentifier}@2x.jpg" "${imgWorkDir}/${urlSafeIdentifier}-hero@2x.jpg"
# Build the cover image thumbnail
git show HEAD:images/cover.jpg > "${imgWorkDir}/${urlSafeIdentifier}.jpg"
git show HEAD:images/cover.svg > "${imgWorkDir}/${urlSafeIdentifier}.svg"
sed -i "s/cover\.jpg/${urlSafeIdentifier}\.jpg/g" "${imgWorkDir}/${urlSafeIdentifier}.svg"
cp "${imgWorkDir}/${urlSafeIdentifier}.svg" "${imgWorkDir}/${urlSafeIdentifier}@2x.svg"
# Due to a bug in `convert` we have to use rsvg-convert to convert SVG to PNG, then work on the PNG with `convert`.
rsvg-convert --keep-aspect-ratio --format png --output "${imgWorkDir}/${urlSafeIdentifier}.png" "${imgWorkDir}/${urlSafeIdentifier}.svg"
rsvg-convert --keep-aspect-ratio --format png --output "${imgWorkDir}/${urlSafeIdentifier}@2x.png" "${imgWorkDir}/${urlSafeIdentifier}@2x.svg"
# Resize and compress the image (formula from Google Page Speed Insights)
convert -resize "196" -sampling-factor 4:2:0 -strip -quality 75 -colorspace RGB -interlace JPEG "${imgWorkDir}/${urlSafeIdentifier}.png" "${imgWorkDir}/${urlSafeIdentifier}.jpg"
convert -resize "392" -sampling-factor 4:2:0 -strip -quality 75 -colorspace RGB -interlace JPEG "${imgWorkDir}/${urlSafeIdentifier}@2x.png" "${imgWorkDir}/${urlSafeIdentifier}@2x.jpg"
mv "${imgWorkDir}/${urlSafeIdentifier}@2x.jpg" "${imgWorkDir}/${urlSafeIdentifier}-cover@2x.jpg"
mv "${imgWorkDir}/${urlSafeIdentifier}.jpg" "${imgWorkDir}/${urlSafeIdentifier}-cover.jpg"
sudo chgrp --preserve-root --recursive "${group}" "${imgWorkDir}/${urlSafeIdentifier}"*
sudo chmod --preserve-root --recursive g+w "${imgWorkDir}/${urlSafeIdentifier}"*
if [ "${verbose}" = "true" ]; then
printf "Done.\n"
printf "Building ebook ... "
fi
git clone --quiet "${repoDir}" "${workDir}"
mkdir "${workDir}/dist"
# Build the ebook
if ! se build --output-dir="${workDir}/dist" --check --kindle --kobo --covers "${workDir}"; then
rm --preserve-root --recursive --force "${workDir}"
die "Error building ebook, stopping deployment."
fi
if [ "${verbose}" = "true" ]; then
printf "Done.\n"
fi
# Delete the contents of the old webdir
rm --preserve-root --recursive --force "${webDir}"
# Re-create the webdir
mkdir -p "${webDir}"
# Move contents of the work dir over
mv "${workDir}"/* "${webDir}/"
# Move the cover images over
mv "${imgWorkDir}/${urlSafeIdentifier}"*.jpg "${webRoot}/www/images/covers/"
# Delete the now-empty work dir (empty except for .git)
rm --preserve-root --recursive --force "${workDir}" "${imgWorkDir}"
sudo chgrp --preserve-root --recursive "${group}" "${webDir}"
sudo chmod --preserve-root --recursive g+ws "${webDir}"
sudo chgrp --preserve-root --recursive "${group}" "${webRoot}/www/images/covers/"
sudo chmod --preserve-root --recursive g+ws "${webRoot}/www/images/covers/"
if [ "${verbose}" = "true" ]; then
printf "Flushing PHP-FPM opcache and apcu cache ... "
fi
"${scriptsDir}"/reset-php-fpm-opcache standardebooks.org
if [ "${verbose}" = "true" ]; then
printf "Done.\n"
fi
popd > /dev/null || die "Couldn't pop directory."
done
# Build the OPDS catalog
if [ "${verbose}" = "true" ]; then
printf "Rebuilding OPDS catalog ... "
fi
bash -c "php \"${scriptsDir}\"/generate-opds.php --webroot \"${webRoot}\" --weburl \"${webUrl}\" > \"${webRoot}\"/www/opds/all.xml; export XMLLINT_INDENT=\$(printf \"\\t\") && xmllint --c14n \"${webRoot}\"/www/opds/all.xml | (printf \"%s\\n\" \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\" && cat) | xmllint --output \"${webRoot}\"/www/opds/all.xml --format -"
if [ "${verbose}" = "true" ]; then
printf "Done.\n"
fi
# Build the new releases RSS feed
if [ "${verbose}" = "true" ]; then
printf "Rebuilding new releases RSS feed ... "
fi
bash -c "php \"${scriptsDir}\"/generate-rss.php --webroot \"${webRoot}\" --weburl \"${webUrl}\" > \"${webRoot}\"/www/rss/new-releases.xml"
if [ "${verbose}" = "true" ]; then
printf "Done.\n"
fi