From 521bd5d879c84a9f78974b694f88adbaf463e2ed Mon Sep 17 00:00:00 2001 From: Cory Dransfeldt Date: Mon, 9 Oct 2023 12:27:18 -0700 Subject: [PATCH] feat: assorted music fixes --- src/_data/json/artist-aliases.json | 20 ++++++++++++ src/_data/music.js | 49 +++++++++++------------------- src/utils/media.js | 41 +++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 32 deletions(-) create mode 100644 src/_data/json/artist-aliases.json create mode 100644 src/utils/media.js diff --git a/src/_data/json/artist-aliases.json b/src/_data/json/artist-aliases.json new file mode 100644 index 00000000..f61a778c --- /dev/null +++ b/src/_data/json/artist-aliases.json @@ -0,0 +1,20 @@ +{ + "aliases": [ + { + "artist": "Aesop Rock", + "aliases": ["Aesop Rock & Homeboy Sandman", "Aesop Rock & Blockhead"] + }, + { + "artist": "Fen", + "aliases": ["Sleepwalker & Fen"] + }, + { + "artist": "Osees", + "aliases": ["OCS", "The Ohsees", "Thee Oh Sees", "Thee Oh See's"] + }, + { + "artist": "Tom Waits", + "aliases": ["Tom Waits & Crystal Gayle", "Crystal Gayle"] + } + ] +} diff --git a/src/_data/music.js b/src/_data/music.js index 30489e42..ef81643f 100644 --- a/src/_data/music.js +++ b/src/_data/music.js @@ -1,9 +1,5 @@ const { AssetCache } = require('@11ty/eleventy-fetch') - -const sortTrim = (array, length = 8) => - Object.values(array) - .sort((a, b) => b.plays - a.plays) - .splice(0, length) +const { aliasArtist, sanitizeMedia, sortByPlays } = require('../utils/media') module.exports = async function () { const API_APPLE_MUSIC_DEVELOPER_TOKEN = process.env.API_APPLE_MUSIC_DEVELOPER_TOKEN @@ -15,7 +11,6 @@ module.exports = async function () { const response = { artists: {}, albums: {}, - tracks: {}, } const RENEWED_MUSIC_TOKEN = await fetch(APPLE_RENEW_TOKEN_URL, { @@ -53,11 +48,10 @@ module.exports = async function () { res.forEach((track) => { if (!response['artists'][track['attributes']['artistName']]) { response['artists'][track['attributes']['artistName']] = { - title: track['attributes']['artistName'], - image: - `https://cdn.coryd.dev/artists/${track['attributes']['artistName'] - .replace(/\s+/g, '-') - .toLowerCase()}.jpg` || 'https://cdn.coryd.dev/artists/missing-artist.jpg', + title: aliasArtist(track['attributes']['artistName']), + image: `https://cdn.coryd.dev/artists/${track['attributes']['artistName'] + .replace(/\s+/g, '-') + .toLowerCase()}.jpg`, url: `https://musicbrainz.org/search?query=${track['attributes']['artistName'].replace( /\s+/g, '+' @@ -72,35 +66,26 @@ module.exports = async function () { // aggregate albums if (!response.albums[track['attributes']['albumName']]) { response.albums[track['attributes']['albumName']] = { - title: track['attributes']['albumName'], - artist: track['attributes']['artistName'], + title: sanitizeMedia(track['attributes']['albumName']), + artist: aliasArtist(track['attributes']['artistName']), image: track['attributes']['artwork']['url'].replace('{w}', '500').replace('{h}', '500'), - url: `https://musicbrainz.org/taglookup/index?tag-lookup.artist=${track['attributes'][ - 'artistName' - ].replace(/\s+/g, '+')}&tag-lookup.release=${track['attributes']['albumName'].replace( - /\s+/g, - '+' - )}`, + url: + track['relationships'] && track['relationships'].albums.data.length > 0 + ? `https://song.link/${track['relationships'].albums.data.pop().attributes.url}` + : `https://musicbrainz.org/taglookup/index?tag-lookup.artist=${track['attributes'][ + 'artistName' + ].replace(/\s+/g, '+')}&tag-lookup.release=${sanitizeMedia( + track['attributes']['albumName'] + ).replace(/\s+/g, '+')}`, plays: 1, type: 'album', } } else { response.albums[track['attributes']['albumName']].plays++ } - - // aggregate tracks - if (!response.tracks[track['attributes']['name']]) { - response.tracks[track['attributes']['name']] = { - name: track['attributes']['name'], - plays: 1, - } - } else { - response.tracks[track['attributes']['name']].plays++ - } }) - response.artists = sortTrim(response.artists) - response.albums = sortTrim(response.albums) - response.tracks = sortTrim(response.tracks, 5) + response.artists = sortByPlays(response.artists) + response.albums = sortByPlays(response.albums) await asset.save(response, 'json') return response } diff --git a/src/utils/media.js b/src/utils/media.js new file mode 100644 index 00000000..39e06eb2 --- /dev/null +++ b/src/utils/media.js @@ -0,0 +1,41 @@ +const artistAliases = require('../_data/json/artist-aliases.json') + +module.exports = { + /** + * Accepts a string representing an artist name, checks to see if said artist name + * exists in an artist alias group of shape string[]. If so, replaces the provided + * artist name with the canonical artist name. + * + * @name aliasArtist + * @param {string} artist + * @returns {string} + */ + aliasArtist: (artist) => { + const aliased = artistAliases.aliases.find((alias) => alias.aliases.includes(artist)) + if (aliased) artist = aliased.artist + return artist + }, + + /** + * Accepts a media name represented as a string (album or song name) and replaces + * matches in the `denyList` with an empty string before returning the result. + * + * @name sanitizeMedia + * @param {string} media + * @returns {string} + */ + sanitizeMedia: (media) => { + const denyList = + /-\s*(?:single|ep)\s*|(\[|\()(Deluxe Edition|Special Edition|Remastered|Full Dynamic Range Edition|Anniversary Edition|Expanded Edition)(\]|\))/gi + return media.replace(denyList, '').trim() + }, + + /** + * Sorts an array of media objects by the number of plays in descending order. + * + * @name sortByPlays + * @param {Array} array - an array of media objects. + * @returns {Array} - a new array sorted by the number of plays in descending order. + */ + sortByPlays: (array) => Object.values(array).sort((a, b) => b.plays - a.plays), +}