Add artist download; fix UTF-8 strings

This commit is contained in:
Jaidyn Ann 2020-10-22 15:56:08 -05:00
parent dcec47acaf
commit 2d54442b8e
2 changed files with 63 additions and 8 deletions

View File

@ -24,6 +24,7 @@ Otherwise, authorization will fail, and downloading tracks will be impossible.
USAGE USAGE
---------------------------------------- ----------------------------------------
Use the `-a` argument followed by a URL or ID to download an album. Use the `-a` argument followed by a URL or ID to download an album.
Use the `-g` argument with URL/ID to download all albums from a given artist.
By default, tracks are downloaded at the highest bitrate available. To use By default, tracks are downloaded at the highest bitrate available. To use
the low bitrate option, use the `-l` argument. the low bitrate option, use the `-l` argument.

View File

@ -4,7 +4,7 @@
# main: jaidedctrl # main: jaidedctrl
# lisc: cc0 # lisc: cc0
# date: 2020 # date: 2020
# requires: `lynx` and `jq` # requires: `jq`, `lynx`, and `ffmpeg`
# -------------------------------------- # --------------------------------------
# ============================================================================== # ==============================================================================
@ -35,10 +35,25 @@ function fetch_album {
fetch_page "https://music.divercities.eu/albums/$album_id" fetch_page "https://music.divercities.eu/albums/$album_id"
} }
# artist_id -> html
# fetch an artist's page
function fetch_artist {
local artist_id="$1"
fetch_page "https://music.divercities.eu/artists/$artist_id"
}
# ============================================================================== # ==============================================================================
# PARSE # PARSE
# ============================================================================== # ==============================================================================
# artist_html -> numbers
# take a list of album IDs from an artist's page
function artist_album_ids {
grep "album-cover " \
| grep "id:" \
| sed 's%.*id: %%' \
| sed 's%}).*%%'
}
# |album_html -> album_track_spans # |album_html -> album_track_spans
# gets all track spans (containing garbled track json) from an album's page # gets all track spans (containing garbled track json) from an album's page
function album_track_spans { function album_track_spans {
@ -50,7 +65,7 @@ function album_track_spans {
# takes a track span ripped from an album's page, turns it into json # takes a track span ripped from an album's page, turns it into json
function track_span_to_json { function track_span_to_json {
sed 's%.* {"id":%%' \ sed 's%.* {"id":%%' \
| lynx -dump -stdin -width=10000 \ | lynx -dump -stdin -width=10000 -assume_charset=UTF-8 -display_charset=UTF-8 \
| tr -d '\n' \ | tr -d '\n' \
| sed 's% %%g' \ | sed 's% %%g' \
| sed 's%^%{"id":%' | sed 's%^%{"id":%'
@ -68,6 +83,16 @@ function track_json_artists {
# ============================================================================== # ==============================================================================
# DOWNLOAD # DOWNLOAD
# ============================================================================== # ==============================================================================
# artist_id -> nil
# download all albums from an artist
function dl_artist {
local artist_id="$1"
local albums="$(fetch_artist "$artist_id" | artist_album_ids)"
for album in $albums; do
dl_album "$album"
done
}
# album_id -> nil # album_id -> nil
# download every track of a given album # download every track of a given album
function dl_album { function dl_album {
@ -95,7 +120,7 @@ function dl_track_from_json {
local json="$1"; local bitrate="$2" local json="$1"; local bitrate="$2"
local title="$(cat "$json" | jq -r '.title' 2>/dev/null)" local title="$(cat "$json" | jq -r '.title' 2>/dev/null)"
local album="$(cat "$json" | jq -r '.album.title' 2>/dev/null)" local album="$(cat "$json" | jq -r '.album.title' 2>/dev/null)"
local artists="$(cat "$json" | track_json_artists)" local artists="$(cat "$json" | track_json_artists | awk -F , '{print $1}')"
local url_stub="$(cat "$json" | jq -r ".${bitrate}_bitrate_url" 2>/dev/null)" local url_stub="$(cat "$json" | jq -r ".${bitrate}_bitrate_url" 2>/dev/null)"
local url="https://music.divercities.eu${url_stub}" local url="https://music.divercities.eu${url_stub}"
local dir="." local dir="."
@ -126,9 +151,12 @@ function dl_track_from_json {
# ============================================================================== # ==============================================================================
# METADATA # METADATA
# ============================================================================== # ==============================================================================
# output, title, album, artist -> nil
# handle a track's metadata (updating, realigning, etc.)
function track_metadata { function track_metadata {
local mp3="${1}.mp3"; local json="${1}.json" local mp3="${1}.mp3"; local json="${1}.json"
local title="$2"; local album="$3"; local artists="$4" local title="$2"; local album="$3"; local artists="$4"
local track_no="$(cat "$json" | jq -r '.track_number')"
local temp="$(mktemp --suffix=divercities)" local temp="$(mktemp --suffix=divercities)"
local temp_mp3_a="$(mktemp --suffix='divercities.mp3')" local temp_mp3_a="$(mktemp --suffix='divercities.mp3')"
local temp_mp3_b="$(mktemp --suffix='divercities.mp3')" local temp_mp3_b="$(mktemp --suffix='divercities.mp3')"
@ -140,10 +168,13 @@ function track_metadata {
metadata_album "$temp" "$temp_mp3_a" "$temp_mp3_b" "$album" metadata_album "$temp" "$temp_mp3_a" "$temp_mp3_b" "$album"
metadata_artist "$temp" "$temp_mp3_a" "$temp_mp3_b" "$artists" metadata_artist "$temp" "$temp_mp3_a" "$temp_mp3_b" "$artists"
metadata_date "$temp" "$temp_mp3_a" "$temp_mp3_b" metadata_date "$temp" "$temp_mp3_a" "$temp_mp3_b"
metadata_track "$temp" "$temp_mp3_a" "$temp_mp3_b" "$track_no"
cp "$temp_mp3_a" "$mp3" cp "$temp_mp3_a" "$mp3"
rm "$temp_mp3_a" "$temp_mp3_b"
} }
# handle title metadata; copy over if exists, otherwise create
function metadata_title { function metadata_title {
local data="$1" local data="$1"
local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b" local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b"
@ -157,6 +188,7 @@ function metadata_title {
fi fi
} }
# handle artist metadata; copy over if exists, otherwise create
function metadata_album { function metadata_album {
local data="$1" local data="$1"
local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b" local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b"
@ -170,14 +202,15 @@ function metadata_album {
fi fi
} }
# handle artist metadata; copy over if exists, otherwise create
function metadata_artist { function metadata_artist {
local data="$1" local data="$1"
local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b" local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b"
local artist="$4" local artist="$4"
if grep "TOPE" "$data" >/dev/null; then # if grep "TOPE" "$data" >/dev/null; then
artist="$(grep "TOPE" "$data" | awk '{print $3}')" # artist="$(grep "TOPE" "$data" | awk '{print $3}')"
fi # fi
if grep "artist" "$data" >/dev/null; then if grep "artist" "$data" >/dev/null; then
return return
@ -187,6 +220,7 @@ function metadata_artist {
fi fi
} }
# handle date metadata; copy over if exists
function metadata_date { function metadata_date {
local data="$1" local data="$1"
local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b" local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b"
@ -198,6 +232,19 @@ function metadata_date {
fi fi
} }
# handle track metadata; add it if nonexistant
function metadata_track {
local data="$1"
local mp3_a="$2"; local mp3_b="$3"; rm "$mp3_b"
local track_no="$4"
if grep "track" "$data" >/dev/null; then
return
else
ffmpeg -i "$mp3_a" -codec copy -metadata track="$track_no" "$mp3_b"
cp "$mp3_b" "$mp3_a"
fi
}
# ============================================================================== # ==============================================================================
# INVOCATION # INVOCATION
@ -205,11 +252,14 @@ function metadata_date {
SEMANTIC=0 SEMANTIC=0
BITRATE="high" BITRATE="high"
ALBUM="" ALBUM=""
GROUP=""
# print usage and seppaku # print usage and seppaku
function usage { function usage {
echo "usage: divercities_dl [-hsl] -a album_url/id" echo "usage: divercities_dl [-hsl] -a album_url/id"
echo " divercities_dl [-hsl] -g artist_url/id"
echo " -a download the album of the given url/id" echo " -a download the album of the given url/id"
echo " -g download albums of artist at given url/id"
echo " -s don't put tracks in semantic path (./artist/album/track.mp3)" echo " -s don't put tracks in semantic path (./artist/album/track.mp3)"
echo " -l use low bitrate downloads" echo " -l use low bitrate downloads"
echo " -h print this message" echo " -h print this message"
@ -223,12 +273,13 @@ function usage {
# -------------------------------------- # --------------------------------------
while getopts 'lsht:a:' c; do while getopts 'lsht:g:a:' c; do
case $c in case $c in
h) usage 1 ;; h) usage 1 ;;
l) BITRATE="low" ;; l) BITRATE="low" ;;
s) SEMANTIC=1 ;; s) SEMANTIC=1 ;;
a) ALBUM="$OPTARG" ;; a) ALBUM="$OPTARG" ;;
g) GROUP="$OPTARG" ;;
esac esac
done done
@ -241,6 +292,9 @@ fi
if test -n "$ALBUM"; then if test -n "$ALBUM"; then
ALBUM="$(echo "$ALBUM" | sed 's%.*/%%')" ALBUM="$(echo "$ALBUM" | sed 's%.*/%%')"
dl_album "$ALBUM" dl_album "$ALBUM"
elif test -n "$GROUP"; then
GROUP="$(echo "$GROUP" | sed 's%.*/%%')"
dl_artist "$GROUP"
else else
usage 2 usage 2
fi fi