discogarchive: yeah I redid the whole thing basically

This commit is contained in:
yosh 2024-04-05 18:12:38 -04:00
parent a71970f1c6
commit 9180519e45
1 changed files with 228 additions and 109 deletions

View File

@ -20,136 +20,255 @@ fail() {
exit 1
}
# transform the escapes html entities that bandcamp has in that one thing
# into unescaped versions, so we can put it through jq
unescapehtml() {
sed '
s/"/"/g
s/'/'\''/g
s/&#60;/</g
s/&#62;/>/g
s/&#38;/\&/g
'
sed 's/&#34;/"/g ; s/&#39;/'\''/g ; s/&#60;/</g ; s/&#62;/>/g ; s/&#38;/\&/g'
}
# for release escaping
escapehtml() {
sed 's/&/\&amp;/g ; s/</\&lt;/g ; s/>/\&gt;/g ; s/"/\&quot;/g ; s/'\''/\&#39/g'
}
# inserts into a section at index after a url
# $1: section
# $2: index (0-indexed)
# $3: string
insert_into_section() {
index="$2"
case "$index" in
end) index_str='/^$' ;;
*) index_str="+$index" ;;
esac
>/dev/null ed DESCRIPTION.html <<-EOF
/<br><div><b>$section
$index_str
i
$3
.
wq
EOF
}
# gets all from a section
get_section() {
awk -v h="$1" -v RS="" -v FS='\n' '$1 ~ h' DESCRIPTION.html
}
# checks if release link is contained or not
# returns num:line if it is
is_contained() {
get_section "Contained Releases" | grep -nF "href=\"$1\""
}
is_uncontained() {
get_section "Uncontained Releases" | grep -nF "href=\"$1\""
}
# move a link from uncontained to contained if it exists in uncontained
# uses $last_contained
# $1 = url
move_from_uncontained() {
if conline=$(is_contained "$last_contained"); then
conline="$(grep -nF "${conline#*:}" DESCRIPTION.html)"
else
conline="/<br><div><b>Contained Releases"
fi
>/dev/null ed DESCRIPTION.html <<-EOF
${unline%%:*}m${conline%%:*}
wq
EOF
}
clean() {
trap 'exit' INT HUP QUIT TERM EXIT
[ -f "$HTML_FILE" ] && rm -f "$HTML_FILE"
[ -f "$json" ] && rm -f "$json"
[ -f "${DISCOG_PAGE:-}" ] && rm -f "$DISCOG_PAGE"
[ -f "${RELEASE_PAGE:-}" ] && rm -f "$RELEASE_PAGE"
[ -f "${JSON_HEAD:-}" ] && rm -f "$JSON_HEAD"
[ -f "${JSON_TRALBUM:-}" ] && rm -f "$JSON_TRALBUM"
exit
}
trap 'clean' INT HUP QUIT TERM EXIT
# OPTIONS #
no_download=""
while getopts :n OPT; do
no_download="" only_download="" skip_contained="" force_desc=""
while getopts :nds OPT; do
case $OPT in
n) no_download=1 ;; # don't download files, just make the description.html
d) only_download=1 ;; # only download files, don't make description.html
s) skip_contained=1 ;; # skip known albums, will insert uncontained -> contained ones after "last contained album"
*) fail "unknown option: -$OPTARG" ;;
esac
done
shift "$((OPTIND - 1))"
# END OPTIONS #
case $1 in
*.bandcamp.com*) : ;;
*) fail 'Please use the *.bandcamp.com link instead of any custom domains!' ;;
esac
IFS="/" read -r _ _ BANDCAMP_DOMAIN _ <<-EOF
$1
# SETUP #
# creates a NEWLINE-deliminated list of all bandcamp domains in question
BANDCAMP_DOMAINS=$(awk -v RS='/| ' '$1 ~ "bandcamp.com"' <<-EOF
$*
EOF
mkdir -p "$BANDCAMP_DOMAIN"; cd "$BANDCAMP_DOMAIN"
logdir="${XDG_DATA_HOME:-$HOME/.local/share}/discogarchive"
mkdir -p "$logdir"
)
DISCOG_PAGE=$(mktemp)
RELEASE_PAGE=$(mktemp)
JSON_HEAD=$(mktemp)
JSON_TRALBUM=$(mktemp)
## END SETUP
HTML_FILE="/tmp/$BANDCAMP_DOMAIN.html"
BASEURL="https://$BANDCAMP_DOMAIN"
# MAIN LOOP #
for BANDCAMP_DOMAIN in $BANDCAMP_DOMAINS; do
cd ~/data/discographies # normalized path ig
is_existing_discog=""
if [ -d "$BANDCAMP_DOMAIN" ]; then
is_existing_discog=1
fi
mkdir -p "$BANDCAMP_DOMAIN"; cd "$BANDCAMP_DOMAIN"
# SOCIALS #
errecho 'input artist socials in KEY=VALUE format. blank line to continue. bandcamp is already filled
common shorthands:
web=website, sc=soundcloud, yt=youtube, tw=twitch, tr=twitter, mx=mixcloud,
ig=instagram, sp=spotify, lt=Linktree, ch=Cohost'
socials="<a href=\"$BASEURL\" rel=\"nofollow\">Bandcamp</a><br>$NL"
while IFS="=" read -r key val; do
case "$key" in
web) key=Website ;;
sc) key=SoundCloud ;;
yt) key=YouTube ;;
tw) key=Twitch ;;
tr) key=Twitter ;;
mx) key=Mixcloud ;;
ig) key=Instagram ;;
sp) key=Spotify ;;
lt) key=Linktree ;;
ch) key=Cohost ;;
"") break ;;
*) : ;;
esac
socials="$socials<a href=\"$val\" rel=\"nofollow\">$key</a><br>$NL"
done
socials="$(printf '%s' "$socials" | sort)$NL"
errecho 'Moving on!'
BASEURL="https://$BANDCAMP_DOMAIN"
# HTML/JSON PARSING #
curl -L -s -o "$HTML_FILE" "$1"
# SOCIALS #
if [ -z "$only_download" ] && [ -z "$is_existing_discog" ] || ! [ -f DESCRIPTION.html ]; then
>&2 cat <<-EOF
input artist socials in KEY=VALUE format. blank line to continue. bandcamp is already filled
common shorthands:
web=website, sc=soundcloud, yt=youtube, tw=twitch, tr=twitter, mx=mixcloud,
ig=instagram, sp=spotify, lt=Linktree, ch=Cohost
EOF
# creates the DESCRIPTION thingy
printf '<a href="%s" rel="nofollow">Bandcamp</a><br>\n' "$BASEURL" > DESCRIPTION.html
while IFS="=" read -r key val; do
case "$key" in
web) key=Website ;;
sc) key=SoundCloud ;;
yt) key=YouTube ;;
tw) key=Twitch ;;
tr) key=Twitter ;;
mx) key=Mixcloud ;;
ig) key=Instagram ;;
sp) key=Spotify ;;
lt) key=Linktree ;;
ch) key=Cohost ;;
"") break ;;
*) : ;;
esac
printf '<a href="%s" rel="nofollow">%s</a><br>\n' "$val" "$key" >> DESCRIPTION.html
done
errecho 'Moving on!'
printf '\n<br><div><b>%s</b></div>\n\n<br><div><b>%s</b></div>' \
"Uncontained Releases" "Contained Releases" >> DESCRIPTION.html
fi
# END SOCIALS #
tmplog="" look_closer="" uncontained_releases="" contained_releases="" contained_releases_raw=""
json="$(mktemp -u)"
# albums and tracks
while read -r url; do
url="$BASEURL$url"
# if rg -q -F "$url" "$logdir/log" 2>/dev/null; then
# errecho "ALREADY CONTAINED $type: $url"
# tmplog="$tmplog$url CONTAINED$NL"
# continue
# fi
curl -L -s -o - "$url" | pup 'script[type="application/ld+json"]' 'text{}' > "$json" || continue
artist="$(jq -r '.byArtist.name' < "$json")"
name="$(jq -r '.name' < "$json")"
if [ "$(jq '.numTracks' < "$json")" = "0.0" ]; then
look_closer="<a href=\"$url\" rel=\"nofollow\">$artist - $name</a><br>$NL$look_closer"
errecho "LOOK CLOSER: $url"
elif [ "$(jq 'if (.inAlbum) then .inAlbum.albumRelease[0].offers.price else .albumRelease[0].offers.price end' < "$json")" = "0.0" ]; then
contained_releases="<a href=\"$url\" rel=\"nofollow\">$artist - $name</a><br>${NL}${contained_releases}"
contained_releases_raw="$url$NL$contained_releases_raw"
errecho "CONTAINED RELEASE: $artist - $name"
if ! rg -q -F "$url" "$logdir/log" 2>/dev/null; then
echo "$url" >> "$logdir/log"
# HTML/JSON PARSING #
curl -L -s -o "$DISCOG_PAGE" "$BASEURL/music"
if [ -z "$only_download" ]; then
look_closer="" uncontained_releases="" contained_releases="" contained_releases_raw=""
last_contained="" last_uncontained=""
# albums and tracks
while read -r url; do
case "$url" in
/*) url="$BASEURL$url" ;;
*) url=${url%%\?*} ;;
esac
# if is contained, skip it but also add its thingy to the contained releases var
if [ -n "$skip_contained" ] && is_contained "$url" >/dev/null; then
last_contained="$url"
errecho "ALREADY CONTAINED: $url"
continue
fi
# get album data
curl -L -s -o "$RELEASE_PAGE" "$url"
pup 'head > script[type="application/ld+json"]' 'text{}' < "$RELEASE_PAGE" > "$JSON_HEAD" || continue
pup -p '[data-tralbum] attr{data-tralbum}' 'text{}' < "$RELEASE_PAGE" > "$JSON_TRALBUM" || continue
artist="$(jq -r '.byArtist.name' < "$JSON_HEAD")"
name="$(jq -r '.name' < "$JSON_HEAD")"
numtracks="$(jq -r '.inAlbum.numTracks' < "$JSON_HEAD")"
[ "$numtracks" = "null" ] && numtracks="$(jq -r .numTracks < "$JSON_HEAD")"
price="$(jq '
if (.inAlbum) then .inAlbum.albumRelease[0].offers.price
else .albumRelease[0].offers.price end' < "$JSON_HEAD"
)"
# check if it even has audio first
if [ "$(jq .hasAudio < "$JSON_TRALBUM")" != "true" ]; then
errecho "NO AUDIO, LOOK CLOSER: $url"
fi
# now check price :D
if [ "$price" = "0.0" ]; then
if unline=$(is_uncontained "$url"); then
unline="$(grep -nF "${unline#*:}" DESCRIPTION.html)"
move_from_uncontained "$url"
else
if indexline=$(is_contained "$last_contained"); then
indexline="$(grep -nF "${indexline#*:}" DESCRIPTION.html)"
else
indexline="/<br><div><b>Contained Releases"
fi
>/dev/null ed DESCRIPTION.html <<-EOF
${indexline%%:*}
a
<a href="$url" rel="nofollow">$artist - $name</a><br>
.
wq
EOF
fi
errecho "CONTAINED RELEASE: $artist - $name"
last_contained="$url"
else
# just to catch if we are rebuilding something and don't skip
is_contained "$url" >/dev/null && continue
errecho "UNCONTAINED RELEASE: $artist - $name"
is_uncontained "$url" >/dev/null && continue
if indexline=$(is_contained "$last_uncontained"); then
indexline="$(grep -nF "${indexline#*:}" DESCRIPTION.html)"
else
indexline="/<br><div><b>Uncontained Releases"
fi
>/dev/null ed DESCRIPTION.html <<-EOF
${indexline%%:*}
a
<a href="$url" rel="nofollow">$artist - $name</a><br>
.
wq
EOF
last_uncontained="$url"
fi
done <<-EOF
$(
pup '#music-grid > li > a attr{href}' < "$DISCOG_PAGE"
pup '#music-grid attr{data-client-items}' < "$DISCOG_PAGE" | unescapehtml | jq -r '.[].page_url'
)
EOF
fi
# download shit
if [ -z "$no_download" ]; then
outdir="./files"
if [ -n "$is_existing_discog" ]; then
outdir="./files/new_stuff"
fi
else
uncontained_releases="<a href=\"$url\" rel=\"nofollow\">$artist - $name</a><br>${NL}${uncontained_releases}"
errecho "UNCONTAINED RELEASE: $artist - $name"
mkdir -p "$outdir"
printf '%s' 'CAT.ALL' > ./files/_rules.conf
# artist img
img="$(pup 'img.band-photo' 'attr{src}' < "$DISCOG_PAGE")"
if [ -n "$img" ]; then
ext="${img##*.}"
curl -s -o ./files/artist."$ext" "${img%_*}_0.$ext"
fi
errecho "Done with retrieving metadata! Now to download..."
bcdl-free --no-unzip -z 12345 -f FLAC -d "$outdir" -e auto -l "$BASEURL/music"
set +f
if [ "$(printf '%s' "$outdir"/*.flac)" != "$outdir/*.flac" ]; then
mkdir "$outdir"/TRACKS
mv "$outdir"/*.flac "$outdir"/TRACKS
fi
set -f
fi
done <<-EOF
$(
pup '#music-grid > li > a attr{href}' < "$HTML_FILE"
pup '#music-grid attr{data-client-items}' < "$HTML_FILE" | unescapehtml | jq -r '.[].page_url'
)
EOF
# formatting the description
if [ -n "${uncontained_releases}" ]; then
uncontained_releases="$NL<br><div><b>Uncontained Releases</b></div>$NL$uncontained_releases"
fi
contained_releases="$NL<br><div><b>Contained Releases</b></div>$NL$contained_releases"
printf '%s%s%s%s' \
"${look_closer:+$look_closer$NL}" "$socials" "$uncontained_releases" "$contained_releases" > DESCRIPTION.html
# download shit
if [ ! "$no_download" ]; then
mkdir -p "files"
printf '%s' 'CAT.ALL' > ./files/_rules.conf
# artist img
img="$(pup 'img.band-photo' 'attr{src}' < "$HTML_FILE")"
if [ -n "$img" ]; then
ext="${img##*.}"
curl -s -o ./files/artist."$ext" "${img%_*}_0.$ext"
fi
errecho "Done with retrieving metadata! Now to download..."
bcdl-free --no-unzip -z 12345 -f FLAC -d "./files" -e auto -l "$BASEURL"
set +f
if [ ./files/*.flac != "./files/*.flac" ]; then
mkdir ./files/TRACKS
mv ./files/*.flac ./files/TRACKS
fi
fi
done
# END MAIN LOOP #