diff --git a/.env b/.env index e55e13be..ae91472e 100644 --- a/.env +++ b/.env @@ -1,5 +1,7 @@ API_KEY_LASTFM= API_KEY_TRAKT= API_KEY_WEBMENTIONS_CORYD_DEV= +API_BEARER_APPLE_MUSIC= +API_TOKEN_APPLE_MUSIC= SECRET_FEED_INSTAPAPER_FAVORITES= SECRET_FEED_ALBUM_RELEASES= \ No newline at end of file diff --git a/config/mediaFilters.js b/config/mediaFilters.js index caa9cc80..5b686ffb 100644 --- a/config/mediaFilters.js +++ b/config/mediaFilters.js @@ -1,16 +1,6 @@ -const ALBUM_DENYLIST = ['no-love-deep-web', 'unremittance'] - module.exports = { artist: (media) => `https://cdn.coryd.dev/artists/${media.replace(/\s+/g, '-').toLowerCase()}.jpg`, - album: (media) => { - return !ALBUM_DENYLIST.includes(media.name.replace(/\s+/g, '-').toLowerCase()) - ? media.image[media.image.length - 1]['#text'].replace( - 'https://lastfm.freetls.fastly.net', - 'https://albums.coryd.dev' - ) - : `https://cdn.coryd.dev/albums/${media.name.replace(/\s+/g, '-').toLowerCase()}.jpg` - }, tv: (episode) => `https://cdn.coryd.dev/tv/${episode.replace(':', '').replace(/\s+/g, '-').toLowerCase()}.jpg`, cdn: (url, host, cdn) => { diff --git a/src/_data/heavyRotation.js b/src/_data/heavyRotation.js new file mode 100644 index 00000000..2bd825b7 --- /dev/null +++ b/src/_data/heavyRotation.js @@ -0,0 +1,20 @@ +const EleventyFetch = require('@11ty/eleventy-fetch') + +module.exports = async function () { + const APPLE_BEARER = process.env.API_BEARER_APPLE_MUSIC + const APPLE_TOKEN = process.env.API_TOKEN_APPLE_MUSIC + const url = `https://api.music.apple.com/v1/me/history/heavy-rotation` + const res = EleventyFetch(url, { + duration: '1h', + type: 'json', + fetchOptions: { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${APPLE_BEARER}`, + 'music-user-token': `${APPLE_TOKEN}`, + }, + }, + }).catch() + const rotation = await res + return rotation.data +} diff --git a/src/_data/recentTracks.js b/src/_data/recentTracks.js new file mode 100644 index 00000000..d1abc7c6 --- /dev/null +++ b/src/_data/recentTracks.js @@ -0,0 +1,62 @@ +const { AssetCache } = require('@11ty/eleventy-fetch') + +const sortTrim = (array, length = 5) => + Object.values(array) + .sort((a, b) => b.plays - a.plays) + .splice(0, length) + +module.exports = async function () { + const APPLE_BEARER = process.env.API_BEARER_APPLE_MUSIC + const APPLE_TOKEN = process.env.API_TOKEN_APPLE_MUSIC + const PAGE_SIZE = 30 + let CURRENT_PAGE = 0 + const PAGES = 4 + let res = [] + const asset = new AssetCache('recent_tracks_data') + if (asset.isCacheValid('1h')) return await asset.getCachedValue() + while (CURRENT_PAGE < PAGES) { + const URL = `https://api.music.apple.com/v1/me/recent/played/tracks?limit=${PAGE_SIZE}&offset=${ + PAGE_SIZE * CURRENT_PAGE + }` + const tracks = await fetch(URL, { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${APPLE_BEARER}`, + 'music-user-token': `${APPLE_TOKEN}`, + }, + }) + .then((data) => data.json()) + .catch() + res = [...res, ...tracks.data] + CURRENT_PAGE++ + } + const response = { + artists: {}, + tracks: {}, + } + res.forEach((track) => { + // aggregate artists + if (!response.artists[track.attributes.artistName]) { + response.artists[track.attributes.artistName] = { + name: track.attributes.artistName, + plays: 1, + } + } else { + response.artists[track.attributes.artistName].plays++ + } + + // aggregate tracks + if (!response.tracks[track.attributes.name]) { + response.tracks[track.attributes.name] = { + name: track.attributes.name, + plays: 1, + } + } else { + response.tracks[track.attributes.name].plays++ + } + }) + response.artists = sortTrim(response.artists, 4) + response.tracks = sortTrim(response.tracks) + await asset.save(response, 'json') + return response +} diff --git a/src/_data/site.json b/src/_data/site.json index 56f4c5cf..d1d6155a 100644 --- a/src/_data/site.json +++ b/src/_data/site.json @@ -8,7 +8,7 @@ "fastmail": "mailto:hi@coryd.dev", "github": "https://github.com/cdransf", "mastodon": "https://social.lol/@cory", - "lastfm": "https://last.fm/user/cdme_", + "applemusic": "https://music.apple.com/profile/cdransf", "listenbrainz": "https://listenbrainz.org/user/cdransf/", "instapaper": "https://www.instapaper.com/p/coryd", "letterboxd": "https://letterboxd.com/cdme", diff --git a/src/_includes/footer.liquid b/src/_includes/footer.liquid index 43815045..a544ebc2 100644 --- a/src/_includes/footer.liquid +++ b/src/_includes/footer.liquid @@ -3,7 +3,7 @@ {% include "icons/fastmail.liquid" %} {% include "icons/github.liquid" %} {% include "icons/mastodon.liquid" %} - {% include "icons/lastfm.liquid" %} + {% include "icons/apple-music.liquid" %} {% include "icons/instapaper.liquid" %} {% include "icons/letterboxd.liquid" %} {% include "icons/trakt.liquid" %} diff --git a/src/_includes/icons/apple-music.liquid b/src/_includes/icons/apple-music.liquid new file mode 100644 index 00000000..e3db63c6 --- /dev/null +++ b/src/_includes/icons/apple-music.liquid @@ -0,0 +1,13 @@ +{% if site.applemusic != "" %} + <a + href={{ site.applemusic }} + rel="me" + title="Apple Music"> + <svg + class="inline w-6 h-6 fill-current text-gray-700 hover:text-purple-500 dark:text-gray-200 dark:hover:text-purple-500" + role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Apple Music</title> + <path + d="M23.994 6.124a9.23 9.23 0 00-.24-2.19c-.317-1.31-1.062-2.31-2.18-3.043a5.022 5.022 0 00-1.877-.726 10.496 10.496 0 00-1.564-.15c-.04-.003-.083-.01-.124-.013H5.986c-.152.01-.303.017-.455.026-.747.043-1.49.123-2.193.4-1.336.53-2.3 1.452-2.865 2.78-.192.448-.292.925-.363 1.408-.056.392-.088.785-.1 1.18 0 .032-.007.062-.01.093v12.223c.01.14.017.283.027.424.05.815.154 1.624.497 2.373.65 1.42 1.738 2.353 3.234 2.801.42.127.856.187 1.293.228.555.053 1.11.06 1.667.06h11.03a12.5 12.5 0 001.57-.1c.822-.106 1.596-.35 2.295-.81a5.046 5.046 0 001.88-2.207c.186-.42.293-.87.37-1.324.113-.675.138-1.358.137-2.04-.002-3.8 0-7.595-.003-11.393zm-6.423 3.99v5.712c0 .417-.058.827-.244 1.206-.29.59-.76.962-1.388 1.14-.35.1-.706.157-1.07.173-.95.045-1.773-.6-1.943-1.536a1.88 1.88 0 011.038-2.022c.323-.16.67-.25 1.018-.324.378-.082.758-.153 1.134-.24.274-.063.457-.23.51-.516a.904.904 0 00.02-.193c0-1.815 0-3.63-.002-5.443a.725.725 0 00-.026-.185c-.04-.15-.15-.243-.304-.234-.16.01-.318.035-.475.066-.76.15-1.52.303-2.28.456l-2.325.47-1.374.278c-.016.003-.032.01-.048.013-.277.077-.377.203-.39.49-.002.042 0 .086 0 .13-.002 2.602 0 5.204-.003 7.805 0 .42-.047.836-.215 1.227-.278.64-.77 1.04-1.434 1.233-.35.1-.71.16-1.075.172-.96.036-1.755-.6-1.92-1.544-.14-.812.23-1.685 1.154-2.075.357-.15.73-.232 1.108-.31.287-.06.575-.116.86-.177.383-.083.583-.323.6-.714v-.15c0-2.96 0-5.922.002-8.882 0-.123.013-.25.042-.37.07-.285.273-.448.546-.518.255-.066.515-.112.774-.165.733-.15 1.466-.296 2.2-.444l2.27-.46c.67-.134 1.34-.27 2.01-.403.22-.043.442-.088.663-.106.31-.025.523.17.554.482.008.073.012.148.012.223.002 1.91.002 3.822 0 5.732z"/> + </svg> + </a> +{% endif %} \ No newline at end of file diff --git a/src/_includes/icons/lastfm.liquid b/src/_includes/icons/lastfm.liquid deleted file mode 100644 index be4508a5..00000000 --- a/src/_includes/icons/lastfm.liquid +++ /dev/null @@ -1,13 +0,0 @@ -{% if site.lastfm != "" %} - <a - href={{ site.lastfm }} - rel="me" - title="Last.fm"> - <svg - class="inline w-6 h-6 fill-current text-gray-700 hover:text-purple-500 dark:text-gray-200 dark:hover:text-purple-500" - role="img" - viewBox="0 0 24 24" - xmlns="http://www.w3.org/2000/svg"> - <title>Last.fm</title><path d="M10.584 17.21l-.88-2.392s-1.43 1.594-3.573 1.594c-1.897 0-3.244-1.649-3.244-4.288 0-3.382 1.704-4.591 3.381-4.591 2.42 0 3.189 1.567 3.849 3.574l.88 2.749c.88 2.666 2.529 4.81 7.285 4.81 3.409 0 5.718-1.044 5.718-3.793 0-2.227-1.265-3.381-3.63-3.931l-1.758-.385c-1.21-.275-1.567-.77-1.567-1.595 0-.934.742-1.484 1.952-1.484 1.32 0 2.034.495 2.144 1.677l2.749-.33c-.22-2.474-1.924-3.492-4.729-3.492-2.474 0-4.893.935-4.893 3.932 0 1.87.907 3.051 3.189 3.601l1.87.44c1.402.33 1.869.907 1.869 1.704 0 1.017-.99 1.43-2.86 1.43-2.776 0-3.93-1.457-4.59-3.464l-.907-2.75c-1.155-3.573-2.997-4.893-6.653-4.893C2.144 5.333 0 7.89 0 12.233c0 4.18 2.144 6.434 5.993 6.434 3.106 0 4.591-1.457 4.591-1.457z" /></svg> - </a> -{% endif %} \ No newline at end of file diff --git a/src/_includes/now.liquid b/src/_includes/now.liquid index 545feaf8..d486b9fa 100644 --- a/src/_includes/now.liquid +++ b/src/_includes/now.liquid @@ -2,191 +2,185 @@ layout: main --- {% include "header.liquid" %} -<ul class="pt-12 prose dark:prose-invert hover:prose-a:text-blue-500 max-w-full"> - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "clock" "Currently" "height=28" %} - <div class="ml-1">Currently</div> - </h2> - <div class="pl-4 md:pl-8"> - <p class="my-2">{{ status.emoji }} {{ status.content }}</p> - <p class="my-2"> - <span class="icon-inline mr-1">{% heroicon "solid" "map" "Map" "width=20 height=20" %}</span> - Living in Camarillo, California with my beautiful family, 4 rescue dogs and a guinea pig. - </p> - <p class="my-2"> - <span class="icon-inline mr-1"> - <svg - class="fill-gray-800 dark:fill-white w-5" - role="img" - viewBox="0 0 24 24" - xmlns="http://www.w3.org/2000/svg"> - <title>NBA</title><path d="M9.19 0a2.486 2.486 0 0 0-2.485 2.484v19.029A2.488 2.488 0 0 0 9.19 24h5.615a2.493 2.493 0 0 0 2.49-2.487V2.484A2.488 2.488 0 0 0 14.81 0zm0 .584h3.21c-.62.237-.707.508-.73 1.366-.105.01-.325-.087-.25.434 0 0 .043.346.18.286-.133.918.023.99-.93 1.031l-.047.067c-.95.093-1.25-.027-2.05 1.603 0 0-.207.505-.268.714-.197.415-.674 1.328-.819 1.919-.046.2-.14.264-.01.553.185.417-.124.527.95.496V9.3s-.286.247-.346.398c-.061.147-.226.89-.22 1.237.019.917.767 1.683.992 2.597l.492.07c.282.634 1.495 2.355 1.743 2.582.057.159.365.355.545.551.149.141 1.025 1.1 2.054 1.692-.007-.001.164.344.249.618-.342.275.32.777.52 1.609.012.107-.19.222.114.495-.022 1.256-.402 1.918.241 2.266H9.191a1.9 1.9 0 0 1-1.9-1.901V2.486a1.9 1.9 0 0 1 1.9-1.902zm3.804.002h1.815a1.9 1.9 0 0 1 1.897 1.898v9.193a1.653 1.653 0 0 0-.22-.397c0-.255-.272-.249-.346-.344-.07-.081.067-.128-.407-.235-.09-.05-.158-.747-.158-.747-.07-.447-.229-.754-.467-1.227-.12-.243-.177-1.001-.305-1.386.071-1.767-.493-2.28-.95-2.569-.174-.11-.262-.191-.433-.29l-.005-.082c-.133-.126-.402-.264-.623-.362-.068-.07-.037-.22.01-.276.15-.02.348-.356.513-.703.129.009.174-.118.214-.19.138-.222.288-.413.096-.542.435-.777.154-1.301-.08-1.321-.095-.195-.26-.316-.551-.42zm.551 6.338c.06.319.34 1.929.456 2.187.123.259.535 1.05.73 1.54a1.69 1.69 0 0 0-1.294 1.646 1.692 1.692 0 0 0 1.693 1.691 1.692 1.692 0 0 0 1.576-1.066v8.59a1.887 1.887 0 0 1-1.598 1.877h-.017c.833-.502.319-1.46.16-2.022-.012-.033.014-.074.026-.1.045-.08-.045-.257-.045-.257-.098-.09-.127-.561-.182-.772-.089-.358.157-.971.157-1.18 0-.206-.156-.491-.445-.858-.069-.078-.276-1.86-.462-2.313-.258-.623-.339-.526-.64-1.266-.24-.525-.055-1.295-.59-3.085.005.006.12-.113.12-.113s-.422-1.55-.561-1.975c-.14-.426-.385-.456-.385-.456s.002-.172.012-.216c.02-.07.516-1.367.558-1.407.001-.03.717-.514.731-.445Z" /></svg> - </span> - Rooting for the - <a href="https://lakers.com">Lakers</a>, for better or worse. (On to next season 💜💛.) - </p> - {{ content }} - </div> - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "terminal" "Making" "height=28" %} - <div class="ml-1">Making</div> - </h2> - <div class="pl-4 md:pl-8"> - <p class="my-2"> - <span class="icon-inline mr-1">{% heroicon "solid" "desktop-computer" "Hacking" "width=20 height=20" %}</span> - Hacking away on random projects like this page, my - <a href="/">blog</a>, and whatever else I can find time for.</p> - <p class="my-2"> - <span class="icon-inline mr-1">{% heroicon "solid" "hand" "hand" "width=20 height=20" %}</span> - <a href="https://github.com/cdransf/awesome-adblock">Assembling lists of ad and tracker-blocking tools.</a> - </p> - </div> - {% if artists.size > 0 %} - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "microphone" "Artists" "height=28" %} - <div class="ml-1">Artists</div> - </h2> - <div class="grid grid-cols-2 gap-2 md:grid-cols-4 not-prose"> - {% for artist in artists %} - <a href="{{artist.url}}" title="{{artist.name | escape}}"> - <div class="relative block"> - <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> - <div class="absolute left-1 bottom-2 drop-shadow-md"> - <div class="px-1 text-xs font-bold text-white">{{ artist.name }}</div> - <div class="px-1 text-xs text-white"> - {{ artist.playcount }} plays - </div> - </div> - {%- capture artistImg %}{{ artist.name | artist }}{% endcapture -%} - {%- capture artistName %}{{ artist.name | escape }}{% endcapture -%} - {% image artistImg, artistName, 'rounded-lg', '225px', 'eager' %} - </div> - </a> - {% endfor %} - </div> - {% endif %} - {% if albums.size > 0 %} - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "music-note" "Albums" "height=28" %} - <div class="ml-1">Albums</div> - </h2> - <div class="grid grid-cols-2 gap-2 md:grid-cols-4 not-prose"> - {% for album in albums %} - <a href="{{album.url}}" title="{{album.name | escape}}"> - <div class="relative block"> - <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> - <div class="absolute left-1 bottom-2 drop-shadow-md"> - <div class="px-1 text-xs font-bold text-white">{{ album.name }}</div> - <div class="px-1 text-xs text-white"> - {{ album.artist.name }} - </div> - </div> - {%- capture albumImg %}{{ album | album }}{% endcapture -%} - {%- capture albumName %}{{ album.name | escape }}{% endcapture -%} - {% image albumImg, albumName, 'rounded-lg', '225px' %} - </div> - </a> - {% endfor %} - </div> - {% endif %} - {% if albumReleases.size > 0 %} - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "calendar" "Anticipated albums" "height=28" %} - <div class="ml-1">Anticipated albums</div> - </h2> - <ul class="list-inside list-disc pl-5 md:pl-10"> - {% for album in albumReleases %} - <li class="mt-1.5 mb-2"> - <span class="font-bold">{{ album.startDate | readableDate }}: </span> - <a href="https://{{album.location}}" title="{{album.summary | escape}}"> - {{album.summary}} - </a> - </li> - {% endfor %} - </ul> - {% endif %} - {% if books.size > 0 %} - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "bookmark" "Books" "height=28" %} - <div class="ml-1">Books</div> - </h2> - <div class="grid grid-cols-3 gap-2 md:grid-cols-6 not-prose"> - {% for book in books %} - <a href="{{book.link}}" title="{{book.title | escape}}"> - <div class="relative block" style="max-width:226px"> - <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> - <div class="absolute left-1 bottom-2 drop-shadow-md"> - <div class="px-1 text-xs font-bold text-white">{{ book.title }}</div> - </div> - {%- capture bookImg %}{{book.image | cdn: site.oku-host, site.cdn-books}}{% endcapture -%} - {%- capture bookName %}{{book.title | escape}}{% endcapture -%} - {% image bookImg, bookName, 'rounded-lg w-full', '180px' %} - </div> - </a> - {% endfor %} - </div> - {% endif %} - {% if links.size > 0 %} - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "newspaper" "Links" "height=28" %} - <div class="ml-1">Links</div> - </h2> - <ul class="list-inside list-disc pl-5 md:pl-10"> - {% for link in links %} - <li class="mt-1.5 mb-2"> - <a href="{{link.link}}" title="{{link.title | escape}}"> - {{ link.title }} - </a> - </li> - {% endfor %} - </ul> - {% endif %} - {% if movies.size > 0 %} - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "film" "Movies" "height=28" %} - <div class="ml-1">Movies</div> - </h2> - <div class="grid grid-cols-3 gap-2 md:grid-cols-6 not-prose"> - {% for movie in movies %} - <a href="{{movie.link}}" title="{{movie.title | escape}}"> - <div class="relative block" style="max-width:226px"> - <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> - <div class="absolute left-1 bottom-2 drop-shadow-md"> - <div class="px-1 text-xs font-bold text-white">{{ movie.title }}</div> - </div> - {%- capture movieImg %}{{movie.image | cdn: site.letterboxd-host, site.cdn-movies}}{% endcapture -%} - {%- capture movieName %}{{movie.title | escape}}{% endcapture -%} - {% image movieImg, movieName, 'rounded-lg w-full', '180px' %} - </div> - </a> - {% endfor %} - </div> - {% endif %} - {% if tv.size > 0 %} - <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> - {% heroicon "solid" "video-camera" "TV" "height=28" %} - <div class="ml-1">TV</div> - </h2> - <div class="grid grid-cols-3 gap-2 md:grid-cols-6 not-prose"> - {% for episode in tv %} - <a href="https://trakt.tv/shows/{{episode.show.ids.slug}}/seasons/{{ episode.episode.season }}/episodes/{{ episode.episode.number }}" title="{{ episode.episode.title | escape}} {{ episode.show.title | escape }}"> - <div class="relative block" style="max-width:226px"> - <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> - <div class="absolute left-1 bottom-2 drop-shadow-md"> - <div class="px-1 text-xs font-bold text-white">{{ episode.episode.title }}</div> - <div class="px-1 text-xs text-white"> - {{ episode.show.title }} • <strong>S</strong>{{ episode.episode.season }}<strong>E</strong>{{ episode.episode.number }} - </div> - </div> - {%- capture tvImg %}{{episode.show.title | tv}}{% endcapture -%} - {%- capture tvName %}{{ episode.episode.title | escape}} {{ episode.show.title | escape }}{% endcapture -%} - {% image tvImg, tvName, 'rounded-lg w-full', '180px' %} - </div> - </a> - {% endfor %} - </div> - {% endif %} - <p class="text-xs text-center pt-4">This is a - <a href="https://nownownow.com/about">now page</a>, and if you have your own site, - <a href="https://nownownow.com/about">you should make one too</a>.</p> +<h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "clock" "Currently" "height=28" %} + <div class="ml-1">Currently</div> +</h2> +<div class="pl-4 md:pl-8"> + <p class="my-2">{{ status.emoji }} {{ status.content }}</p> + <p class="my-2"> + <span class="icon-inline mr-1">{% heroicon "solid" "map" "Map" "width=20 height=20" %}</span> + Living in Camarillo, California with my beautiful family, 4 rescue dogs and a guinea pig. + </p> + <p class="my-2"> + <span class="icon-inline mr-1"> + <svg + class="fill-gray-800 dark:fill-white w-5" + role="img" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg"> + <title>NBA</title><path d="M9.19 0a2.486 2.486 0 0 0-2.485 2.484v19.029A2.488 2.488 0 0 0 9.19 24h5.615a2.493 2.493 0 0 0 2.49-2.487V2.484A2.488 2.488 0 0 0 14.81 0zm0 .584h3.21c-.62.237-.707.508-.73 1.366-.105.01-.325-.087-.25.434 0 0 .043.346.18.286-.133.918.023.99-.93 1.031l-.047.067c-.95.093-1.25-.027-2.05 1.603 0 0-.207.505-.268.714-.197.415-.674 1.328-.819 1.919-.046.2-.14.264-.01.553.185.417-.124.527.95.496V9.3s-.286.247-.346.398c-.061.147-.226.89-.22 1.237.019.917.767 1.683.992 2.597l.492.07c.282.634 1.495 2.355 1.743 2.582.057.159.365.355.545.551.149.141 1.025 1.1 2.054 1.692-.007-.001.164.344.249.618-.342.275.32.777.52 1.609.012.107-.19.222.114.495-.022 1.256-.402 1.918.241 2.266H9.191a1.9 1.9 0 0 1-1.9-1.901V2.486a1.9 1.9 0 0 1 1.9-1.902zm3.804.002h1.815a1.9 1.9 0 0 1 1.897 1.898v9.193a1.653 1.653 0 0 0-.22-.397c0-.255-.272-.249-.346-.344-.07-.081.067-.128-.407-.235-.09-.05-.158-.747-.158-.747-.07-.447-.229-.754-.467-1.227-.12-.243-.177-1.001-.305-1.386.071-1.767-.493-2.28-.95-2.569-.174-.11-.262-.191-.433-.29l-.005-.082c-.133-.126-.402-.264-.623-.362-.068-.07-.037-.22.01-.276.15-.02.348-.356.513-.703.129.009.174-.118.214-.19.138-.222.288-.413.096-.542.435-.777.154-1.301-.08-1.321-.095-.195-.26-.316-.551-.42zm.551 6.338c.06.319.34 1.929.456 2.187.123.259.535 1.05.73 1.54a1.69 1.69 0 0 0-1.294 1.646 1.692 1.692 0 0 0 1.693 1.691 1.692 1.692 0 0 0 1.576-1.066v8.59a1.887 1.887 0 0 1-1.598 1.877h-.017c.833-.502.319-1.46.16-2.022-.012-.033.014-.074.026-.1.045-.08-.045-.257-.045-.257-.098-.09-.127-.561-.182-.772-.089-.358.157-.971.157-1.18 0-.206-.156-.491-.445-.858-.069-.078-.276-1.86-.462-2.313-.258-.623-.339-.526-.64-1.266-.24-.525-.055-1.295-.59-3.085.005.006.12-.113.12-.113s-.422-1.55-.561-1.975c-.14-.426-.385-.456-.385-.456s.002-.172.012-.216c.02-.07.516-1.367.558-1.407.001-.03.717-.514.731-.445Z" /></svg> + </span> + Rooting for the + <a href="https://lakers.com">Lakers</a>, for better or worse. (On to next season 💜💛.) + </p> + {{ content }} </div> +<h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "terminal" "Making" "height=28" %} + <div class="ml-1">Making</div> +</h2> +<div class="pl-4 md:pl-8"> + <p class="my-2"> + <span class="icon-inline mr-1">{% heroicon "solid" "desktop-computer" "Hacking" "width=20 height=20" %}</span> + Hacking away on random projects like this page, my + <a href="/">blog</a>, and whatever else I can find time for.</p> + <p class="my-2"> + <span class="icon-inline mr-1">{% heroicon "solid" "hand" "hand" "width=20 height=20" %}</span> + <a href="https://github.com/cdransf/awesome-adblock">Assembling lists of ad and tracker-blocking tools.</a> + </p> +</div> +{% if recentTracks.size > 0 %} + <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "microphone" "Artists" "height=28" %} + <div class="ml-1">Artists</div> + </h2> + <div class="grid grid-cols-2 gap-2 md:grid-cols-4 not-prose"> + {% for artist in recentTracks.artists %} + <a href="https://rateyourmusic.com/search?searchterm={{ artist.name | escape }}" title="{{artist.name | escape}}"> + <div class="relative block"> + <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> + <div class="absolute left-1 bottom-2 drop-shadow-md"> + <div class="px-1 text-xs font-bold text-white">{{ artist.name }}</div> + </div> + {%- capture artistImg %}{{ artist.name | artist }}{% endcapture -%} + {%- capture artistName %}{{ artist.name | escape }}{% endcapture -%} + {% image artistImg, artistName, 'rounded-lg', '225px', 'eager' %} + </div> + </a> + {% endfor %} + </div> +{% endif %} +{% if heavyRotation.size > 0 %} + <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "music-note" "Albums" "height=28" %} + <div class="ml-1">Albums</div> + </h2> + <div class="grid grid-cols-2 gap-2 md:grid-cols-4 not-prose"> + {% for album in heavyRotation %} + <a href="https://rateyourmusic.com/search?searchtype=l&searchterm={{album.attributes.name | escape}}" title="{{album.attributes.name | escape}}"> + <div class="relative block"> + <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> + <div class="absolute left-1 bottom-2 drop-shadow-md"> + <div class="px-1 text-xs font-bold text-white">{{ album.attributes.name }}</div> + <div class="px-1 text-xs text-white"> + {{ album.attributes.artistName }} + </div> + </div> + {%- capture albumName %}{{ album.attributes.name | escape }}{% endcapture -%} + {% image album.attributes.artwork.url, albumName, 'rounded-lg', '225px' %} + </div> + </a> + {% endfor %} + </div> +{% endif %} +{% if albumReleases.size > 0 %} + <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "calendar" "Anticipated albums" "height=28" %} + <div class="ml-1">Anticipated albums</div> + </h2> + <ul class="list-inside list-disc pl-5 md:pl-10"> + {% for album in albumReleases %} + <li class="mt-1.5 mb-2"> + <span class="font-bold">{{ album.startDate | readableDate }}: </span> + <a href="https://{{album.location}}" title="{{album.summary | escape}}"> + {{album.summary}} + </a> + </li> + {% endfor %} + </ul> +{% endif %} +{% if books.size > 0 %} + <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "bookmark" "Books" "height=28" %} + <div class="ml-1">Books</div> + </h2> + <div class="grid grid-cols-3 gap-2 md:grid-cols-6 not-prose"> + {% for book in books %} + <a href="{{book.link}}" title="{{book.title | escape}}"> + <div class="relative block" style="max-width:226px"> + <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> + <div class="absolute left-1 bottom-2 drop-shadow-md"> + <div class="px-1 text-xs font-bold text-white">{{ book.title }}</div> + </div> + {%- capture bookImg %}{{book.image | cdn: site.oku-host, site.cdn-books}}{% endcapture -%} + {%- capture bookName %}{{book.title | escape}}{% endcapture -%} + {% image bookImg, bookName, 'rounded-lg w-full', '180px' %} + </div> + </a> + {% endfor %} + </div> +{% endif %} +{% if links.size > 0 %} + <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "newspaper" "Links" "height=28" %} + <div class="ml-1">Links</div> + </h2> + <ul class="list-inside list-disc pl-5 md:pl-10"> + {% for link in links %} + <li class="mt-1.5 mb-2"> + <a href="{{link.link}}" title="{{link.title | escape}}"> + {{ link.title }} + </a> + </li> + {% endfor %} + </ul> +{% endif %} +{% if movies.size > 0 %} + <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "film" "Movies" "height=28" %} + <div class="ml-1">Movies</div> + </h2> + <div class="grid grid-cols-3 gap-2 md:grid-cols-6 not-prose"> + {% for movie in movies %} + <a href="{{movie.link}}" title="{{movie.title | escape}}"> + <div class="relative block" style="max-width:226px"> + <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> + <div class="absolute left-1 bottom-2 drop-shadow-md"> + <div class="px-1 text-xs font-bold text-white">{{ movie.title }}</div> + </div> + {%- capture movieImg %}{{movie.image | cdn: site.letterboxd-host, site.cdn-movies}}{% endcapture -%} + {%- capture movieName %}{{movie.title | escape}}{% endcapture -%} + {% image movieImg, movieName, 'rounded-lg w-full', '180px' %} + </div> + </a> + {% endfor %} + </div> +{% endif %} +{% if tv.size > 0 %} + <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4"> + {% heroicon "solid" "video-camera" "TV" "height=28" %} + <div class="ml-1">TV</div> + </h2> + <div class="grid grid-cols-3 gap-2 md:grid-cols-6 not-prose"> + {% for episode in tv %} + <a href="https://trakt.tv/shows/{{episode.show.ids.slug}}/seasons/{{ episode.episode.season }}/episodes/{{ episode.episode.number }}" title="{{ episode.episode.title | escape}} {{ episode.show.title | escape }}"> + <div class="relative block" style="max-width:226px"> + <div class="absolute left-0 top-0 h-full w-full rounded-lg border border-purple-600 hover:border-purple-500 bg-cover-gradient dark:border-purple-400 dark:hover:border-purple-500"></div> + <div class="absolute left-1 bottom-2 drop-shadow-md"> + <div class="px-1 text-xs font-bold text-white">{{ episode.episode.title }}</div> + <div class="px-1 text-xs text-white"> + {{ episode.show.title }} • <strong>S</strong>{{ episode.episode.season }}<strong>E</strong>{{ episode.episode.number }} + </div> + </div> + {%- capture tvImg %}{{episode.show.title | tv}}{% endcapture -%} + {%- capture tvName %}{{ episode.episode.title | escape}} {{ episode.show.title | escape }}{% endcapture -%} + {% image tvImg, tvName, 'rounded-lg w-full', '180px' %} + </div> + </a> + {% endfor %} + </div> +{% endif %} +<p class="text-xs text-center pt-6">This is a + <a href="https://nownownow.com/about">now page</a>, and if you have your own site, + <a href="https://nownownow.com/about">you should make one too</a>.</p>