Created
December 8, 2024 02:39
-
-
Save mtfurlan/1fa16b4d00aff25dd32c5cbb2fe795fb to your computer and use it in GitHub Desktop.
Revisions
-
mtfurlan created this gist
Dec 8, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,184 @@ #!/usr/bin/env bash set -euo pipefail # shellcheck disable=SC2120 h () { # if arguments, print them [ $# == 0 ] || echo "$*" cat <<EOF Usage: $(basename "${BASH_SOURCE[0]}") [OPTION]... <album> <mixcloud url> download a mix from mixcloud and try to tag properly album Available options: -h, --help display this help and exit EOF # if args, exit 1 else exit 0 [ $# == 0 ] || exit 1 exit 0 } msg() { echo >&2 -e "${*-}" } die() { local msg=$1 local code=${2-1} # default exit status 1 msg "$msg" exit "$code" } # getopt short options go together, long options have commas TEMP=$(getopt -o h --long help -n "$0" -- "$@") #shellcheck disable=SC2181 if [ $? != 0 ] ; then die "something wrong with getopt" fi eval set -- "$TEMP" while true ; do case "$1" in -h|--help) h ;; --) shift ; break ;; *) die "issue parsing args, unexpected argument '$1'!" ;; esac done album=${1:-} if [ -z "$album" ]; then h "need to pass in album" fi url=${2:-} if [ -z "$url" ]; then h "need to pass in target url" fi #url looks like https://www.mixcloud.com/Ishkur/the-ultimate-hi-nrg-mix/ if [[ "$url" =~ https:\/\/www.mixcloud.com\/([^\/]*)\/([^\/]*)\/?$ ]]; then username="${BASH_REMATCH[1]}" slug="${BASH_REMATCH[2]}" else help "can't match url, either use better input or fix mathcing logic in script" fi msg "fetching $username's $slug, putting in album $album" doGraphQL() { username=$1 slug=$2 query=$3 headers=( -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0' -H 'Content-Type: application/json' -H 'Cookie: mx_t=c5cbc44f_b2dd_4e29_afba_a2c9d9d6ed03; csrftoken=4VDmUTpAWggOM3xzMG8Ltx32glJE9kSg; ch=AhcwEy6RKoCd9Dg0Q4PUUj28STBYGAMBmW1E6jFLDMk; c="gAAAAABnVAZ6gC4sfT1vgYcsVh7JAZEsABUXW7TaOv4SlbZXPdyyZmBYriuDBcxCl_EvUUu_0bOc8KySKG5GNqmtUCwo-jq2Ycw3x7fGseN2_wb7GW5QB0VLhqPAdQMcEAOH8cJ1xXLFYVEz8u248zZKKV3F6NmqABHx5eJKFrUTJyKYVCYMn_k="' ) curl -s 'https://app.mixcloud.com/graphql' \ -X POST \ "${headers[@]}" \ --data-raw "$( jq -cn \ --arg slug "$slug" \ --arg username "$username" \ --arg query "$query" \ '{id: "something", query: $query, variables: { lookup: { username: $username, slug: $slug}}}' )" } fetchSongList() { username=$1 slug=$2 #shellcheck disable=SC2016 doGraphQL "$username" "$slug" \ 'query TracklistAudioPageQuery( $lookup: CloudcastLookup! ) { cloudcast: cloudcastLookup(lookup: $lookup) { canShowTracklist featuringArtistList moreFeaturingArtists sections { __typename ... on TrackSection { __typename artistName songName } ... on ChapterSection { chapter } ... on Node { __isNode: __typename id } } id } }' \ | jq '[.data.cloudcast.sections[] | select(.artistName != null) | {artist: .artistName, song: .songName}]' } fetchDescriptionAndPicture() { username=$1 slug=$2 #shellcheck disable=SC2016 doGraphQL "$username" "$slug" \ 'query cloudcastQuery( $lookup: CloudcastLookup! ) { cloudcast: cloudcastLookup(lookup: $lookup) { tags { tag { slug } } name description publishDate picture { urlRoot } } } ' \ | jq '.data.cloudcast | {tags: [.tags[] | .tag.slug], publishDate: .publishDate, name: .name, description: .description, picture: "https://thumbnailer.mixcloud.com/unsafe/666x666/\(.picture.urlRoot)"}' } songList=$(fetchSongList "$username" "$slug" | tee /tmp/songList) meta=$(fetchDescriptionAndPicture "$username" "$slug" | tee /tmp/meta) #songList=$(cat /tmp/songList) #meta=$(cat /tmp/meta) description="$(echo "$meta" | jq -r '.description')" if [[ "$(echo "$songList" | jq 'length')" -gt 0 ]]; then description+=" Incomplete Song List: $(echo "$songList" | jq -r '.[] | "\(.artist) - \(.song)"')" fi title="$(echo "$meta" | jq -r '.name')" image=$title.jpg songFile="$title.mp3" if [[ ! -f "$image" ]]; then curl -s "$(echo "$meta" | jq -r '.picture')" > "$image" fi eyeD3Args=( --to-v2.4 --remove-all --artist="$(echo "$songList" | jq --arg artist "$username" -r '[{artist: $artist}] + . | [.[] | .artist] | join(", ")')" --album-artist="$username" --album="$album" --title="$title" --comment="$description" --recording-date="$(date -d "$(echo "$meta" | jq -r '.publishDate')" +"%Y-%m-%d")" --genre="$(echo "$meta" | jq -r '.tags | join("/")')" --add-image="$image:OTHER:from mixcloud" ) if [[ ! -f "$songFile" ]]; then yt-dlp -x --audio-format mp3 --audio-quality 0 -o "$title.%(ext)s" "$url" fi eyeD3 "${eyeD3Args[@]}" "$songFile"