feat: music caching v1

This commit is contained in:
Cory Dransfeldt 2023-07-19 11:58:16 -07:00
parent c1fb450712
commit b1e97ecda2
No known key found for this signature in database
4 changed files with 2314 additions and 45 deletions

1
.gitignore vendored
View file

@ -3,7 +3,6 @@ _site
node_modules node_modules
.env.local .env.local
.cache .cache
.vercel
# logs # logs
*-error.log *-error.log

View file

@ -48,6 +48,7 @@
"ics-to-json-extended": "^1.1.4", "ics-to-json-extended": "^1.1.4",
"lint-staged": "^13.2.3", "lint-staged": "^13.2.3",
"liquidjs": "^10.8.3", "liquidjs": "^10.8.3",
"lodash": "^4.17.21",
"luxon": "^3.3.0", "luxon": "^3.3.0",
"markdown-it": "^13.0.1", "markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.4.1", "markdown-it-anchor": "^8.4.1",

2203
src/_data/json/cache/music.json vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,5 @@
const fs = require('fs')
const _ = require('lodash')
const { AssetCache } = require('@11ty/eleventy-fetch') const { AssetCache } = require('@11ty/eleventy-fetch')
const artistAliases = require('./json/artist-aliases.json') const artistAliases = require('./json/artist-aliases.json')
@ -9,10 +11,106 @@ const aliasArtist = (artist) => {
const sanitizeMedia = (media) => { const sanitizeMedia = (media) => {
const denyList = const denyList =
/(\[|\()(Deluxe Edition|Special Edition|Remastered|Full Dynamic Range Edition)(\]|\))/i /-\s*(?:single|ep)\s*|(\[|\()(Deluxe Edition|Special Edition|Remastered|Full Dynamic Range Edition)(\]|\))/gi
return media.replace(denyList, '').trim() return media.replace(denyList, '').trim()
} }
const diffTracks = (cache, tracks) => {
const trackCompareSet = Object.values(tracks)
const cacheCompareSet = Object.values(cache).sort((a, b) => a.time - b.time)
const diffedTracks = {}
const ONE_HOUR_MS = 3600000
const tracksOneHour = []
let trackIndex = 0
let trackTimer = 0
while (trackTimer < ONE_HOUR_MS) {
trackTimer = trackTimer + parseInt(trackCompareSet[trackIndex].duration)
tracksOneHour.push(trackCompareSet[trackIndex])
trackIndex++
}
const comparedTracks = _.differenceWith(
tracksOneHour,
cacheCompareSet.slice(-tracksOneHour.length),
(a, b) => _.isEqual(a.id, b.id)
)
for (let i = 0; i < comparedTracks.length; i++)
diffedTracks[`${comparedTracks[i]?.id}-${comparedTracks[i].time}`] = comparedTracks[i]
return diffedTracks
}
const formatTracks = (tracks, time) => {
let formattedTracks = {}
Object.values(tracks).forEach((track) => {
const artistFormatted = titleCase(aliasArtist(track.attributes['artistName']))
const albumFormatted = titleCase(sanitizeMedia(track.attributes['albumName']))
const trackFormatted = sanitizeMedia(track.attributes['name'])
if (!formattedTracks[track.attributes.name]) {
formattedTracks[track.attributes.name] = {
name: trackFormatted,
artist: artistFormatted,
album: albumFormatted,
art: track.attributes.artwork.url.replace('{w}', '300').replace('{h}', '300'),
url:
track['relationships'] && track['relationships'].albums.data.length > 0
? `https://song.link/${track['relationships'].albums.data.pop().attributes.url}`
: `https://rateyourmusic.com/search?searchtype=l&searchterm=${encodeURI(
albumFormatted
)}%20${encodeURI(artistFormatted)}`,
id: track.id,
time,
duration: track.attributes['durationInMillis'],
}
} else {
formattedTracks[track.attributes.name].plays++
}
})
return formattedTracks
}
const deriveCharts = (tracks) => {
const charts = {
artists: {},
albums: {},
}
const tracksForLastWeek = Object.values(tracks).filter((track) => {
const currentDate = new Date()
const currentDateTime = new Date().getTime()
const lastWeek = new Date(currentDate.setDate(currentDate.getDate() - 7))
const lastWeekDateTime = lastWeek.getTime()
const trackDateTime = new Date(track.time).getTime()
return trackDateTime <= currentDateTime && trackDateTime > lastWeekDateTime
})
tracksForLastWeek.forEach((track) => {
if (!charts.artists[track.artist]) {
charts.artists[track.artist] = {
artist: track.artist,
plays: 1,
}
} else {
charts.artists[track.artist].plays++
}
if (!charts.albums[track.album]) {
charts.albums[track.album] = {
name: track.album,
artist: track.artist,
art: track.art,
url: track.url,
plays: 1,
}
} else {
charts.albums[track.album].plays++
}
})
return charts
}
const titleCase = (string) => { const titleCase = (string) => {
const exceptions = [ const exceptions = [
'a', 'a',
@ -63,10 +161,10 @@ module.exports = async function () {
const asset = new AssetCache('recent_tracks_data') const asset = new AssetCache('recent_tracks_data')
const PAGE_SIZE = 30 const PAGE_SIZE = 30
const PAGES = 10 const PAGES = 10
const charts = { const time = Number(new Date())
let charts = {
artists: {}, artists: {},
albums: {}, albums: {},
tracks: {},
} }
let CURRENT_PAGE = 0 let CURRENT_PAGE = 0
let res = [] let res = []
@ -91,50 +189,18 @@ module.exports = async function () {
if (tracks.data.length) res = [...res, ...tracks.data] if (tracks.data.length) res = [...res, ...tracks.data]
CURRENT_PAGE++ CURRENT_PAGE++
} }
res.forEach((track) => {
const formattedArtist = titleCase(aliasArtist(track.attributes['artistName']))
const formattedAlbum = titleCase(sanitizeMedia(track.attributes['albumName']))
const formattedTrack = sanitizeMedia(track.attributes['name'])
if (!charts.artists[formattedArtist]) { const cachedTracks = fs.readFileSync('./src/_data/json/cache/music.json', { encoding: 'utf8' })
charts.artists[formattedArtist] = { const updatedCache = {
artist: formattedArtist, ...JSON.parse(cachedTracks),
url: `https://rateyourmusic.com/search?searchterm=${encodeURI(formattedArtist)}`, ...diffTracks(JSON.parse(cachedTracks), formatTracks(res, time)),
plays: 1,
} }
} else { charts = deriveCharts(updatedCache)
charts.artists[formattedArtist].plays++
}
if (!charts.albums[formattedAlbum]) {
charts.albums[formattedAlbum] = {
name: formattedAlbum,
artist: formattedArtist,
art: track.attributes.artwork.url.replace('{w}', '300').replace('{h}', '300'),
url: track['relationships']
? `https://song.link/${track['relationships'].albums.data.pop().attributes.url}`
: `https://rateyourmusic.com/search?searchtype=l&searchterm=${encodeURI(
formattedAlbum
)}%20${encodeURI(formattedArtist)}`,
plays: 1,
}
} else {
charts.albums[formattedAlbum].plays++
}
if (!charts.tracks[formattedTrack]) {
charts.tracks[formattedTrack] = {
name: formattedTrack,
artist: formattedArtist,
plays: 1,
}
} else {
charts.tracks[formattedTrack].plays++
}
})
charts.artists = sort(charts.artists).splice(0, 8) charts.artists = sort(charts.artists).splice(0, 8)
charts.albums = sort(charts.albums).splice(0, 8) charts.albums = sort(charts.albums).splice(0, 8)
charts.tracks = sort(charts.tracks).splice(0, 5) fs.writeFileSync('./src/_data/json/cache/music.json', JSON.stringify(updatedCache), {
encoding: 'utf8',
})
await asset.save(charts, 'json') await asset.save(charts, 'json')
return charts return charts
} }