Files
fuzic/src/sh/cache.sh
2025-09-11 15:57:06 +02:00

247 lines
7.4 KiB
Bash

# This implements the caching functionalities. The cache is stored under
# `CACHEDIR` defined below, and organized as follows (all paths relative to
# `CAHCEDIR`) ./<type>/radix(mbid)/<file>. Here, type is one of `TYPE_ARTIST`,
# `TYPE_RELEASEGROUP`, or `TYPE_RELEASE`. The string `radix(mbid)` is the radix
# encoded MusicBrainz ID of given type (see method below). Finally <file> is a
# filename to hold the respective data in the json format. Currently, the data
# is stored as follows:
# ./artist/radix(mbid)/musicbrainz.json MusicBrainz artist data
# ./artist/radix(mbid)/discogs.json Discogs artist data
# ./artist/radix(mbid)/wikidata.json Wikidata artist data
# ./artist/radix(mbid)/enwikipedia.json Wikipedia artist data
# ./artist/radix(mbid)/releasegroups.json Release groups of artist
# ./releasegroup/radix(mbid)/musicbrainz.json MusicBrainz release-group data
# ./releasegroup/radix(mbid)/releases.json Releases in release group
# ./release/radix(mbid)/musicbrainz.json MusicBrainz release data
if [ ! "${CACHE_LOADED:-}" ]; then
# Base path for cache
CACHEDIR="$HOME/.cache/$APP_NAME"
# Directory names for cache types
TYPE_ARTIST="artist"
TYPE_RELEASEGROUP="releasegroup"
TYPE_RELEASE="release"
# Filenames for cache entries
ARTIST_FILENAME="musicbrainz.json"
ARTIST_RELEASEROUPS_FILENAME="releasegroups.json"
ARTIST_DISCOGS_FILENAME="discogs.json"
ARTIST_WIKIDATA_FILENAME="wikidata.json"
ARTIST_ENWIKIPEDIA_FILENAME="enwikipedia.json"
RELEASEGROUP_FILENAME="musicbrainz.json"
RELEASEGROUP_RELEASES_FILENAME="releases.json"
RELEASE_FILENAME="musicbrainz.json"
export CACHEDIR TYPE_ARTIST TYPE_RELEASEGROUP TYPE_RELEASE ARTIST_FILENAME \
ARTIST_RELEASEROUPS_FILENAME ARTIST_DISCOGS_FILENAME \
ARTIST_WIKIDATA_FILENAME ARTIST_ENWIKIPEDIA_FILENAME \
RELEASEGROUP_FILENAME RELEASEGROUP_RELEASES_FILENAME RELEASE_FILENAME
export CACHE_LOADED=1
fi
# Radix transform string
#
# @argument $1: some string
__radix() {
echo "$1" | awk -F "" '{ print $1$2$3$4"/"$5$6$7$8"/"$0 }'
}
# Radix transform strings (batch)
#
# Here, the input is read line-by-line from stdin.
__radix_batch() {
cat | awk -F "" '{ print $1$2$3$4"/"$5$6$7$8"/"$0 }'
}
# Super wrapper to print json data from cache
#
# argument $1: type
# argument $2: MusicBrainz ID
# argument $3: Filename of json file
__get_json() {
f="$CACHEDIR/$1/$(__radix "$2")/$3"
[ -f "$f" ] || return
cat "$f"
}
# Super wrapper to store json data in cache
#
# argument $1: type
# argument $2: MusicBrainz ID
# argument $3: Filename of json file
__put_json() {
dir="$CACHEDIR/$1/$(__radix "$2")"
[ -d "$dir" ] || mkdir -p "$dir"
f="$dir/$3"
tmpf=$(mktemp)
cat >"$tmpf"
[ -s "$tmpf" ] && mv "$tmpf" "$f" || printf "{}" >"$f"
}
# Print MusicBrainz data of given artist from cache
#
# @argument $1: MusicBrainz artist ID
cache_get_artist() {
__get_json "$TYPE_ARTIST" "$1" "$ARTIST_FILENAME"
}
# Print release groups (MusicBrainz) of given artist from cache
#
# @argument $1: MusicBrainz artist ID
cache_get_artist_releasegroups() {
__get_json "$TYPE_ARTIST" "$1" "$ARTIST_RELEASEROUPS_FILENAME"
}
# Print Discogs data of given artist from cache
#
# @argument $1: MusicBrainz artist ID
cache_get_artist_discogs() {
__get_json "$TYPE_ARTIST" "$1" "$ARTIST_DISCOGS_FILENAME"
}
# Print Wikipedia data of given artist from cache
#
# @argument $1: MusicBrainz artist ID
cache_get_artist_enwikipedia() {
__get_json "$TYPE_ARTIST" "$1" "$ARTIST_ENWIKIPEDIA_FILENAME"
}
# Print Wikidata data of given artist from cache
#
# @argument $1: MusicBrainz artist ID
cache_get_artist_wikidata() {
__get_json "$TYPE_ARTIST" "$1" "$ARTIST_WIKIDATA_FILENAME"
}
# Store MusicBrainz data of given artist in cache
#
# @argument $1: MusicBrainz artist ID
#
# This methods reads the data to be stored from stdin.
cache_put_artist() {
cat | __put_json "$TYPE_ARTIST" "$1" "$ARTIST_FILENAME"
}
# Store release groups (MusicBrainz) of given artist in cache
#
# @argument $1: MusicBrainz artist ID
#
# This methods reads the data to be stored from stdin.
cache_put_artist_releasegroups() {
cat | __put_json "$TYPE_ARTIST" "$1" "$ARTIST_RELEASEROUPS_FILENAME"
}
# Append release groups (MusicBrainz) of given artist to existing file in cache
#
# @argument $1: MusicBrainz artist ID
#
# This methods reads the data to be stored from stdin.
cache_append_artist_releasegroups() {
tmpf=$(mktemp)
cat >"$tmpf"
updated=$(mktemp)
f="$CACHEDIR/$TYPE_ARTIST/$(__radix "$1")/$ARTIST_RELEASEROUPS_FILENAME"
$JQ --slurpfile n "$tmpf" '."release-groups" += ($n[0]|."release-groups")' "$f" >"$updated" && mv "$updated" "$f"
rm -f "$tmpf"
}
# Store Discogs data of given artist to cache
#
# @argument $1: MusicBrainz artist ID
cache_put_artist_discogs() {
cat | __put_json "$TYPE_ARTIST" "$1" "$ARTIST_DISCOGS_FILENAME"
}
# Store Wikipedia data of given artist to cache
#
# @argument $1: MusicBrainz artist ID
cache_put_artist_enwikipedia() {
cat | __put_json "$TYPE_ARTIST" "$1" "$ARTIST_ENWIKIPEDIA_FILENAME"
}
# Store Wikidata data of given artist to cache
#
# @argument $1: MusicBrainz artist ID
cache_put_artist_wikidata() {
cat | __put_json "$TYPE_ARTIST" "$1" "$ARTIST_WIKIDATA_FILENAME"
}
# Print MusicBrainz data of given release group from cache
#
# @argument $1: MusicBrainz release-group ID
cache_get_releasegroup() {
__get_json "$TYPE_RELEASEGROUP" "$1" "$RELEASEGROUP_FILENAME"
}
# Print releases (MusicBrainz) in release group from cache
#
# @argument $1: MusicBrainz release-group ID
cache_get_releasegroup_releases() {
__get_json "$TYPE_RELEASEGROUP" "$1" "$RELEASEGROUP_RELEASES_FILENAME"
}
# Store MusicBrainz data of given release group in cache
#
# @argument $1: MusicBrainz release-group ID
cache_put_releasegroup() {
cat | __put_json "$TYPE_RELEASEGROUP" "$1" "$RELEASEGROUP_FILENAME"
}
# Store releases (MusicBrainz) of given release group in cache
#
# @argument $1: MusicBrainz release-group ID
cache_put_releasegroup_releases() {
cat | __put_json "$TYPE_RELEASEGROUP" "$1" "$RELEASEGROUP_RELEASES_FILENAME"
}
# Append releases (MusicBrainz) of given release group to existing file in
# cache
#
# @argument $1: MusicBrainz release-group ID
cache_append_releasegroup_releases() {
tmpf=$(mktemp)
cat >"$tmpf"
updated=$(mktemp)
f="$CACHEDIR/$TYPE_RELEASEGROUP/$(__radix "$1")/$RELEASEGROUP_RELEASES_FILENAME"
$JQ --slurpfile n "$tmpf" '."releases" += ($n[0]|."releases")' "$f" >"$updated" && mv "$updated" "$f"
rm -f "$tmpf"
}
# Print MusicBrainz data of given release from cache
#
# @argument $1: MusicBrainz release ID
cache_get_release() {
__get_json "$TYPE_RELEASE" "$1" "$RELEASE_FILENAME"
}
# Store MusicBrainz data of given release in cache
#
# @argument $1: MusicBrainz release ID
cache_put_release() {
cat | __put_json "$TYPE_RELEASE" "$1" "$RELEASE_FILENAME"
}
# Print all MusicBrainz cache paths to the files specified by their IDs
#
# @argument $1: type
#
# This method reads from stdin any number of MusicBrainz IDs of objects of the
# specified type, and prints the file paths.
cache_get_file_batch() {
case "$1" in
"$TYPE_ARTIST") fn="$ARTIST_FILENAME" ;;
"$TYPE_RELEASEGROUP") fn="$RELEASEGROUP_FILENAME" ;;
"$TYPE_RELEASE") fn="$RELEASE_FILENAME" ;;
*) return 1 ;;
esac
cat |
__radix_batch |
awk -v dir="$CACHEDIR/$1/" -v f="/$fn" '{ print dir $0 f }'
}
# Print MusicBrainz ID associated to the file paths
#
# This reads from stdin any number of paths (one per line)
cache_mbid_from_path_batch() {
cat | awk -F "/" '{ print $(NF-1) }'
}