#!/usr/bin/env bash
C_YELLOW="$(tput setaf 3)"
C_RED="$(tput setaf 1)"
C_BOLD="$(tput bold)"
C_RESET="$(tput sgr0)"

# last updated 2025-05-16 20:21
xml_header='<?xml version="1.0" encoding="UTF-8"?>'
urlset_props='xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"'
domain='https://yet.anotherpage.ch'

content_root="${1:-/srv/yetanotherpage/data/www}"
outfile="${2:-/srv/yetanotherpage/data/www/sitemap.xml}"

content_root="$(realpath "$content_root")"

cleanup(){
    rm -f "${outcache}"
}

log(){
    echo "$@" >&2
}

check_lastmod(){
    current_lastmod="$(date -u -r "$1" +%s)"
    if [ "$current_lastmod" -gt "$lastmod" ]; then
        lastmod="$current_lastmod"
    fi
}

smart_lastmod(){
    lastmod="0"
    check_lastmod "$1"
    # update checks as needed here
    [ "$1" == "$content_root/posts.html" ] && check_lastmod "$content_root/../assets/components/posts.html"

    # reformat from UNIX to ISO & print
    echo "$(date -u -d "@$lastmod" +%Y-%m-%d)"
}

if ! type xmlstarlet &>/dev/null; then
    log "${C_RED}You don't have an xmlstarlet binary, so you'll either have to bring your own xml escaper or install it$C_RESET"
    exit 1
fi

xmlesc(){
    xmlstarlet esc
}

if [ ! -d "$content_root" ]; then
    log "$C_RED$content_root is not a directory$C_RESET"
    exit 1
fi

outcache="$(mktemp)"

if [ -e "$outcache" ]; then
    if [ -w "$outcache" ]; then
        : > "$outcache"
    else
        log "${C_RED}output not writable$C_RESET"
        cleanup
        exit 1
    fi
fi

echo "$xml_header" >> "$outcache"
echo "<urlset $urlset_props>" >> "$outcache"

find "$content_root" '(' -name '*.html' -o -name '*.txt' ')' '!' '(' -name "robots.txt" ')' -print0 | \
while IFS= read -r -d '' path; do
    lastmod="$(smart_lastmod "$path")"
    virtual="${path#"$content_root"}"
    [[ $virtual == *index.html ]] && virtual="${virtual%index.html}"
    url="$domain$virtual"
    log "$C_BOLD$C_YELLOW- $C_RESET$url $C_YELLOW@$C_RESET $lastmod"
    xml_val="$(echo "$url" | xmlesc)"
    echo "  <url>" >> "$outcache"
    echo "    <loc>$xml_val</loc>" >> "$outcache"
    echo "    <lastmod>$lastmod</lastmod>" >> "$outcache"
    echo "  </url>" >> "$outcache"
done

echo "</urlset>" >> "$outcache"

mv "${outcache}" "${outfile}"; move_error=$?
if [ "${move_error}" -gt "0" ]; then
    log "moving to outfile failed, check permissions?"
    cleanup
    exit 1
fi
