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,6 +6,7 @@ const BASE_URL = 'https://coryd.dev'
const md = markdownIt()
const normalizeWord = (word) => {
if (!word) return ''
const wordMap = {
'ai': 'AI',
'css': 'CSS',
@ -14,12 +15,12 @@ const normalizeWord = (word) => {
'macos': 'macOS',
'tv': 'TV'
}
return wordMap[word.toLowerCase()] || word.charAt(0).toUpperCase() + word.slice(1)
return wordMap[word?.toLowerCase()] || word?.charAt(0).toUpperCase() + word.slice(1)
}
const tagsToHashtags = (item) => {
const tags = item?.tags || []
if (tags.length) return tags.map(tag => '#' + tag.split(' ').map(normalizeWord).join('')).join(' ')
const tags = item?.['tags'] || []
if (tags.length) return tags.map(tag => '#' + normalizeWord(tag)).join(' ')
return ''
}
@ -40,7 +41,7 @@ export const processContent = (collection) => {
{ method: 'fromISO' },
{ method: 'fromFormat', format: 'yyyy-MM-dd' },
{ method: 'fromFormat', format: 'MM/dd/yyyy' },
{ method: 'fromFormat', format: 'dd-MM-yyyy' },
{ method: 'fromFormat', format: 'dd-MM-yyyy' }
]
for (const { method, format } of formats) {
@ -115,16 +116,16 @@ export const processContent = (collection) => {
if (item['type'] === 'album-release') hashTags = ' #Music #NewMusic'
if (item['type'] === 'concert') hashTags = ' #Music #Concert'
if (item?.['authors']?.['mastodon']) {
const mastoUrl = new URL(item['authors']['mastodon'])
if (item?.['author']?.['mastodon']) {
const mastoUrl = new URL(item['author']['mastodon'])
attribution = `${mastoUrl.pathname.replace('/', '')}@${mastoUrl.host}`
} else if (item?.['authors']?.['name']) {
attribution = item['authors']['name']
} else if (item?.['author']?.['name']) {
attribution = item['author']['name']
}
let url = item['url'] || item['link']
if (url && !isValidUrl(url)) url = absoluteUrl(url)
if (item['type'] === 'concert') url = `${item['artistUrl'] ? item['artistUrl'] : BASE_URL + '/music/concerts'}?t=${DateTime.fromISO(item['date']).toMillis()}${item['artistUrl'] ? '#concerts' : ''}`
if (item['type'] === 'concert') url = `${item['artist']?.['url'] ? item['artist']['url'] : BASE_URL + '/music/concerts'}?t=${DateTime.fromISO(item['date']).toMillis()}${item['artist']?.['url'] ? '#concerts' : ''}`
const content = {
url,
@ -149,12 +150,12 @@ export const processContent = (collection) => {
}
const movieData = movies['movies'].filter((movie) => movie['rating'])
const showData = tv['shows'].filter((show) => show['episodes']?.[0]?.['last_watched_at'])
const bookData = books.all.filter((book) => book['rating'])
const showData = tv['shows'].filter((show) => show?.['episode']?.['formatted_episode'])
const bookData = books['all'].filter((book) => book['rating'])
addItemToIndex(posts, '📝', (item) => item['url'], (item) => item['title'], (item) => item['tags'])
addItemToIndex(links, '🔗', (item) => item['link'], (item) => item['title'], (item) => item['tags'])
addItemToIndex(artists, '🎙️', (item) => item['url'], (item) => `${item['name']} (${item['country']}) - ${item['genre']['name']}`, (item) => `['${item['genre']}']`)
addItemToIndex(artists, '🎙️', (item) => item['url'], (item) => `${item['name']} (${item['country']}) - ${item['genre']?.['name']}`, (item) => `['${item['genre']}']`)
addItemToIndex(genres, '🎵', (item) => item['url'], (item) => item['name'], (item) => item.artists.map(artist => artist['name_string']))
if (movieData) addItemToIndex(movieData, '🎥', (item) => item['url'], (item) => `${item['title']} (${item['rating']})`, (item) => item['tags'])
if (showData) addItemToIndex(showData, '📺', (item) => item['url'], (item) => `${item['title']} (${item['year']})`, (item) => item['tags'])
@ -167,13 +168,13 @@ export const processContent = (collection) => {
addContent(concerts, '🎤', (item) => `${item['artistNameString'] ? item['artistNameString'] : item['artist']['name']} at ${item['venue']['name'].split(',')[0].trim()}`, (item) => item['date'])
addContent([...albumReleases['current']].reverse(), '📆', (item) => `${item['title']} by ${item['artist']['name']}`, (item) => item['release_date'])
addSiteMapContent(posts, (item) => item.title, (item) => item.date)
addSiteMapContent(pages, (item) => item.title, (item) => item.date)
addSiteMapContent(artists, (item) => item.name, (item) => item.date)
addSiteMapContent(genres, (item) => item.name, (item) => item.date)
addSiteMapContent(movies['movies'], (item) => item.title, (item) => item.date)
addSiteMapContent(books.all, (item) => item.title, (item) => item.date)
addSiteMapContent(tv?.['shows'], (item) => item.title, (item) => item.date)
addSiteMapContent(posts, (item) => item['title'], (item) => item['date'])
addSiteMapContent(pages, (item) => item['title'], (item) => item['date'])
addSiteMapContent(artists, (item) => item['name'], (item) => item['date'])
addSiteMapContent(genres, (item) => item['name'], (item) => item['date'])
addSiteMapContent(movies['movies'], (item) => item['title'], (item) => item['date'])
addSiteMapContent(books.all, (item) => item['title'], (item) => item['date'])
addSiteMapContent(tv?.['shows'], (item) => item['title'], (item) => item['date'])
return {
searchIndex,
@ -197,7 +198,7 @@ export const albumReleasesCalendar = (collection) => {
if (!all || all.length === 0) return ''
const events = all.map(album => {
const date = DateTime.fromFormat(album.date, 'MMMM d, yyyy')
const date = DateTime.fromFormat(album['date'], 'MMMM d, yyyy')
if (!date.isValid) return null
return {
@ -206,8 +207,8 @@ export const albumReleasesCalendar = (collection) => {
startOutputType: 'local',
title: `Release: ${album['artist']['name']} - ${album['title']}`,
description: `Check out this new album release: ${album['url']}. Read more about ${album['artist']['name']} at https://coryd.dev${album['artist']['url']}`,
url: album.url,
uid: `${date.toFormat('yyyyMMdd')}-${album['artist']['name']}-${album.title}@coryd.dev`,
url: album['url'],
uid: `${date.toFormat('yyyyMMdd')}-${album['artist']['name']}-${album['title']}@coryd.dev`,
timestamp: DateTime.now().toUTC().toFormat("yyyyMMdd'T'HHmmss'Z'")
}
}).filter(event => event !== null)

View file

@ -14,13 +14,13 @@ export default {
const md = markdownIt({ html: true, linkify: true })
md.use(markdownItAnchor, {
level: [1, 2],
permalink: markdownItAnchor.permalink.headerLink({ safariReaderFix: true })
permalink: markdownItAnchor['permalink']['headerLink']({ safariReaderFix: true })
})
md.use(markdownItFootnote)
md.renderer.rules.footnote_ref = (tokens, idx) => `<sup>${tokens[idx].meta.id + 1}</sup>`
md.renderer.rules.footnote_block_open = () => '<hr class="footnotes-sep">\n<section class="footnotes">\n<ol class="footnotes-list">\n'
md.renderer.rules.footnote_open = (tokens, idx) => `<li id="fn${tokens[idx].meta.id + 1}" class="footnote-item"> `
md.renderer.rules.footnote_anchor = () => ''
md.renderer['rules']['footnote_ref'] = (tokens, idx) => `<sup>${tokens[idx]['meta']['id'] + 1}</sup>`
md.renderer['rules']['footnote_block_open'] = () => '<hr class="footnotes-sep">\n<section class="footnotes">\n<ol class="footnotes-list">\n'
md.renderer['rules']['footnote_open'] = (tokens, idx) => `<li id="fn${tokens[idx]['meta']['id'] + 1}" class="footnote-item"> `
md.renderer['rules']['footnote_anchor'] = () => ''
return md
}
@ -30,7 +30,7 @@ export default {
const md = mdGenerator()
const dateKey = Object.keys(entry).find(key => key.includes('date'))
const {
artist, authors, backdrop, content, description, image, link, rating, review,
artist, author, backdrop, content, description, image, link, rating, review,
slug, title, url, tags, type
} = entry
@ -41,36 +41,36 @@ export default {
}
const feedNote = '<hr/><p>This is a full text feed, but not all content can be rendered perfectly within the feed. If something looks off, feel free to <a href="https://coryd.dev">visit my site</a> for the original post.</p>'
processedEntry.url = (url?.includes('http')) ? url : new URL(slug || url, BASE_URL).toString()
processedEntry['url'] = (url?.includes('http')) ? url : new URL(slug || url, BASE_URL).toString()
if (link) {
processedEntry.title = `${title} via ${authors?.name || 'Unknown'}`
processedEntry.url = link
processedEntry.author = {
name: authors?.name || 'Unknown',
url: authors?.url || '',
mastodon: authors?.mastodon || '',
rss: authors?.rss_feed || ''
processedEntry['title'] = `${title} via ${author?.['name'] || 'Unknown'}`
processedEntry['url'] = link
processedEntry['author'] = {
name: author?.['name'] || 'Unknown',
url: author?.['url'] || '',
mastodon: author?.['mastodon'] || '',
rss: author?.['rss_feed'] || ''
}
processedEntry.excerpt = sanitizeHtml(md.render(description || ''))
processedEntry['excerpt'] = sanitizeHtml(md.render(description || ''))
} else if (['book', 'movie'].includes(type)) {
processedEntry.excerpt = sanitizeHtml(md.render(review || description || ''))
processedEntry['excerpt'] = sanitizeHtml(md.render(review || description || ''))
} else if (type === 'album-release') {
let sanitizedDescription = sanitizeHtml(md.render(description || ''))
let truncatedDescription = truncate(sanitizedDescription, { length: 500, reserveLastWord: true, ellipsis: '...' })
if (sanitizedDescription.length > 500) truncatedDescription += ` <p><a href="${artist?.url}">Read more about ${artist?.name}</a></p>`
processedEntry.excerpt = truncatedDescription
if (artist?.['name'] && artist?.['url'] && sanitizedDescription.length > 500) truncatedDescription += ` <p><a href="${artist['url']}">Read more about ${artist['name']}</a></p>`
processedEntry['excerpt'] = truncatedDescription
} else if (slug && content) {
processedEntry.excerpt = sanitizeHtml(md.render(content) + feedNote, { disallowedTagsMode: 'completelyDiscard' })
processedEntry['excerpt'] = sanitizeHtml(md.render(content) + feedNote, { disallowedTagsMode: 'completelyDiscard' })
} else if (description) {
processedEntry.excerpt = description
processedEntry['excerpt'] = description
}
processedEntry.image = backdrop || image
processedEntry['image'] = backdrop || image
if (rating) processedEntry.rating = rating
if (tags) processedEntry.tags = tags
if (type === 'album-release' && artist) processedEntry.title = `${title} by ${artist['name']}`
if (rating) processedEntry['rating'] = rating
if (tags) processedEntry['tags'] = tags
if (type === 'album-release' && artist) processedEntry['title'] = `${title} by ${artist['name']}`
posts.push(processedEntry)
})

View file

@ -10,6 +10,7 @@ export default {
const mediaData = limit ? media.slice(0, limit) : media
return mediaData.map((item) => {
let normalized = {
title: item['title'],
image: item['image'],
url: item['url'],
type: item['type']
@ -17,22 +18,18 @@ export default {
switch (item['type']) {
case 'artist':
normalized.title = item['title']
normalized.alt = `${item['plays']} plays of ${item['title']}`
normalized.subtext = `${item['plays']} plays`
break
case 'album':
normalized.title = item['title']
normalized.alt = `${item['title']} by ${item['artist']}`
normalized.subtext = `${item['artist']}`
break
case 'album-release':
normalized.title = item['title']
normalized.alt = `${item['title']} by ${item['artist']['name']}`
normalized.subtext = `${item['artist']['name']} / ${item['date']}`
break
case 'movie':
normalized.title = item['title']
normalized.alt = item['title']
normalized.rating = item['rating']
normalized.favorite = item['favorite']
@ -46,10 +43,8 @@ export default {
}
break
case 'tv':
case 'tv-range':
normalized.title = item['name']
normalized.alt = `${item['subtext']} ${item['type'] === 'tv' ? 'of' : 'from'} ${item['name']}`
normalized.subtext = item['subtext']
normalized.alt = item['formatted_episode']
normalized.subtext = item['formatted_episode']
break
}
@ -57,29 +52,16 @@ export default {
})
},
calculatePlayPercentage: (plays, mostPlayed) => `${plays/mostPlayed * 100}%`,
bookStatus: (books, status) => books.filter(book => book.status === status),
bookStatus: (books, status) => books.filter(book => book['status'] === status),
bookFavorites: (books) => books.filter(book => book.favorite === true),
bookYearLinks: (years) => years.sort((a, b) => b.value - a.value).map((year, index) => {
const separator = index < years.length - 1 ? ' / ' : ''
return `<a href="/books/years/${year.value}">${year.value}</a>${separator}`
}).join(''),
bookSortDescending: (books) => books.filter(book => !isNaN(DateTime.fromISO(book.date).toMillis())).sort((a, b) => {
const dateA = DateTime.fromISO(a.date)
const dateB = DateTime.fromISO(b.date)
return dateB - dateA
}),
bookFinishedYear: (books, year) => books.filter(book => {
if (book.status === 'finished' && book.date) return parseInt(book.date.split('-')[0]) === year
if (book['status'] === 'finished' && book['year']) return parseInt(book['year']) === parseInt(year)
return ''
}),
currentBookCount: (books) => {
const year = DateTime.now().year
return books.filter(book => {
if (book.status === 'finished' && book.date) return parseInt(book.date.split('-')[0]) === year
return ''
}).length
},
getLastWatched: (show) => show?.['episodes'][show['episodes']?.length - 1]?.['last_watched_at'],
sortByPlaysDescending: (data, key) => data.sort((a, b) => b[key] - a[key]),
mediaLinks: (data, type, count = 10) => {
if (!data || !type) return ''

28
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "coryd.dev",
"version": "1.0.6",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "coryd.dev",
"version": "1.0.6",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"@cdransf/api-text": "^1.5.0",
@ -1767,9 +1767,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.33",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz",
"integrity": "sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA==",
"version": "1.5.35",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.35.tgz",
"integrity": "sha512-hOSRInrIDm0Brzp4IHW2F/VM+638qOL2CzE0DgpnGzKW27C95IqqeqgKz/hxHGnvPxvQGpHUGD5qRVC9EZY2+A==",
"dev": true,
"license": "ISC"
},
@ -4521,16 +4521,16 @@
"license": "MIT"
},
"node_modules/send": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz",
"integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
@ -4562,16 +4562,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/send/node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/send/node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",

View file

@ -1,6 +1,6 @@
{
"name": "coryd.dev",
"version": "1.0.6",
"version": "1.0.0",
"description": "The source for my personal site. Built using 11ty (and other tools).",
"type": "module",
"scripts": {

View file

@ -1,40 +1,40 @@
#tracks-recent,
#tracks-window,
#tracks-chart,
#tracks-recent ~ .tracks-recent,
#tracks-window ~ .tracks-window {
#tracks-chart ~ .tracks-chart {
display: none;
}
#tracks-recent:checked ~ .tracks-recent,
#tracks-window:checked ~ .tracks-window {
#tracks-chart:checked ~ .tracks-chart {
display: block;
}
input[id="tracks-recent"] ~ .tracks-recent,
input[id="tracks-window"] ~ .tracks-window {
input[id="tracks-chart"] ~ .tracks-chart {
margin-top: var(--spacing-base);
}
input[id="tracks-recent"] ~ [for="tracks-recent"]:has(+ [for="tracks-window"]) {
input[id="tracks-recent"] ~ [for="tracks-recent"]:has(+ [for="tracks-chart"]) {
margin-right: var(--spacing-xs);
}
#tracks-recent:checked ~ [for="tracks-recent"],
#tracks-window:checked ~ [for="tracks-window"] {
#tracks-chart:checked ~ [for="tracks-chart"] {
cursor: not-allowed;
border-color: var(--accent-color);
background-color: var(--accent-color);
}
#tracks-recent:not(:checked) ~ [for="tracks-recent"],
#tracks-window:not(:checked) ~ [for="tracks-window"] {
#tracks-chart:not(:checked) ~ [for="tracks-chart"] {
color: var(--accent-color);
background: transparent;
}
#tracks-recent:not(:checked) ~ [for="tracks-recent"]:hover,
#tracks-recent:not(:checked) ~ [for="tracks-recent"]:active,
#tracks-window:not(:checked) ~ [for="tracks-window"]:hover,
#tracks-window:not(:checked) ~ [for="tracks-window"]:active {
#tracks-chart:not(:checked) ~ [for="tracks-chart"]:hover,
#tracks-chart:not(:checked) ~ [for="tracks-chart"]:active {
color: var(--accent-color-hover);
}

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: [],
}

View file

@ -47,7 +47,7 @@
{%- assign pageDescription = description -%}
{%- endif -%}
{%- assign ogImage = 'https://cdn.coryd.dev/' | append: globals.opengraph_default -%}
{%- assign ogImage = 'https://cdn.coryd.dev/' | append: globals.avatar | append: "?class=w800" -%}
{%- case schema -%}
{%- when 'music' -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: page.image -%}
@ -61,11 +61,20 @@
{%- when 'watching' -%}
{%- assign featuredMovie = movies.recentlyWatched | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredMovie.backdrop -%}
{%- when 'watching-shows' -%}
{%- assign featuredShow = tv.recentlyWatched | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredShow.backdrop -%}
{%- when 'favorite-movies' -%}
{%- assign featuredMovie = movies.favorites| shuffleArray | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredMovie.backdrop -%}
{%- when 'favorite-shows' -%}
{%- assign featuredShow = tv.favorites | shuffleArray | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredShow.backdrop -%}
{%- when 'books' -%}
{%- assign featuredBook = books.all | bookStatus: 'started' | reverse | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredBook.image -%}
{%- when 'books-year' -%}
{%- assign featuredBook = books.all | bookStatus: 'finished' | bookFinishedYear: year.value | bookSortDescending | first -%}
{%- assign featuredBook = books.all | bookStatus: 'finished' | bookFinishedYear: year.value | first -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: featuredBook.image -%}
{%- when 'book' -%}
{%- assign ogImage = 'https://cdn.coryd.dev' | append: book.image -%}
@ -95,12 +104,12 @@
<meta property="og:url" content="{{ fullUrl }}" />
<meta property="og:image" content="{{ ogImage }}?class=w800" />
<meta name="theme-color" content="{{ globals.theme_color }}" />
<meta name="fediverse:creator" content="@cory@follow.coryd.dev" />
<meta name="fediverse:creator" content="{{ globals.mastodon }}" />
<meta name="generator" content="Eleventy">
<meta name="robots" content="noai, noimageai">
<link href="https://cdn.coryd.dev/{{ globals.favicon_ico }}?class=w50&v={% appVersion %}" rel="icon" sizes="any">
<link href="https://cdn.coryd.dev/{{ globals.favicon_svg }}?class=w50&v={% appVersion %}" rel="icon" type="image/svg+xml">
<link href="https://cdn.coryd.dev/{{ globals.apple_touch_icon }}?class=w200&v={% appVersion %}" rel="apple-touch-icon">
<link href="https://cdn.coryd.dev{{ globals.avatar_transparent }}?class=w50&v={% appVersion %}" rel="icon" sizes="any">
<link href="https://cdn.coryd.dev{{ globals.avatar_transparent }}?class=w50&v={% appVersion %}&type=svg" rel="icon" type="image/svg+xml">
<link href="https://cdn.coryd.dev{{ globals.avatar_transparent }}?class=w200&v={% appVersion %}" rel="apple-touch-icon">
<link type="application/atom+xml" rel="alternate" title="Posts / {{ globals.site_name }}" href="https://coryd.dev/feeds/posts">
<link rel="alternate" href="https://coryd.dev/feeds/links" title="Links / {{ globals.site_name }}" type="application/rss+xml">
<link rel="alternate" href="https://coryd.dev/feeds/movies" title="Movies / {{ globals.site_name }}'s movies feed" type="application/rss+xml">

View file

@ -1,13 +1,13 @@
<img
srcset="
https://cdn.coryd.dev/{{ image }}?class=bannersm&type=webp 256w,
https://cdn.coryd.dev/{{ image }}?class=bannermd&type=webp 512w,
https://cdn.coryd.dev/{{ image }}?class=bannerbase&type=webp 1024w
https://cdn.coryd.dev{{ image }}?class=bannersm&type=webp 256w,
https://cdn.coryd.dev{{ image }}?class=bannermd&type=webp 512w,
https://cdn.coryd.dev{{ image }}?class=bannerbase&type=webp 1024w
"
sizes="(max-width: 450px) 256px,
(max-width: 850px) 512px
1024px"
src="https://cdn.coryd.dev/{{ image }}?class=bannersm&type=webp"
src="https://cdn.coryd.dev{{ image }}?class=bannersm&type=webp"
alt="{{ alt }}"
class="image-banner"
loading="lazy"

View file

@ -8,7 +8,7 @@
{%- elsif block.type == 'rss_banner' -%}
{% render "partials/blocks/banners/rss.liquid", url:block.url, text:block.text %}
{%- elsif block.type == 'hero' -%}
{% render "partials/blocks/hero.liquid", image:block.image.filename_disk, alt:block.alt_text %}
{% render "partials/blocks/hero.liquid", image:block.image, alt:block.alt %}
{%- elsif block.type == 'markdown' -%}
{{ block.text | markdown }}
{%- elsif block.type == 'divider' -%}

View file

@ -4,12 +4,12 @@
"home_page_url": "{{ permalink | absoluteUrl | escape }}",
"feed_url": "{{ permalink | absoluteUrl | escape }}.json",
"description": "{{ globals.site_description | escape }}",
"icon": "https://cdn.coryd.dev/{{ globals.feed_image | escape }}?class=w200&v={% appVersion %}",
"favicon": "https://cdn.coryd.dev/{{ globals.favicon_ico | escape }}?class=w50&v={% appVersion %}",
"icon": "https://cdn.coryd.dev{{ globals.avatar | escape }}?class=w200&v={% appVersion %}",
"favicon": "https://cdn.coryd.dev{{ globals.avatar | escape }}?class=w50&v={% appVersion %}",
"authors": [{
"name": "{{ globals.site_name }}",
"url": "{{ globals.url | escape }}",
"avatar": "https://cdn.coryd.dev/{{ globals.avatar | escape }}?class=w200&v={% appVersion %}"
"avatar": "https://cdn.coryd.dev{{ globals.avatar | escape }}?class=w200&v={% appVersion %}"
}],
"items": [
{%- assign entries = data | normalizeEntries: 20 -%}

View file

@ -11,7 +11,7 @@
<image>
<title><![CDATA[{{ title }}]]></title>
<link>{{ permalink | absoluteUrl }}</link>
<url>{{ "https://cdn.coryd.dev/" | append: globals.feed_image | append: "?class=w200" }}</url>
<url>{{ "https://cdn.coryd.dev" | append: globals.avatar | append: "?class=w200" }}</url>
<width>144</width>
<height>144</height>
</image>

View file

@ -1,7 +1,8 @@
{%- assign currentYear = 'now' | date: "%Y" -%}
{%- assign track = music.week.tracks | first -%}
{%- assign show = tv.recentlyWatched | first -%}
{%- assign movie = movies.recentlyWatched | first -%}
{%- assign book = books | bookStatus: 'finished' | bookSortDescending | first -%}
{%- assign book = books | bookFinishedYear: currentYear | first -%}
{%- assign link = links | first -%}
<article>
<h2>
@ -10,10 +11,10 @@
</h2>
<ul>
<li><span class="music">Top track this week:</span> <a href="{{ track.url }}">{{ track.title }} by {{ track.artist }}</a></li>
<li><span class="tv">Last episode watched:</span> <strong class="highlight-text">S{{ show.season }}E{{ show.episode }}</strong> of <a href="{{ show.url }}">{{ show.name }}</a></li>
<li><span class="tv">Last episode watched:</span> <strong class="highlight-text">{{ show.formatted_episode }}</strong> of <a href="{{ show.url }}">{{ show.title }}</a></li>
<li><span class="movies">Last movie watched:</span> <a href="{{ movie.url }}">{{ movie.title }}</a>{%- if movie.rating %} ({{ movie.rating }}){%- endif -%}</li>
<li><span class="books">Last book finished:</span> <a href="{{ book.url }}">{{ book.title }}</a> by {{ book.author }}{%- if book.rating %} ({{ book.rating }}){%- endif -%}</li>
<li><span class="link">Last link shared:</span> <a href="{{ link.link }}">{{ link.title }}</a>{% if link.authors %} via <a href="{{ link.authors.url }}">{{ link.authors.name }}</a>{% endif %}</li>
<li><span class="link">Last link shared:</span> <a href="{{ link.link }}">{{ link.title }}</a>{% if link.author %} via <a href="{{ link.author.url }}">{{ link.author.name }}</a>{% endif %}</li>
</ul>
{% render "partials/blocks/banners/rss.liquid", url: "/feeds", text: "Subscribe to my movies, books, links or activity feed(s)" %}
</article>

View file

@ -15,7 +15,7 @@
({{ item.year }})
</div>
{%- else -%}
<div class="header">{{ item.name }}</div>
<div class="header">{{ item.title }}</div>
<div class="subheader">({{ item.year }})</div>
{%- endif -%}
</div>

View file

@ -6,8 +6,9 @@ permalink: "/books/index.html"
updated: "now"
schema: books
---
{%- assign currentYear = 'now' | date: "%Y" -%}
{%- assign bookData = books.all | bookStatus: 'started' | reverse -%}
{%- assign currentBookCount = books.all | currentBookCount -%}
{%- assign currentBookCount = books.all | bookFinishedYear: currentYear | size -%}
<h2>Currently reading</h2>
<p>Here's what I'm reading at the moment. I've finished <strong class="highlight-text">{{ currentBookCount }} books</strong> this year.</p>
<p>{{ books.years | bookYearLinks }}</p>

View file

@ -7,7 +7,7 @@ pagination:
permalink: "/books/years/{{ year.value }}.html"
schema: books-year
---
{%- assign bookData = year.data | bookStatus: 'finished' | bookSortDescending -%}
{%- assign bookData = year.data | bookStatus: 'finished' -%}
{%- assign bookDataFavorites = bookData | bookFavorites -%}
{%- capture favoriteBooks -%}{{ bookDataFavorites | shuffleArray | mediaLinks: "book", 5 }}{%- endcapture -%}
{%- capture currentYear -%}{% currentYear %}{%- endcapture -%}

View file

@ -19,7 +19,7 @@ permalink: "/links/{% if pagination.pageNumber > 0 %}{{ pagination.pageNumber }}
<a href="{{ link.link }}" title="{{ link.title | escape }}">
<strong>{{ link.title }}</strong>
</a>
{% if link.authors %} via <a href="{{ link.authors.url }}">{{ link.authors.name }}</a>{% endif %}
{% if link.author %} via <a href="{{ link.author.url }}">{{ link.author.name }}</a>{% endif %}
</div>
{% endfor %}
</div>

View file

@ -34,13 +34,13 @@ schema: music-index
</h3>
<div class="track-display">
<input id="tracks-recent" name="track-options" type="radio" aria-hidden="true" checked />
<input id="tracks-window" name="track-options" type="radio" aria-hidden="true" />
<input id="tracks-chart" name="track-options" type="radio" aria-hidden="true" />
<label for="tracks-recent" class="button" data-toggle="tracks-recent">Recent</label>
<label for="tracks-window" class="button" data-toggle="tracks-window">This week</label>
<label for="tracks-chart" class="button" data-toggle="tracks-chart">This week</label>
<div class="tracks-recent">
{% render "partials/media/music/recent", data:music.recent %}
</div>
<div class="tracks-window">
<div class="tracks-chart">
{% render "partials/media/music/chart.liquid", data:music.week.tracks, mostPlayed:music.week.tracks[0].plays, count: 10 %}
</div>
</div>

View file

@ -6,7 +6,7 @@ pagination:
alias: page
description: "{{ page.description }}"
permalink: "{{ page.permalink }}/index.html"
image: "{{ page.open_graph_image | prepend: 'https://cdn.coryd.dev/' | default: globals.meta_data.opengraph_default }}"
image: "{{ page.open_graph_image | prepend: 'https://cdn.coryd.dev' | default: globals.avatar }}"
updated: {{ page.updated | default: null }}
---
{% render "partials/blocks/index.liquid", blocks:page.blocks, collections:collections, links:links %}
{% render "partials/blocks/index.liquid", blocks:page.blocks %}

View file

@ -6,7 +6,7 @@ pagination:
data: movies.favorites
size: 24
permalink: "/watching/favorite-movies/{% if pagination.pageNumber > 0 %}{{ pagination.pageNumber }}/{% endif %}index.html"
schema: watching
schema: favorite-movies
---
<a class="icon-link" href="/watching" title="Go back to the watching index page">{% tablericon "arrow-left" %} Back to watching</a>
{% if pagination.pageNumber == 0 %}

View file

@ -6,7 +6,7 @@ pagination:
data: tv.favorites
size: 24
permalink: "/watching/favorite-shows/{% if pagination.pageNumber > 0 %}{{ pagination.pageNumber }}/{% endif %}index.html"
schema: watching
schema: favorite-shows
---
<a class="icon-link" href="/watching" title="Go back to the watching index page">{% tablericon "arrow-left" %} Back to watching</a>
{% if pagination.pageNumber == 0 %}

View file

@ -32,7 +32,7 @@ schema: watching
Favorite movies
</a>
</h3>
{% assign favoriteMovies = movies.favorites | featuredWatching: 6 %}
{% assign favoriteMovies = movies.favorites | shuffleArray | featuredWatching: 6 %}
{% render "partials/media/watching/grid.liquid", mediaItems:favoriteMovies, count: 6 %}
<h3 id="favorite-shows">
<a class="icon-link" href="/watching/favorite-shows">
@ -40,5 +40,5 @@ schema: watching
Favorite shows
</a>
</h3>
{% assign favoriteShows = tv.favorites | featuredWatching: 6 %}
{% assign favoriteShows = tv.favorites | shuffleArray | featuredWatching: 6 %}
{% render "partials/media/watching/grid.liquid", mediaItems:favoriteShows, count: 6 %}

View file

@ -6,7 +6,7 @@ pagination:
data: tv.recentlyWatched
size: 24
permalink: "/watching/recent/shows/{% if pagination.pageNumber > 0 %}{{ pagination.pageNumber }}/{% endif %}index.html"
schema: watching
schema: watching-shows
---
<a class="icon-link" href="/watching" title="Go back to the watching index page">{% tablericon "arrow-left" %} Back to watching</a>
{% if pagination.pageNumber == 0 %}

View file

@ -10,7 +10,6 @@ schema: show
{%- capture alt -%}
{{ show.title }} / {{ show.year }}
{%- endcapture -%}
{% assign lastWatched = show | getLastWatched %}
<a class="icon-link" href="/watching" title="Go back to the watching index page">{% tablericon "arrow-left" %} Back to watching</a>
<article class="watching-focus">
<img
@ -41,13 +40,9 @@ schema: show
{%- if show.collected -%}
<p class="sub-meta collected">{% tablericon "circle-check" %} This show is in my collection!</p>
{%- endif -%}
{%- if lastWatched -%}
{%- if show.episode.formatted_episode -%}
{%- capture lastWatchedText -%}
{%- if show.episodes -%}
I last watched <strong class="highlight-text">{{ show.episodes | lastWatchedEpisode }}</strong> on {{ lastWatched | date: "%B %e, %Y" }}.
{%- else -%}
Last watched on {{ lastWatched | date: "%B %e, %Y" }}.
{%- endif -%}
I last watched <strong class="highlight-text">{{ show.episode.formatted_episode }}</strong> on {{ show.episode.last_watched_at | date: "%B %e, %Y" }}.
{%- endcapture -%}
<p class="sub-meta">{{ lastWatchedText }}</p>
{%- endif -%}

View file

@ -9,6 +9,6 @@ permalink: "/feeds/album-releases.json"
title:"Album releases / Cory Dransfeldt"
globals:globals
data:releases
updated:releases[0].release_date
updated:releases[0].releaseDate
appVersion:appVersion
%}

View file

@ -3,7 +3,7 @@ layout: null
eleventyExcludeFromCollections: true
permalink: "/feeds/books.json"
---
{%- assign bookData = books.all | bookStatus: 'finished' | bookSortDescending -%}
{%- assign bookData = books.all | bookStatus: 'finished' -%}
{% render "partials/feeds/json.liquid"
permalink:"/feeds/books"
title:"Books / Cory Dransfeldt"

View file

@ -9,5 +9,5 @@ permalink: "/feeds/album-releases"
title:"Album releases / Cory Dransfeldt"
globals:globals
data:releases
updated:releases[0].release_date
updated:releases[0].releaseDate
%}

View file

@ -3,7 +3,7 @@ layout: null
eleventyExcludeFromCollections: true
permalink: "/feeds/books"
---
{%- assign bookData = books.all | bookStatus: 'finished' | bookSortDescending -%}
{%- assign bookData = books.all | bookStatus: 'finished' -%}
{% render "partials/feeds/rss.liquid"
permalink:"/feeds/books"
title:"Books / Cory Dransfeldt"