feat: massive refactor

This commit is contained in:
Cory Dransfeldt 2024-10-09 18:10:28 -07:00
parent d424082c95
commit 1880790c05
No known key found for this signature in database
38 changed files with 245 additions and 761 deletions

View file

@ -6,21 +6,11 @@ const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const fetchAlbumReleases = async () => {
const today = DateTime.utc().startOf('day')
const today = DateTime.utc().startOf('day').toSeconds()
const { data, error } = await supabase
.from('optimized_album_releases')
.select(`
name,
release_date,
release_link,
total_plays,
art,
artist_name,
artist_description,
artist_total_plays,
artist_country,
artist_favorite
`)
.select('*')
if (error) {
console.error('Error fetching data:', error)
@ -28,31 +18,18 @@ const fetchAlbumReleases = async () => {
}
const all = data.map(album => {
const releaseDate = DateTime.fromISO(album['release_date']).toUTC().startOf('day')
const releaseDate = DateTime.fromSeconds(album['release_timestamp']).toUTC().startOf('day')
return {
artist: {
name: album['artist_name'],
description: album['artist_description'],
total_plays: album['artist_total_plays'],
country: album['artist_country'],
favorite: album['artist_favorite'],
url: album['artist_url'],
},
title: album['name'],
...album,
description: album['artist']['description'],
date: releaseDate.toLocaleString(DateTime.DATE_FULL),
description: album['artist_description'],
url: album['release_link'],
image: album['art'] ? `/${album['art']}` : '',
total_plays: album['total_plays'],
release_date: releaseDate,
type: 'album-release',
timestamp: releaseDate.toSeconds(),
timestamp: releaseDate.toSeconds()
}
}).sort((a, b) => a['timestamp'] - b['timestamp'])
const upcoming = all.filter(album => (!album['total_plays'] || album['total_plays'] <= 0) && album['release_date'] > today)
const current = all.filter(album => album['release_date'] <= today)
const upcoming = all.filter(album => album['release_timestamp'] > today)
const current = all.filter(album => album['release_timestamp'] <= today)
return { all, upcoming, current }
}

View file

@ -13,27 +13,7 @@ const fetchAllArtists = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_artists')
.select(`
id,
name_string,
url,
tentative,
total_plays,
country,
description,
favorite,
genre,
emoji,
tattoo,
art,
albums,
concerts,
books,
movies,
posts,
related_artists,
shows
`)
.select('*')
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
@ -51,49 +31,8 @@ const fetchAllArtists = async () => {
const processArtists = (artists) => {
return artists.map(artist => ({
name: artist['name_string'],
tentative: artist['tentative'],
totalPlays: artist['total_plays'],
...artist,
country: parseCountryField(artist['country']),
description: artist['description'],
favorite: artist['favorite'],
genre: {
name: artist['genre']['name'],
url: artist['genre']['url'],
},
emoji: artist['emoji'],
tattoo: artist['tattoo'],
image: artist['art'] ? `/${artist['art']}` : '',
url: artist['url'],
albums: (artist['albums'] || []).map(album => ({
name: album['name'],
releaseYear: album['release_year'],
totalPlays: album['total_plays'],
art: album.art ? `/${album['art']}` : ''
})).sort((a, b) => a['release_year'] - b['release_year']),
concerts: artist['concerts'] ? artist['concerts'].sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
books: artist['books'] ? artist['books'].map(book => ({
title: book['title'],
author: book['author'],
description: book['description'],
url: `/books/${book['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null,
movies: artist['movies'] ? artist['movies'].map(movie => ({
title: movie['title'],
year: movie['year'],
url: `/watching/movies/${movie['tmdb_id']}`,
})).sort((a, b) => b['year'] - a['year']) : null,
shows: artist['shows'] ? artist['shows'].map(show => ({
title: show['title'],
year: show['year'],
url: `/watching/shows/${show['tmdb_id']}`,
})).sort((a, b) => b['year'] - a['year']) : null,
posts: artist['posts'] ? artist['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
relatedArtists: artist['related_artists'] ? artist['related_artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null,
}))
}

View file

@ -12,33 +12,12 @@ const fetchAllBooks = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_books')
.select(`
id,
isbn,
date_finished,
author,
description,
title,
progress,
read_status,
star_rating,
review,
art,
favorite,
tattoo,
tags,
artists,
genres,
movies,
posts,
shows,
related_books
`)
.select('*')
.order('date_finished', { ascending: false })
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
console.error('Error fetching data from Supabase:', error)
console.error('Error fetching books:', error)
break
}
@ -52,45 +31,11 @@ const fetchAllBooks = async () => {
const processBooks = (books) => {
return books.map(book => {
const dateFinished = new Date(book['date_finished'])
const year = dateFinished.getUTCFullYear()
const dateFinished = book['date_finished'] ? new Date(book['date_finished']) : null
const year = dateFinished && !isNaN(dateFinished.getTime()) ? dateFinished.getUTCFullYear() : null
return {
title: book['title'],
author: book['author'] || '',
review: book['review'],
rating: book['star_rating'] !== 'unrated' ? book['star_rating'] : '',
favorite: book['favorite'],
tattoo: book['tattoo'],
description: book['description'],
image: `/${book['art']}`,
url: `/books/${book['isbn']}`,
date: book['date_finished'],
status: book['read_status'],
progress: book['progress'],
tags: Array.isArray(book['tags']) ? book['tags'] : book['tags']?.split(',') || [],
type: 'book',
artists: book['artists'] ? book['artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null,
movies: book['movies'] ? book['movies'].map(movie => {
movie['url'] = `/watching/movies/${movie['tmdb_id']}`
return movie
}).sort((a, b) => b['year'] - a['year']) : null,
genres: book['genres'] ? book['genres'].sort((a, b) => a['name'].localeCompare(b['name'])) : null,
shows: book['shows'] ? book['shows'].map(show => {
show['url'] = `/watching/shows/${show['tmdb_id']}`
return show
}).sort((a, b) => b['year'] - a['year']) : null,
posts: book['posts'] ? book['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
relatedBooks: book['related_books'] ? book['related_books'].map(relatedBook => ({
title: relatedBook['title'],
author: relatedBook['author'],
description: relatedBook['description'],
url: `/books/${relatedBook['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null, // Add related books processing
...book,
year,
}
})
@ -112,5 +57,6 @@ const sortBooksByYear = (books) => {
export default async function () {
const books = await fetchAllBooks()
const processedBooks = processBooks(books)
return { all: processedBooks, years: sortBooksByYear(processedBooks) }
}

View file

@ -12,13 +12,7 @@ const fetchAllConcerts = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_concerts')
.select(`
id,
date,
artist,
venue,
concert_notes
`)
.select('*')
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
@ -36,24 +30,9 @@ const fetchAllConcerts = async () => {
const processConcerts = (concerts) => {
return concerts.map(concert => ({
id: concert['id'],
type: 'concert',
date: concert['date'],
artist: concert['artist'] && typeof concert['artist'] === 'object' ? {
name: concert['artist'].name,
url: concert['artist'].url
} : { name: concert['artist'], url: null },
venue: concert['venue'] && typeof concert['venue'] === 'object' ? {
name: concert['venue'].name,
latitude: concert['venue'].latitude,
longitude: concert['venue'].longitude,
notes: concert['venue'].notes
} : null,
description: 'I went to (yet another) concert!',
notes: concert['concert_notes'],
url: `/music/concerts?id=${concert['id']}`,
artistUrl: concert['artist'] && typeof concert['artist'] === 'object' ? concert['artist'].url : null
})).sort((a, b) => new Date(b['date']) - new Date(a['date']))
...concert,
artist: concert.artist || { name: concert.artist_name_string, url: null },
}))
}
export default async function () {

View file

@ -4,53 +4,22 @@ const SUPABASE_URL = process.env.SUPABASE_URL
const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const fetchGenresWithArtists = async () => {
const fetchGenres = async () => {
const { data, error } = await supabase
.from('optimized_genres')
.select(`
name,
description,
total_plays,
wiki_link,
url,
artists,
books,
movies,
posts
`)
.order('id', { ascending: true })
.select('*')
if (error) {
console.error('Error fetching genres with artists:', error)
return []
}
return data.map(genre => ({
...genre,
artists: genre['artists'],
url: genre['url'],
books: genre['books'] ? genre['books'].map(book => ({
title: book['title'],
author: book['author'],
description: book['description'],
url: `/books/${book['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null,
movies: genre['movies'] ? genre['movies'].map(movie => ({
title: movie['title'],
year: movie['year'],
url: `/watching/movies/${movie['tmdb_id']}`,
})).sort((a, b) => b['year'] - a['year']) : null,
posts: genre['posts'] ? genre['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
}))
return data
}
export default async function () {
try {
return await fetchGenresWithArtists()
return await fetchGenres()
} catch (error) {
console.error('Error fetching and processing genres:', error)
return []

View file

@ -5,24 +5,6 @@ const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 1000
const fetchAllTags = async () => {
const { data, error } = await supabase
.from('links_tags')
.select('links_id, tags(name)')
if (error) {
console.error('Error fetching all tags from Supabase:', error)
return {}
}
return data.reduce((acc, { links_id, tags }) => {
if (!tags || !tags.name) return acc
if (!acc[links_id]) acc[links_id] = []
acc[links_id].push(tags['name'])
return acc
}, {})
}
const fetchAllLinks = async () => {
let links = []
let page = 0
@ -30,9 +12,8 @@ const fetchAllLinks = async () => {
while (fetchMore) {
const { data, error } = await supabase
.from('links')
.select('*, authors (name, url, mastodon)')
.order('date', { ascending: false })
.from('optimized_links')
.select('*')
.range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1)
if (error) {
@ -49,15 +30,11 @@ const fetchAllLinks = async () => {
return links
}
const processLinks = (links, tagsByLinkId) => {
return links.map(link => {
link['tags'] = tagsByLinkId[link['id']] || []
link['type'] = 'link'
return link
})
}
export default async function () {
const [links, tagsByLinkId] = await Promise.all([fetchAllLinks(), fetchAllTags()])
return processLinks(links, tagsByLinkId)
try {
return await fetchAllLinks()
} catch (error) {
console.error('Error fetching and processing links:', error)
return []
}
}

View file

@ -13,34 +13,11 @@ const fetchAllMovies = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_movies')
.select(`
id,
tmdb_id,
last_watched,
title,
year,
collected,
plays,
favorite,
tattoo,
star_rating,
description,
review,
art,
backdrop,
tags,
artists,
books,
genres,
shows,
posts,
related_movies
`)
.order('last_watched', { ascending: false })
.select('*')
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
console.error(error)
console.error('Error fetching movies:', error)
break
}
@ -53,62 +30,20 @@ const fetchAllMovies = async () => {
return movies
}
const processMovies = (movies) => {
return movies.map(item => ({
title: item['title'],
lastWatched: item['last_watched'],
dateAdded: item['last_watched'],
year: item['year'],
url: `/watching/movies/${item['tmdb_id']}`,
description: item['description'],
image: item['art'] ? `/${item['art']}` : '',
backdrop: item['backdrop'] ? `/${item['backdrop']}` : '',
plays: item['plays'],
collected: item['collected'],
favorite: item['favorite'],
tattoo: item['tattoo'],
rating: item['star_rating'],
review: item['review'],
type: 'movie',
tags: item['tags'] ? item['tags'].split(',') : [],
artists: item['artists'] ? item['artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null,
books: item['books'] ? item['books'].map(book => {
book['url'] = `/books/${book['isbn']}`
return book
}).sort((a, b) => a['title'].localeCompare(b['title'])) : null,
genres: item['genres'] ? item['genres'].sort((a, b) => a['title'].localeCompare(b['title'])) : null,
shows: item['shows'] ? item['shows'].map(show => {
show['url'] = `/watching/shows/${show['tmdb_id']}`
return show
}).sort((a, b) => b['year'] - a['year']) : null,
posts: item['posts'] ? item['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
relatedMovies: item['related_movies'] ? item['related_movies'].map(movie => {
movie['url'] = `/watching/movies/${movie['tmdb_id']}`
return movie
}).sort((a, b) => b['year'] - a['year']) : null,
}))
}
export default async function () {
const year = DateTime.now().year
try {
const movies = await fetchAllMovies()
const processedMovies = processMovies(movies)
const filterMovies = (condition) => processedMovies.filter(condition)
const formatMovieData = (movies) => movies.map(movie => movie)
const favoriteMovies = filterMovies(movie => movie['favorite'])
const recentlyWatchedMovies = filterMovies(movie => movie['lastWatched'] && year - DateTime.fromISO(movie['lastWatched']).year <= 3).sort((a, b) => new Date(b['lastWatched']) - new Date(a['lastWatched']))
const filterMovies = (condition) => movies.filter(condition)
const favoriteMovies = filterMovies(movie => movie.favorite)
const recentlyWatchedMovies = filterMovies(movie => movie.last_watched && year - DateTime.fromISO(movie.last_watched).year <= 3)
return {
movies: formatMovieData(processedMovies),
watchHistory: formatMovieData(filterMovies(movie => movie['lastWatched'])),
recentlyWatched: formatMovieData(recentlyWatchedMovies),
favorites: formatMovieData(favoriteMovies).sort((a, b) => a['title'].localeCompare(b['title'])),
movies,
watchHistory: filterMovies(movie => movie.last_watched),
recentlyWatched: recentlyWatchedMovies,
favorites: favoriteMovies.sort((a, b) => a.title.localeCompare(b.title)),
}
} catch (error) {
console.error('Error fetching and processing movies data:', error)
@ -116,7 +51,7 @@ export default async function () {
movies: [],
watchHistory: [],
recentlyWatched: [],
favorites: [],
favorites: []
}
}
}

View file

@ -5,14 +5,14 @@ const SUPABASE_KEY = process.env.SUPABASE_KEY
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const PAGE_SIZE = 1000
const fetchDataFromView = async (viewName, fields) => {
const fetchDataFromView = async (viewName) => {
let rows = []
let rangeStart = 0
while (true) {
const { data, error } = await supabase
.from(viewName)
.select(fields)
.select('*')
.order('listened_at', { ascending: false })
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
@ -32,36 +32,40 @@ const fetchDataFromView = async (viewName, fields) => {
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, genreMapping) => {
const aggregateData = (data, groupByField, groupByType) => {
const aggregation = {}
data.forEach(item => {
const key = item[groupByField]
if (!aggregation[key]) {
let imageField = ''
switch (groupByType) {
case 'artist':
imageField = item['artist_art']
break
case 'album':
imageField = item['album_art']
break
case 'track':
imageField = item['album_art']
break
default:
imageField = ''
}
aggregation[key] = {
title: item[groupByField],
plays: 0,
url: item['artist_url'],
image: `/${item[groupByType]}`,
type: groupByType === 'artist_art' ? 'artist' : groupByType === 'album_art' ? 'album' : groupByType,
genre: genreMapping[item['artist_genres']] || ''
image: imageField,
genre: item['artist_genres'],
type: groupByType
}
if (groupByType === 'track' || groupByType === 'album_art') aggregation[key]['artist'] = item['artist_name']
if (groupByType === 'track' || groupByType === 'album') aggregation[key]['artist'] = item['artist_name']
}
aggregation[key].plays++
})
@ -74,66 +78,62 @@ const buildRecents = (data) => {
artist: listen['artist_name'],
url: listen['artist_url'],
timestamp: listen['listened_at'],
image: `/${listen['album_art']}`
})).sort((a, b) => b.timestamp - a.timestamp)
image: listen['album_art'],
type: 'track'
})).sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
}
const aggregateGenres = (data, genreMapping) => {
const aggregateGenres = (data) => {
const genreAggregation = {}
data.forEach(item => {
const genre = genreMapping[item['artist_genres']] || ''
if (!genreAggregation[genre]) genreAggregation[genre] = { name: genre, url: item['genre_url'], plays: 0 }
const genre = item['genre_name'] || ''
const genreUrl = item['genre_url'] || ''
if (!genreAggregation[genre]) {
genreAggregation[genre] = {
name: genre,
url: genreUrl,
plays: 0,
type: 'genre'
}
}
genreAggregation[genre]['plays']++
})
return Object.values(genreAggregation).sort((a, b) => b['plays'] - a['plays'])
}
export default async function () {
const selectFields = `
listened_at,
track_name,
artist_name,
album_name,
album_key,
artist_art,
artist_genres,
artist_country,
album_art,
artist_url,
genre_url
`
try {
const genreMapping = await fetchGenreMapping()
const [recentTracks, monthTracks, threeMonthTracks] = await Promise.all([
fetchDataFromView('recent_tracks', selectFields),
fetchDataFromView('month_tracks', selectFields),
fetchDataFromView('three_month_tracks', selectFields)
fetchDataFromView('recent_tracks'),
fetchDataFromView('month_tracks'),
fetchDataFromView('three_month_tracks')
])
return {
recent: buildRecents(recentTracks),
week: {
artists: aggregateData(recentTracks, 'artist_name', 'artist_art', genreMapping),
albums: aggregateData(recentTracks, 'album_name', 'album_art', genreMapping),
tracks: aggregateData(recentTracks, 'track_name', 'track', genreMapping),
genres: aggregateGenres(recentTracks, genreMapping),
artists: aggregateData(recentTracks, 'artist_name', 'artist'),
albums: aggregateData(recentTracks, 'album_name', 'album'),
tracks: aggregateData(recentTracks, 'track_name', 'track'),
genres: aggregateGenres(recentTracks),
totalTracks: recentTracks.length.toLocaleString('en-US')
},
month: {
artists: aggregateData(monthTracks, 'artist_name', 'artist_art', genreMapping),
albums: aggregateData(monthTracks, 'album_name', 'album_art', genreMapping),
tracks: aggregateData(monthTracks, 'track_name', 'track', genreMapping),
genres: aggregateGenres(monthTracks, genreMapping),
artists: aggregateData(monthTracks, 'artist_name', 'artist'),
albums: aggregateData(monthTracks, 'album_name', 'album'),
tracks: aggregateData(monthTracks, 'track_name', 'track'),
genres: aggregateGenres(monthTracks),
totalTracks: monthTracks.length.toLocaleString('en-US')
},
threeMonth: {
artists: aggregateData(threeMonthTracks, 'artist_name', 'artist_art', genreMapping),
albums: aggregateData(threeMonthTracks, 'album_name', 'album_art', genreMapping),
tracks: aggregateData(threeMonthTracks, 'track_name', 'track', genreMapping),
genres: aggregateGenres(threeMonthTracks, genreMapping),
artists: aggregateData(threeMonthTracks, 'artist_name', 'artist'),
albums: aggregateData(threeMonthTracks, 'album_name', 'album'),
tracks: aggregateData(threeMonthTracks, 'track_name', 'track'),
genres: aggregateGenres(threeMonthTracks),
totalTracks: threeMonthTracks.length.toLocaleString('en-US')
}
}

View file

@ -3,43 +3,8 @@ 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 = 250
const fetchBlockData = async (collection, itemId) => {
const { data, error } = await supabase
.from(collection)
.select(collection === 'hero' ? '*, image(filename_disk)' : '*')
.eq('id', itemId)
.single()
if (error) {
console.error(`Error fetching data from ${collection} for item ${itemId}:`, error)
return null
}
return data
}
const fetchAllBlocks = async () => {
const { data, error } = await supabase
.from('pages_blocks')
.select('pages_id, collection, item, sort')
if (error) {
console.error('Error fetching all blocks from Supabase:', error)
return {}
}
return data.reduce((acc, block) => {
if (!acc[block['pages_id']]) {
acc[block['pages_id']] = []
}
acc[block['pages_id']].push(block)
return acc
}, {})
}
const fetchAllPages = async () => {
let pages = []
let page = 0
@ -65,40 +30,9 @@ const fetchAllPages = async () => {
return pages
}
const processPages = async (pages, blocksByPageId) => {
return Promise.all(pages.map(async page => {
const blocks = blocksByPageId[page['id']] || []
page['blocks'] = await Promise.all(blocks.map(async block => {
const blockData = await fetchBlockData(block['collection'], block['item'])
if (!blockData) return {
'type': block['collection'],
'sort': block['sort']
}
return {
'type': block['collection'],
'sort': block['sort'],
...blockData
}
})).then(blocks => blocks.filter(block => block !== null))
page['blocks'].sort((a, b) => a['sort'] - b['sort'])
if (page['open_graph_image']) page['open_graph_image'] = page['open_graph_image']['filename_disk']
return page
}))
}
export default async function () {
try {
const [pages, blocksByPageId] = await Promise.all([
fetchAllPages(),
fetchAllBlocks()
])
return await processPages(pages, blocksByPageId)
return await fetchAllPages()
} catch (error) {
console.error('Error fetching and processing pages:', error)
return []

View file

@ -9,7 +9,6 @@ const fetchAllPosts = async () => {
let posts = []
let page = 0
let fetchMore = true
const uniquePosts = new Set()
while (fetchMore) {
const { data, error } = await supabase
@ -25,44 +24,18 @@ const fetchAllPosts = async () => {
if (data.length < PAGE_SIZE) fetchMore = false
for (const post of data) {
if (uniquePosts.has(post['url'])) continue
uniquePosts.add(post['url'])
posts.push(post)
}
posts = posts.concat(data)
page++
}
return posts
}
const processPosts = async (posts) => {
return Promise.all(posts.map(async post => {
post['artists'] = post['artists'] ? post['artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null
post['books'] = post['books'] ? post['books'].map(book => ({
title: book['title'],
author: book['author'],
description: book['description'],
url: `/books/${book['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null
post['movies'] = post['movies'] ? post['movies'].map(movie => {
movie['url'] = `/watching/movies/${movie['tmdb_id']}`
return movie
}).sort((a, b) => b['year'] - a['year']) : null
post['genres'] = post['genres'] ? post['genres'].sort((a, b) => a['name'].localeCompare(b['name'])) : null
post['shows'] = post['shows'] ? post['shows'].map(show => {
show['url'] = `/watching/shows/${show['tmdb_id']}`
return show
}).sort((a, b) => b['year'] - a['year']) : null
if (post['image']) post['image'] = post['image']['filename_disk']
return post
}))
}
export default async function () {
const posts = await fetchAllPosts()
return await processPosts(posts)
try {
return await fetchAllPosts()
} catch (error) {
console.error('Error fetching and processing posts:', error)
return []
}
}

View file

@ -12,26 +12,7 @@ const fetchAllShows = async () => {
while (true) {
const { data, error } = await supabase
.from('optimized_shows')
.select(`
id,
tmdb_id,
title,
year,
collected,
favorite,
tattoo,
description,
review,
art,
backdrop,
tags,
episodes,
artists,
books,
movies,
posts,
related_shows
`)
.select('*')
.range(rangeStart, rangeStart + PAGE_SIZE - 1)
if (error) {
@ -47,136 +28,31 @@ const fetchAllShows = async () => {
return shows
}
const prepareShowData = (show) => ({
...show,
image: show['art'] ? `/${show['art']}` : '',
backdrop: show['backdrop'] ? `/${show['backdrop']}` : '',
url: `/watching/shows/${show['tmdb_id']}`,
episodes: show['episodes'] || [],
tattoo: show['tattoo'],
tags: Array.isArray(show['tags']) ? show['tags'] : show['tags']?.split(',') || [],
movies: show['movies'] ? show['movies'].map(movie => {
movie['url'] = `/watching/movies/${movie['tmdb_id']}`
return movie
}).sort((a, b) => b['year'] - a['year']) : null,
books: show['books'] ? show['books'].map(book => ({
title: book['title'],
author: book['author'],
description: book['description'],
url: `/books/${book['isbn']}`,
})).sort((a, b) => a['title'].localeCompare(b['title'])) : null,
posts: show['posts'] ? show['posts'].map(post => ({
title: post['title'],
date: post['date'],
url: post['url'],
})).sort((a, b) => new Date(b['date']) - new Date(a['date'])) : null,
relatedShows: show['related_shows'] ? show['related_shows'].map(relatedShow => ({
title: relatedShow['title'],
year: relatedShow['year'],
url: `/watching/shows/${relatedShow['tmdb_id']}`,
})).sort((a, b) => b['year'] - a['year']) : null,
artists: show['artists'] ? show['artists'].sort((a, b) => a['name'].localeCompare(b['name'])) : null
})
const prepareEpisodeData = (show) => show['episodes'].map(episode => ({
...episode,
show_title: show['title'],
show_tmdb_id: show['tmdb_id'],
show_year: show['year'],
collected: show['collected'],
favorite: show['favorite'],
image: show['image'],
backdrop: show['backdrop'],
episode_number: episode['episode_number'],
season_number: episode['season_number'],
last_watched_at: episode['last_watched_at']
}))
const formatEpisodeData = (episodes) => {
const showEpisodesMap = {}
episodes.forEach(episode => {
const showTmdbId = episode['show_tmdb_id']
const showYear = episode['show_year']
if (!showEpisodesMap[showTmdbId]) {
showEpisodesMap[showTmdbId] = {
title: episode['show_title'],
tmdbId: showTmdbId,
year: showYear,
collected: episode['collected'],
favorite: episode['favorite'],
dateAdded: episode['last_watched_at'],
lastWatchedAt: episode['last_watched_at'],
episodes: [],
image: episode['image'],
backdrop: episode['backdrop'],
}
}
showEpisodesMap[showTmdbId].episodes.push({
name: episode['show_title'],
url: `/watching/shows/${showTmdbId}`,
subtext: `S${episode['season_number']}E${episode['episode_number']}`,
episode: episode['episode_number'],
season: episode['season_number'],
tmdbId: showTmdbId,
year: showYear,
type: 'tv',
dateAdded: episode['last_watched_at'],
lastWatchedAt: episode['last_watched_at'],
image: episode['image'],
backdrop: episode['backdrop'],
})
})
return Object.values(showEpisodesMap).sort((a, b) => new Date(b['episodes'][0]['lastWatchedAt']) - new Date(a['episodes'][0]['lastWatchedAt'])).flatMap(show => {
const startingEpisode = show['episodes'][show['episodes'].length - 1]['episode']
const startingSeason = show['episodes'][show['episodes'].length - 1]['season']
const endingEpisode = show['episodes'][0]['episode']
const endingSeason = show['episodes'][0]['season']
if (show.episodes.length > 1) {
return {
name: show['title'],
url: `/watching/shows/${show['tmdbId']}`,
subtext: `S${startingSeason}E${startingEpisode} - S${endingSeason}E${endingEpisode}`,
startingEpisode,
startingSeason,
episode: endingEpisode,
season: endingSeason,
tmdbId: show['tmdbId'],
year: show['year'],
collected: show['collected'],
favorite: show['favorite'],
type: 'tv-range',
image: show['image'],
backdrop: show['backdrop'],
}
} else {
return show['episodes'][0]
}
})
}
export default async function () {
try {
const rawShows = await fetchAllShows()
const shows = rawShows.map(prepareShowData)
const episodes = shows.flatMap(prepareEpisodeData).sort((a, b) => new Date(b['last_watched_at']) - new Date(a['last_watched_at']))
const favoriteShows = shows.filter(show => show.favorite)
const shows = await fetchAllShows()
const watchedShows = shows.filter(show => show['last_watched_at'] !== null)
const episodes = watchedShows.map(show => ({
title: show['episode']['title'],
year: show['year'],
formatted_episode: show['episode']['formatted_episode'],
url: show['episode']['url'],
image: show['episode']['image'],
backdrop: show['episode']['backdrop'],
last_watched_at: show['episode']['last_watched_at'],
type: 'tv'
}))
return {
shows,
watchHistory: formatEpisodeData(episodes),
recentlyWatched: formatEpisodeData(episodes.slice(0, 225)),
favorites: formatEpisodeData(favoriteShows.flatMap(prepareEpisodeData)).sort((a, b) => a['name'].localeCompare(b['name'])),
recentlyWatched: episodes.slice(0, 225),
favorites: shows.filter(show => show.favorite).sort((a, b) => a.title.localeCompare(b.title)),
}
} catch (error) {
console.error('Error fetching and processing shows data:', error)
return {
shows: [],
watchHistory: [],
recentlyWatched: [],
favorites: [],
}