feat: cms integration

This commit is contained in:
Cory Dransfeldt 2024-06-01 07:16:49 -07:00
parent ff77bdaf36
commit d23243b177
No known key found for this signature in database
1050 changed files with 1032 additions and 27229 deletions

View file

@ -16,7 +16,7 @@ export default async function () {
image,
release_date,
release_link,
artists (name_string, genre, mbid, country)
artists (name_string, mbid, country)
`)
.gt('release_date', today)
@ -31,8 +31,7 @@ export default async function () {
title: album['name'],
date: DateTime.fromISO(album['release_date']).toLocaleString(DateTime.DATE_FULL),
url: album['release_link'],
artist_url: `https://coryd.dev/music/artists/${sanitizeMediaString(album['artists']['name_string'])}-${sanitizeMediaString(parseCountryField(album['artists']['country']))}`,
genre: album['artists']['genre'],
artist_url: `/music/artists/${sanitizeMediaString(album['artists']['name_string'])}-${sanitizeMediaString(parseCountryField(album['artists']['country']))}`,
mbid: album['artists']['mbid'],
timestamp: DateTime.fromISO(album['release_date']).toSeconds()
}

View file

@ -1,8 +1,8 @@
import { createClient } from '@supabase/supabase-js'
import { parseCountryField } from '../../config/utilities/index.js'
const SUPABASE_URL = process.env.SUPABASE_URL || 'YOUR_SUPABASE_URL'
const SUPABASE_KEY = process.env.SUPABASE_KEY || 'YOUR_SUPABASE_KEY'
const SUPABASE_URL = process.env.SUPABASE_URL
const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 50
@ -36,13 +36,29 @@ const fetchPaginatedData = async (table, selectFields) => {
return data
}
export default async function () {
const artists = await fetchPaginatedData('artists', 'mbid, name_string, image, genre, total_plays, country, description, favorite')
const albums = await fetchPaginatedData('albums', 'mbid, name, release_year, artist_mbid, total_plays')
const fetchGenreMapping = async () => {
const { data, error } = await supabase
.from('genres')
.select('id, name')
if (error) {
console.error('Error fetching genres:', error)
return {}
}
return data.reduce((acc, genre) => {
acc[genre.id] = genre.name
return acc
}, {})
}
export default async function () {
const genreMapping = await fetchGenreMapping()
const artists = await fetchPaginatedData('artists', 'id, mbid, name_string, image, total_plays, country, description, favorite, genres')
const albums = await fetchPaginatedData('albums', 'mbid, name, release_year, total_plays, artist')
const albumsByArtist = albums.reduce((acc, album) => {
if (!acc[album.artist_mbid]) acc[album.artist_mbid] = []
acc[album.artist_mbid].push({
if (!acc[album.artist]) acc[album.artist] = []
acc[album.artist].push({
id: album.id,
name: album.name,
release_year: album.release_year,
@ -51,10 +67,11 @@ export default async function () {
return acc
}, {})
artists.forEach(artist => {
artist.albums = albumsByArtist[artist.mbid]?.sort((a, b) => a['release_year'] - b['release_year']) || []
for (const artist of artists) {
artist.albums = albumsByArtist[artist.id]?.sort((a, b) => a['release_year'] - b['release_year']) || []
artist.country = parseCountryField(artist.country)
})
artist.genres = genreMapping[artist.genres] || ''
}
return artists
}

View file

@ -1,30 +1,77 @@
import { createRequire } from 'module'
import { createClient } from '@supabase/supabase-js'
const require = createRequire(import.meta.url)
const books = require('./json/read.json')
const SUPABASE_URL = process.env.SUPABASE_URL
const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 1000
const fetchTagsForBook = async (bookId) => {
const { data, error } = await supabase
.from('books_tags')
.select('tags(id, name)')
.eq('books_id', bookId)
if (error) {
console.error(`Error fetching tags for book ${bookId}:`, error)
return []
}
return data.map(bt => bt.tags.name)
}
async function fetchAllBooks() {
let books = []
let from = 0
let to = PAGE_SIZE - 1
while (true) {
const { data, error } = await supabase
.from('books')
.select('*')
.range(from, to)
if (error) {
console.error('Error fetching data from Supabase:', error)
break
}
for (const book of data) {
book.tags = await fetchTagsForBook(book.id)
}
books = books.concat(data)
if (data.length < PAGE_SIZE) break
from += PAGE_SIZE
to += PAGE_SIZE
}
return books
}
export default async function () {
const books = await fetchAllBooks()
return books.map(book => {
let authors = ''
let date = book?.['dateAdded']
if (book['authors']?.length > 1) authors = book['authors'].join(', ')
if (book['authors']?.length === 1) authors = book['authors'][0]
if (book?.['dateStarted']) date = book['dateStarted']
if (book?.['dateFinished']) date = book['dateFinished']
const author = book['author'] || ''
let date = book?.['date_finished']
if (book?.['date_started']) date = book['date_started']
if (book?.['date_finished']) date = book['date_finished']
return {
title: book['title'],
authors,
author,
description: book['description'],
image: book['thumbnail'],
url: `https://coryd.dev/books/${book['isbn']}`,
url: `/books/${book['isbn']}`,
date,
status: book['status'],
tags: book['tags'],
categories: book['categories']?.length > 1 ? book['categories'].join(', ') : book['categories']?.[0],
rating: book['rating'] !== 'unrated' ? book['rating'] : '',
isbn: book['isbn'],
type: 'book',
}
})
}
}

View file

@ -1,8 +1,8 @@
import { createClient } from '@supabase/supabase-js'
import { parseCountryField } from '../../config/utilities/index.js'
const SUPABASE_URL = process.env.SUPABASE_URL || 'YOUR_SUPABASE_URL'
const SUPABASE_KEY = process.env.SUPABASE_KEY || 'YOUR_SUPABASE_KEY'
const SUPABASE_URL = process.env.SUPABASE_URL
const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
export default async function fetchGenresWithArtists() {

File diff suppressed because it is too large Load diff

View file

@ -3,42 +3,42 @@ export default {
{
title: 'Stay True',
authors: 'Hua Hsu',
image: 'https://coryd.dev/media/books/9780385547772-stay-true.jpg',
image: '/media/books/9780385547772-stay-true.jpg',
url: 'https://openlibrary.org/isbn/9780593663660',
type: 'book',
},
{
title: 'Where Are Your Boys Tonight?',
authors: 'Chris Payne',
image: 'https://coryd.dev/media/books/9780063251281-where-are-your-boys-tonight.jpg',
image: '/media/books/9780063251281-where-are-your-boys-tonight.jpg',
url: 'https://openlibrary.org/isbn/9780063161573',
type: 'book',
},
{
title: 'Trouble Boys',
authors: 'Bob Mehr',
image: 'https://coryd.dev/media/books/0306818795-trouble-boys.jpg',
image: '/media/books/0306818795-trouble-boys.jpg',
url: 'https://openlibrary.org/isbn/9780306818790',
type: 'book',
},
{
title: 'Corporate Rock Sucks',
authors: 'Jim Ruland',
image: 'https://coryd.dev/media/books/9780306925481-corporate-rock-sucks.jpg',
image: '/media/books/9780306925481-corporate-rock-sucks.jpg',
url: 'https://openlibrary.org/isbn/9780306925474',
type: 'book',
},
{
title: 'Tracers in the Dark',
authors: 'Andy Greenberg',
image: 'https://coryd.dev/media/books/0593315618-tracers-in-the-dark.jpg',
image: '/media/books/0593315618-tracers-in-the-dark.jpg',
url: 'http://openlibrary.org/isbn/9780385548106',
type: 'book',
},
{
title: 'Girl in a Band',
authors: 'Kim Gordon',
image: 'https://coryd.dev/media/books/9780062295897-kim-gordon-girl-in-a-band.jpg',
image: '/media/books/9780062295897-kim-gordon-girl-in-a-band.jpg',
url: 'https://openlibrary.org/isbn/9780062295910',
type: 'book',
}
@ -47,56 +47,56 @@ export default {
{
title: 'the whaler',
artist: 'home is where',
image: 'https://coryd.dev/media/albums/home-is-where-the-whaler.jpg',
image: '/media/albums/home-is-where-the-whaler.jpg',
url: 'https://musicbrainz.org/release-group/6fe3516f-c324-4265-8f43-d902f3a4cc20',
type: 'album',
},
{
title: 'The Enduring Spirit',
artist: 'Tomb Mold',
image: 'https://coryd.dev/media/albums/tomb-mold-the-enduring-spirit.jpg',
image: '/media/albums/tomb-mold-the-enduring-spirit.jpg',
url: 'https://musicbrainz.org/release-group/cd3e5dfb-acca-4856-80f6-2e095ac3270d',
type: 'album',
},
{
title: 'A Dialogue With The Eeriest Sublime',
artist: 'Vertebra Atlantis',
image: 'https://coryd.dev/media/albums/vertebra-atlantis-a-dialogue-with-the-eeriest-sublime.jpg',
image: '/media/albums/vertebra-atlantis-a-dialogue-with-the-eeriest-sublime.jpg',
url: 'https://musicbrainz.org/release-group/b8f1913b-f461-443c-a26c-377b259f2af6',
type: 'album',
},
{
title: 'ONE MORE TIME...',
artist: 'blink-182',
image: 'https://coryd.dev/media/albums/blink-182-one-more-time.jpg',
image: '/media/albums/blink-182-one-more-time.jpg',
url: 'https://musicbrainz.org/release-group/520d6d45-19c8-4ee1-a954-180e7902f3da',
type: 'album',
},
{
title: 'Life Like',
artist: 'Dead Bob',
image: 'https://coryd.dev/media/albums/dead-bob-life-like.jpg',
image: '/media/albums/dead-bob-life-like.jpg',
url: 'https://musicbrainz.org/release-group/ab53e625-74af-4a09-a8ff-e1c08dbae596',
type: 'album',
},
{
title: 'Threads of Unknowing',
artist: 'VoidCeremony',
image: 'https://coryd.dev/media/albums/voidceremony-threads-of-unknowing.jpg',
image: '/media/albums/voidceremony-threads-of-unknowing.jpg',
url: 'https://musicbrainz.org/release-group/f1f91cde-ff57-41c8-bd58-28c236b3f0c6',
type: 'album',
},
{
title: 'Why Would I Watch',
artist: 'Hot Mulligan',
image: 'https://coryd.dev/media/albums/hot-mulligan-why-would-i-watch.jpg',
image: '/media/albums/hot-mulligan-why-would-i-watch.jpg',
url: 'https://musicbrainz.org/release-group/5afd31ea-3a96-4b99-a477-4d121efaedec',
type: 'album',
},
{
title: 'Losing What We Love',
artist: 'Knuckle Puck',
image: 'https://coryd.dev/media/albums/knuckle-puck-losing-what-we-love.jpg',
image: '/media/albums/knuckle-puck-losing-what-we-love.jpg',
url: 'https://musicbrainz.org/release-group/b51d8882-3854-400a-b79b-4353a77a389b',
type: 'album',
}

55
src/_data/links.js Normal file
View file

@ -0,0 +1,55 @@
import { createClient } from '@supabase/supabase-js'
const SUPABASE_URL = process.env.SUPABASE_URL
const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 50
const fetchTagsForLink = async (linkId) => {
const { data, error } = await supabase
.from('links_tags')
.select('tags(id, name)')
.eq('links_id', linkId)
if (error) {
console.error(`Error fetching tags for link ${linkId}:`, error)
return []
}
return data.map((lt) => lt.tags.name)
}
const fetchAllLinks = async () => {
let links = []
let page = 0
let fetchMore = true
while (fetchMore) {
const { data, error } = await supabase
.from('links')
.select('*, authors (name, url)')
.order('date', { ascending: false })
.range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1)
if (error) {
console.error('Error fetching links:', error)
return links
}
if (data.length < PAGE_SIZE) fetchMore = false
for (const link of data) {
link.tags = await fetchTagsForLink(link.id)
}
links = links.concat(data)
page++
}
return links
}
export default async function () {
return await fetchAllLinks()
}

View file

@ -51,7 +51,7 @@ export default async function () {
lastWatched: item['last_watched'],
dateAdded: item['last_watched'],
year: item['year'],
url: `https://coryd.dev/watching/movies/${item['tmdb_id']}`,
url: `/watching/movies/${item['tmdb_id']}`,
description: `${item['title']} (${item['year']})<br/>Watched at: ${DateTime.fromISO(item['last_watched'], { zone: 'utc' }).setZone('America/Los_Angeles').toFormat('MMMM d, yyyy, h:mma')}`,
image: `https://coryd.dev/media/movies/poster-${item['tmdb_id']}.jpg`,
backdrop: `https://coryd.dev/media/movies/backdrops/backdrop-${item['tmdb_id']}.jpg`,
@ -76,6 +76,5 @@ export default async function () {
recentlyWatched: formatMovieData(recentlyWatchedMovies),
favorites: formatMovieData(favoriteMovies).sort((a, b) => a['title'].localeCompare(b['title'])),
collection: formatMovieData(collectedMovies),
toWatch: formatMovieData(movies, false).sort((a, b) => a['title'].localeCompare(b['title'])),
}
}

View file

@ -59,8 +59,25 @@ const fetchAllTimeData = async (fields, table) => {
return rows
}
const fetchGenreMapping = async () => {
const { data, error } = await supabase
.from('genres')
.select('id, name')
if (error) {
console.error('Error fetching genres:', error)
return {}
}
return data.reduce((acc, genre) => {
acc[genre.id] = genre.name
return acc
}, {})
}
const aggregateData = (data, groupByField, groupByType) => {
const aggregation = {}
const genreMapping = fetchGenreMapping()
data.forEach(item => {
const key = item[groupByField]
@ -70,21 +87,21 @@ const aggregateData = (data, groupByField, groupByType) => {
title: item[groupByField],
plays: 0,
mbid: item['albums']['mbid'],
url: `https://coryd.dev/music/artists/${sanitizeMediaString(item['artist_name'])}-${sanitizeMediaString(parseCountryField(item['artists']['country']))}`,
url: `/music/artists/${sanitizeMediaString(item['artist_name'])}-${sanitizeMediaString(parseCountryField(item['artists']['country']))}`,
image: item['albums']?.['image'] || '',
timestamp: item['listened_at'],
type: groupByType,
genre: item['artists']?.['genre'] || ''
genre: genreMapping[item['artists']['genre']] || ''
}
} else {
aggregation[key] = {
title: item[groupByField],
plays: 0,
mbid: item[groupByType]?.['mbid'] || '',
url: `https://coryd.dev/music/artists/${sanitizeMediaString(item['artist_name'])}-${sanitizeMediaString(parseCountryField(item['artists']['country']))}`,
url: `/music/artists/${sanitizeMediaString(item['artist_name'])}-${sanitizeMediaString(parseCountryField(item['artists']['country']))}`,
image: item[groupByType]?.image || '',
type: groupByType,
genre: item['artists']?.['genre'] || ''
genre: genreMapping[item['artists']['genre']] || ''
}
}
if (
@ -106,11 +123,11 @@ const aggregateData = (data, groupByField, groupByType) => {
const aggregateGenres = (data) => {
const genreAggregation = {}
const genreMapping = fetchGenreMapping()
data.forEach(item => {
const genre = item.artists.genre
if (!genreAggregation[genre]) {
genreAggregation[genre] = { genre, plays: 0 }
}
const genre = genreMapping[item['artists']['genre']] || ''
if (!genreAggregation[genre]) genreAggregation[genre] = { genre, plays: 0 }
genreAggregation[genre]['plays']++
})
return Object.values(genreAggregation).sort((a, b) => b['plays'] - a['plays'])
@ -130,7 +147,7 @@ export default async function() {
album_name,
album_key,
listened_at,
artists (mbid, image, genre, country),
artists (mbid, image, genres, country),
albums (mbid, image)
`

62
src/_data/posts.js Normal file
View file

@ -0,0 +1,62 @@
import { createClient } from '@supabase/supabase-js'
import { DateTime } from 'luxon'
import slugify from 'slugify'
const SUPABASE_URL = process.env.SUPABASE_URL
const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 50
const fetchTagsForPost = async (postId) => {
const { data, error } = await supabase
.from('posts_tags')
.select('tags(id, name)')
.eq('posts_id', postId)
if (error) {
console.error(`Error fetching tags for post ${postId}:`, error)
return []
}
return data.map(pt => pt.tags.name)
}
const fetchAllPosts = async () => {
let posts = []
let page = 0
let fetchMore = true
while (fetchMore) {
const { data, error } = await supabase
.from('posts')
.select('*')
.order('date', { ascending: false })
.range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1)
if (error) {
console.error('Error fetching posts:', error)
return posts
}
if (data.length < PAGE_SIZE) fetchMore = false
for (const post of data) {
post.tags = await fetchTagsForPost(post.id)
post.url = `/posts/${DateTime.fromISO(post.date).year}/${slugify(post.title, {
replacement: '-',
remove: /[#,&,+()$~%.'":*?<>{}\[\]\/\\|`!@\^\—]/g,
lower: true,
})}/`
}
posts = posts.concat(data)
page++
}
return posts
}
export default async function () {
return await fetchAllPosts()
}

View file

@ -90,14 +90,14 @@ export default async function () {
showEpisodesMap[showTmdbId].episodes.push({
name: showTitle,
url: `https://coryd.dev/watching/shows/${showTmdbId}`,
url: `/watching/shows/${showTmdbId}`,
subtext: `${showTitle} • S${seasonNumber}E${episodeNumber}`,
episode: episodeNumber,
season: seasonNumber,
tmdbId: showTmdbId,
type: 'tv',
image: `https://coryd.dev/media/shows/poster-${showTmdbId}.jpg`,
backdrop: `https://coryd.dev/media/shows/backdrops/backdrop-${showTmdbId}.jpg`,
image: `/media/shows/poster-${showTmdbId}.jpg`,
backdrop: `/media/shows/backdrops/backdrop-${showTmdbId}.jpg`,
dateAdded: lastWatchedAt,
lastWatchedAt
})
@ -114,7 +114,7 @@ export default async function () {
if (show.episodes.length > 1) {
episodeData.push({
name: show.title,
url: `https://coryd.dev/watching/shows/${show['tmdbId']}`,
url: `/watching/shows/${show['tmdbId']}`,
subtext: `S${startingSeason}E${startingEpisode} - S${endingSeason}E${endingEpisode}`,
startingEpisode,
startingSeason,
@ -124,8 +124,8 @@ export default async function () {
collected: show['collected'],
favorite: show['favorite'],
type: 'tv-range',
image: `https://coryd.dev/media/shows/poster-${show['tmdbId']}.jpg`,
backdrop: `https://coryd.dev/media/shows/backdrops/backdrop-${show['tmdbId']}.jpg`,
image: `/media/shows/poster-${show['tmdbId']}.jpg`,
backdrop: `/media/shows/backdrops/backdrop-${show['tmdbId']}.jpg`,
})
} else {
const singleEpisode = show['episodes'][0]
@ -140,7 +140,7 @@ export default async function () {
const favoriteShows = shows.filter(show => show['favorite'])
const collectedShows = shows.filter(show => show['collected'])
const toWatch = shows.map(show => ({...show, url: `https://coryd.dev/watching/shows/${show['tmdb_id']}`})).filter(show => !show.episodes.some(episode => episode.last_watched_at)).sort((a, b) => a['title'].localeCompare(b['title']))
const toWatch = shows.map(show => ({...show, url: `/watching/shows/${show['tmdb_id']}`})).filter(show => !show.episodes.some(episode => episode.last_watched_at)).sort((a, b) => a['title'].localeCompare(b['title']))
return {
shows,