chore: feed updates

This commit is contained in:
Cory Dransfeldt 2023-09-19 13:15:27 -07:00
parent 797aa959a9
commit d53d0f9505
No known key found for this signature in database
13 changed files with 666 additions and 70 deletions

View file

@ -179,7 +179,7 @@ module.exports = function (eleventyConfig) {
}) })
eleventyConfig.on('eleventy.after', () => { eleventyConfig.on('eleventy.after', () => {
execSync(`npx pagefind --source _site --glob "**/*.html"`, { encoding: 'utf-8' }) execSync(`npx pagefind --site _site --glob "**/*.html"`, { encoding: 'utf-8' })
}) })
return { return {

View file

@ -56,7 +56,7 @@
"markdownlint-cli": "^0.36.0", "markdownlint-cli": "^0.36.0",
"marked": "^9.0.3", "marked": "^9.0.3",
"pagefind": "^1.0.3", "pagefind": "^1.0.3",
"postcss": "^8.4.29", "postcss": "^8.4.30",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.5.4", "prettier-plugin-tailwindcss": "^0.5.4",
"rss-parser": "^3.13.0", "rss-parser": "^3.13.0",

View file

@ -8,15 +8,19 @@ module.exports = async function () {
const entries = feed.getEntries().catch() const entries = feed.getEntries().catch()
const res = await entries const res = await entries
const activity = { posts: [] } const activity = { posts: [] }
res.forEach((entry) => res.forEach((entry) => {
let excerpt = ''
if (entry.content) excerpt = entry.content
if (entry.data?.post_excerpt) excerpt = entry.data.post_excerpt
activity.posts.push({ activity.posts.push({
id: entry.url, id: entry.url,
title: entry.title, title: entry.title,
url: entry.url, url: entry.url,
description: entry.content || '', description: excerpt,
content_html: entry.content || '', content_html: excerpt,
date_published: entry.published, date_published: entry.published,
}) })
) })
return activity return activity
} }

View file

@ -1,33 +1,24 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom"> <rss version="2.0">
{% assign entries = data | normalizeEntries %} <channel>
<title>{{ title }}</title> {% assign entries = data | normalizeEntries -%}
<link href="{{ permalink | absoluteUrl: site.url }}" rel="self" /> <title>{{ title }}</title>
<link href="{{ site.url }}/" /> <description>{{ description }}</description>
<link rel="hub" href="https://pubsubhubbub.superfeedr.com/" /> <link>{{ permalink | absoluteUrl: site.url }}</link>
<updated>{{ updated | stringToDate | dateToRfc822 }}</updated> <image>
<id>{{ site.url }}/</id> <title>{{ title }}</title>
<author> <link>{{ permalink | absoluteUrl: site.url }}</link>
<name>{{ site.name }}</name> <url>{{ site.url }}/assets/icons/feed-icon.png</url>
<email>{{ site.email }}</email> <width>144</width>
</author> <height>144</height>
<image> </image>
<url>https://coryd.dev/assets/icons/apple-touch-icon.png</url> {% for entry in entries limit: 20 -%}
<title>Cory Dransfeldt</title> <item>
<link>https://coryd.dev/</link> <title>{{ entry.title | escape }}</title>
<width>512</width> <link>{{ entry.url | stripUtm | encodeAmp }}</link>
<height>512</height> <guid>{{ entry.url | stripUtm | encodeAmp }}</guid>
</image> <description>{{ entry.excerpt | markdown | escape }}</description>
<generator uri="https://11ty.dev" version="{{ eleventy.version }}">{{ eleventy.generator }}</generator> </item>
{% for entry in entries limit: 20 -%} {%- endfor %}
<entry> </channel>
<title>{{ entry.title | escape }}</title> </rss>
<link href="{{ entry.url | stripUtm | encodeAmp }}" />
<updated>{{ entry.date | date: "%m.%d.%Y" }}</updated>
<id>{{ entry.url | stripUtm | encodeAmp }}</id>
<content type="html">
{{ entry.excerpt | markdown | escape }}
</content>
</entry>
{%- endfor %}
</feed>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View file

@ -1,3 +1,602 @@
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
* {
box-sizing: border-box;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.cf:before,
.cf:after {
content: "";
display: table;
}
.cf:after {
clear: both;
}
a:link,
a:visited,
a:active {
color: #9333ea;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
body {
margin: 0 auto;
padding: 0;
font-size: 13px;
color: #374151;
}
body, html { body, html {
font-family: Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji font-family: Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji
} }
p {
margin-bottom: 1em;
}
div#main {
margin: 0 auto;
padding: 0;
}
div#header {
padding: 20px;
margin: 0 auto 16px;
}
div#header:before,
div#header:after {
content: "";
display: table;
}
div#header:after {
clear: both;
}
div#header h1 {
font-size: 32px;
line-height: 101%;
letter-spacing: -0.5px;
text-align: center;
padding-bottom: 10px;
}
div#header h1 a {
color: #fff;
font-weight: 700;
}
div#header h2 {
font-size: 15px;
color: #fff;
text-align: center;
}
div#header p.about {
color: #fff;
text-align: center;
font-size: 14px;
margin: 10px 0 3px;
line-height: 1.3;
}
div#header p#logo {
text-align: center;
margin: 30px 0;
}
div#header p#logo img#feedimage {
max-width: 250px;
max-height: 250px;
border-radius: 10px;
border: 1px solid #e5e7eb;
box-shadow: rgba(0, 0, 0, 0.5) 0 2px 10px 0;
}
div#header figure#background {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100vw;
min-width: 100vw;
z-index: -1;
margin: 0;
overflow: hidden;
}
div#header figure#background img {
position: absolute;
width: 100%;
min-width: 100%;
top: 50%;
left: 0;
transform: translateY(-50%) scale(2);
filter: blur(20px);
}
div#header figure#background::before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
background: rgba(0, 0, 0, 0.55);
}
div#feedpress {
position: absolute;
top: 5px;
left: 5px;
}
div#feedpress a {
background: url(https://static.feedpress.com/images/feedpress-white@2x.png);
background-size: 124px 25px;
width: 32px;
height: 25px;
display: inline-block;
}
div#feedpress a:hover {
width: 124px;
}
div#subscribe {
padding: 30px 20px 30px;
width: 90%;
margin: 0 auto;
text-align: center;
}
div#subscribe div.subbutton {
background: #fff;
border: 1px solid #e5e7eb;
box-shadow: rgba(0, 0, 0, 0.1) 0 2px 10px 0;
display: inline-block;
border-radius: 5px;
cursor: pointer;
transition-property: box-shadow;
transition-duration: 200ms;
margin: 5px 5px;
}
div#subscribe div.subbutton svg {
float: left;
margin: 5px 5px 5px 10px;
}
div#subscribe div.subbutton span {
display: inline-block;
margin: 7px 10px 0 0;
}
div#subscribe div.subbutton:hover {
box-shadow: rgba(0, 0, 0, 0.5) 0 2px 10px 0;
}
div#subscribe h3 {
padding-left: 0;
font-size: 18px;
}
div#subscribe h4 {
font-weight: 400;
margin: 14px 0 6px 0;
}
div#subscribe div#feedinput {
text-align: center;
}
div#subscribe div#feedinput input[type="text"] {
padding: 6px;
border: 1px solid #e5e7eb;
font-size: 16px;
width: 500px;
color: #333;
outline: 0;
}
div#subscribe div#feedinput input[type="button"] {
padding: 6px;
border: 1px solid #0f766e;
background: #0f766e;
font-size: 16px;
width: 180px;
margin: 0 0 0 4px;
color: #fff;
outline: 0;
font-weight: 700;
}
div#subscribe div#feedinput div#subpopin {
display: none;
z-index: 1000;
position: fixed;
background: #fff;
border: 1px solid #e5e7eb;
box-shadow: rgba(0, 0, 0, 0.5) 0 2px 10px 0;
width: 300px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 5px;
padding-top: 45px;
padding-bottom: 15px;
}
div#subscribe div#feedinput div#subpopin span {
position: absolute;
top: 10px;
right: 15px;
font-size: 20px;
cursor: pointer;
}
div#subscribe div#feedinput div#subpopin h3 {
position: absolute;
top: 10px;
left: 15px;
text-transform: uppercase;
font-size: 10px;
}
div#subscribe div#feedinput div#subpopin div.subprovider a {
text-decoration: none;
color: #374151;
display: inline-block;
padding: 10px 10px 10px 15px;
width: 100%;
transition-property: background-color;
transition-duration: 200ms;
}
div#subscribe div#feedinput div#subpopin div.subprovider a svg,
div#subscribe div#feedinput div#subpopin div.subprovider a img {
padding: 0;
width: 24px;
height: 24px;
float: left;
}
div#subscribe div#feedinput div#subpopin div.subprovider a span {
position: relative;
float: left;
margin: 5px 5px 5px 10px;
top: 0;
left: 0;
font-size: 16px;
}
div#subscribe div#feedinput div#subpopin div.subprovider a:hover {
background-color: #f5f5f5;
}
div#subscribe div#readerslinks {
text-align: center;
}
div#subscribe div#xmllink {
text-align: center;
}
div#subscribe div#newsletterlink {
text-align: center;
}
div#subscribe div img {
padding-left: 3px;
padding-right: 3px;
padding-bottom: 3px;
}
div#subscribe p {
margin-top: 12px;
line-height: 150%;
}
div#subscribe div#subpopin {
z-index: 1000;
position: fixed;
background: #fff;
border: 1px solid #e5e7eb;
box-shadow: rgba(0, 0, 0, 0.5) 0 2px 10px 0;
width: 300px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 5px;
padding-top: 45px;
padding-bottom: 15px;
}
div#subscribe div#subpopin span {
position: absolute;
top: 10px;
right: 15px;
font-size: 20px;
cursor: pointer;
}
div#subscribe div#subpopin h3 {
position: absolute;
top: 15px;
left: 15px;
text-transform: uppercase;
font-size: 10px;
}
div#subscribe div#subpopin div.subprovider a {
text-decoration: none;
color: #374151;
display: inline-block;
padding: 10px 10px 10px 15px;
width: 100%;
transition-property: background-color;
transition-duration: 200ms;
}
div#subscribe div#subpopin div.subprovider a svg {
width: 24px;
height: 24px;
float: left;
}
div#subscribe div#subpopin div.subprovider a span {
position: relative;
float: left;
margin: 5px 5px 5px 10px;
top: 0;
left: 0;
font-size: 16px;
}
div#subscribe div#subpopin div.subprovider a:hover {
background-color: #f5f5f5;
}
ul#items {
background: #e5e7eb url(https://static.feedpress.com/images/background.png);
background-size: 568px 468px;
padding: 20px 0;
}
ul#items li.regularitem {
padding: 20px 20px 5px;
margin: 20px auto;
width: 50%;
background: #fff;
border-radius: 5px;
border: 1px solid #e5e7eb;
box-shadow: rgba(0, 0, 0, 0.2) 0 2px 10px 0;
}
ul#items li.regularitem h4.itemtitle {
font-size: 18px;
letter-spacing: -0.25px;
padding-bottom: 4px;
margin-bottom: 6px;
}
ul#items li.regularitem h5.itemposttime {
font-size: 12px;
font-weight: 400;
color: #374151;
margin-top: 3px;
margin-bottom: 20px;
}
ul#items li.regularitem h5.itemposttime span {
color: #374151;
}
ul#items li.regularitem div.itemcontent {
font-size: 14px;
line-height: 130% !important;
overflow: hidden;
width: 99%;
}
ul#items li.regularitem div.itemcontent h1 {
font-weight: 700;
font-size: 20px;
margin: 0 0 16px 0;
}
ul#items li.regularitem div.itemcontent h2 {
font-weight: 700;
font-size: 18px;
margin: 0 0 16px 0;
}
ul#items li.regularitem div.itemcontent h3 {
font-weight: 700;
font-size: 16px;
margin: 0 0 16px 0;
}
ul#items li.regularitem div.itemcontent h4 {
font-weight: 700;
font-size: 14px;
margin: 0 0 16px 0;
}
ul#items li.regularitem div.itemcontent ul {
list-style: square;
padding-left: 1em;
margin-bottom: 1em;
}
ul#items li.regularitem div.itemcontent li {
margin-left: 2.4em;
margin-bottom: 0.5em;
}
ul#items li.regularitem div.itemcontent ol {
list-style-type: decimal;
margin-bottom: 1em;
}
ul#items li.regularitem div.itemcontent img[align="right"] {
padding-left: 12px;
padding-bottom: 12px;
}
ul#items li.regularitem div.itemcontent img[align="left"] {
padding-right: 12px;
padding-bottom: 12px;
}
ul#items li.regularitem div.itemcontent iframe {
display: block !important;
margin: 0 auto 25px !important;
text-align: center;
}
ul#items li.regularitem div.itemcontent pre {
border: 0 !important;
font-size: 13px;
margin: 0 25px 25px;
font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
ul#items li.regularitem div.itemcontent img {
max-width: 100%;
height: auto;
}
ul#items li.regularitem div.itemcontent blockquote {
margin: 25px;
}
ul#items li.regularitem div.itemcontent strong {
font-weight: 700;
}
ul#items li.regularitem div.player img {
max-width: 100%;
}
ul#items li.regularitem img.mediacontent {
float: left;
max-height: 140px;
margin-right: 15px;
}
ul#items li.regularitem p.mediasubtitle {
line-height: 150%;
color: #374151;
font-style: italic;
}
ul#items li.regularitem p.mediaenclosure {
text-transform: uppercase;
font-weight: 700;
margin: 10px 0 10px 0;
word-wrap: break-word;
}
ul#items li.regularitem p.mediaenclosure a {
text-transform: none;
}
ul#items li.regularitem audio {
width: 100%;
margin: 10px auto 20px;
}
#footer {
padding: 20px 20px 5px;
background: rgba(255, 255, 255, 0.75);
}
#footer p {
line-height: 140%;
}
#footer img {
float: right;
margin: 5px 0 0 10px;
}
@media screen and (max-width: 980px) {
div#main {
width: auto;
}
div#subscribe div#feedinput input[type="text"] {
max-width: 100%;
}
ul#items li.regularitem {
margin-bottom: 0;
border: 0;
width: 85%;
}
#footer p {
text-align: center;
}
#footer img {
float: none;
display: block;
margin: 0 auto 15px;
}
}

View file

@ -3,10 +3,10 @@ layout: null
permalink: /feeds/books permalink: /feeds/books
--- ---
{% render "partials/feeds/content.liquid" {% render "partials/feeds/content.liquid"
permalink:'/feeds/books' permalink:"/feeds/books"
title:'Books • Cory Dransfeldt' title:"Books • Cory Dransfeldt"
description:"Books I'm currently reading."
data:books data:books
updated:books[0].dateAdded updated:books[0].dateAdded
site:site site:site
eleventy:eleventy
%} %}

View file

@ -4,10 +4,10 @@ permalink: /feeds/posts
--- ---
{%- assign posts = collections.posts | reverse -%} {%- assign posts = collections.posts | reverse -%}
{% render "partials/feeds/content.liquid" {% render "partials/feeds/content.liquid"
permalink:'/feeds/posts' permalink:"/feeds/posts"
title:'Cory Dransfeldt' title:"Cory Dransfeldt"
description:"Posts from my site."
data:posts data:posts
updated:posts[0].date updated:posts[0].date
site:site site:site
eleventy:eleventy
%} %}

View file

@ -3,10 +3,10 @@ layout: null
permalink: /feeds/follow permalink: /feeds/follow
--- ---
{% render "partials/feeds/content.liquid" {% render "partials/feeds/content.liquid"
permalink:'/feeds/follow' permalink:"/feeds/follow"
title:'Follow • Cory Dransfeldt' title:"Follow • Cory Dransfeldt"
description:"My activity from around the web."
data:follow.posts data:follow.posts
updated:follow.posts[0].date_published updated:follow.posts[0].date_published
site:site site:site
eleventy:eleventy
%} %}

View file

@ -3,10 +3,10 @@ layout: null
permalink: /feeds/links permalink: /feeds/links
--- ---
{% render "partials/feeds/content.liquid" {% render "partials/feeds/content.liquid"
permalink:'/feeds/links' permalink:"/feeds/links"
title:'Links • Cory Dransfeldt' title:"Links • Cory Dransfeldt"
description:"Links I've shared."
data:collections.links data:collections.links
updated:collections.links[0].date updated:collections.links[0].date
site:site site:site
eleventy:eleventy
%} %}

View file

@ -5,7 +5,7 @@ draft: false
tags: ['Matter', 'development', 'Eleventy', 'API'] tags: ['Matter', 'development', 'Eleventy', 'API']
--- ---
I dropped in a quick update to [my now page](/now) to display the 5 most recent articles from my favorites feed in [Matter](https://getmatter.com/).<!-- excerpt --> I dropped in a quick update to [my now page](https://coryd.dev/now) to display the 5 most recent articles from my favorites feed in [Matter](https://getmatter.com/).<!-- excerpt -->
To do this I'm borrowing from [Federico Viticci's method of obtaining a key for their api](https://www.macstories.net/stories/macstories-starter-pack-reverse-engineering-the-matter-api-and-my-save-to-matter-shortcut/) and using it to make a `GET` request to their `favorites_feed` endpoint: To do this I'm borrowing from [Federico Viticci's method of obtaining a key for their api](https://www.macstories.net/stories/macstories-starter-pack-reverse-engineering-the-matter-api-and-my-save-to-matter-shortcut/) and using it to make a `GET` request to their `favorites_feed` endpoint:

View file

@ -5,27 +5,29 @@ draft: false
tags: ['development', 'music', 'Eleventy', 'Apple', 'JavaScript', 'API'] tags: ['development', 'music', 'Eleventy', 'Apple', 'JavaScript', 'API']
image: https://cdn.coryd.dev/blog/charlie.jpg image: https://cdn.coryd.dev/blog/charlie.jpg
--- ---
I've written before about [displaying my listening data from Apple Music](/posts/2023/displaying-listening-data-from-apple-music-using-musickit/) but, recently, I've attempted to take things a bit further.<!-- excerpt --> I've written before about [displaying my listening data from Apple Music](https://coryd.dev/posts/2023/displaying-listening-data-from-apple-music-using-musickit/) but, recently, I've attempted to take things a bit further.<!-- excerpt -->
The Apple Music is API is cool because it gives you data about your music, its not cool because well, its missing some things. It sends back a whole host of handy-dandy track metadata that youd expect from a music service and thats great. But it doesnt provide data youd normally expect like, well, a time stamp of when the recently played track was recently played. The Apple Music is API is cool because it gives you data about your music, it's not cool because well, it's missing some things. It sends back a whole host of handy-dandy track metadata that you'd expect from a music service and that's great. But it doesn't provide data you'd normally expect like, well, a time stamp of when the recently played track was recently played.
I want an API that can act as a state of truth — what Ive got is an API that returns tracks in the play order, but with no concrete representation of when they were actually played. I want an API that can act as a state of truth — what I've got is an API that returns tracks in the play order, but with no concrete representation of when they were actually played.
Where does that leave us? Well, if were smart, that solution might look like what I ran with during my first go around. I call Apples API and iteratively page through it to aggregate a 200 track sample. Thats about 6-7 calls and a moving window. Where does that leave us? Well, if we're smart, that solution might look like what I ran with during my first go around. I call Apple's API and iteratively page through it to aggregate a 200 track sample. That's about 6-7 calls and a moving window.
What we can achieve though, dear listener, through some inferences and external storage is a cache and — wait for it — with a more slowly moving, less capricious window. What we can achieve though, dear listener, through some inferences and external storage is a cache and — wait for it — with a more slowly moving, less capricious window.
What weve got: What we've got:
- The current time - The current time
- A duration for each track - A duration for each track
What we can do: What we can do:
- Calculate how many tracks from Apples response approximate an hour of listening
- Calculate how many tracks from Apple's response approximate an hour of listening
- Infer time stamps by moving backwards iteratively through an hour of listening - Infer time stamps by moving backwards iteratively through an hour of listening
This isnt canonical, its not definitive, but its what weve got. This isn't canonical, it's not definitive, but it's what we've got.
So, were dealing with JSON and a static site generator. We want to persist our data as a cache, read it in and write out an update. For this Ive elected to use Wasabi, who offer a 1:1 compatible S3 API. The data structure we want to store for each track looks like this[^1]: So, we're dealing with JSON and a static site generator. We want to persist our data as a cache, read it in and write out an update. For this I've elected to use Wasabi, who offer a 1:1 compatible S3 API. The data structure we want to store for each track looks like this[^1]:
```json ```json
{ {
@ -42,7 +44,7 @@ So, were dealing with JSON and a static site generator. We want to persist ou
} }
``` ```
When I deploy a production build of my site[^2] well read in our cache from Wasabi, call Apples flawed[^3] but persistent API, align the two and suss out the difference: When I deploy a production build of my site[^2] we'll read in our cache from Wasabi, call Apple's flawed[^3] but persistent API, align the two and suss out the difference:
```javascript ```javascript
const _ = require('lodash') const _ = require('lodash')
@ -79,7 +81,7 @@ const diffTracks = (cache, tracks) => {
} }
``` ```
Still with me? Next — were going to derive some chart data, excluding anything not within a week prior to build time (this is where that slower moving window comes in). Still with me? Next — we're going to derive some chart data, excluding anything not within a week prior to build time (this is where that slower moving window comes in).
```javascript ```javascript
const deriveCharts = (tracks) => { const deriveCharts = (tracks) => {
@ -127,11 +129,11 @@ const deriveCharts = (tracks) => {
_Cool_[^4]. GitHub triggers a rebuild of the site every hour, Netlify builds it, Eleventy optimizes images that are stored at bunny.net, Apple provides the listening data, Wasabi provides persistence. _Cool_[^4]. GitHub triggers a rebuild of the site every hour, Netlify builds it, Eleventy optimizes images that are stored at bunny.net, Apple provides the listening data, Wasabi provides persistence.
There are some significant issues with this approach: it doesnt capture listens to an album in a loop (like me playing the new Outer Heaven record today — hails 🤘). It can get wonky when my diff function hits a track order that elicits a false positive return value. There are some significant issues with this approach: it doesn't capture listens to an album in a loop (like me playing the new Outer Heaven record today — hails 🤘). It can get wonky when my diff function hits a track order that elicits a false positive return value.
{% image 'https://cdn.coryd.dev/blog/charlie.jpg', 'Charlie Day standing in front of "charts"', 'w-full', '600px' %} {% image 'https://cdn.coryd.dev/blog/charlie.jpg', 'Charlie Day standing in front of "charts"', 'w-full', '600px' %}
"But Cory theres last.fm." I hear this, I love last.fm, but Ive got concerns about its age, ownership and maintenance. I dont want to be on the wrong end of a scream test when the wrong (right?) server rack gets decommissioned. "But Cory there's last.fm." I hear this, I love last.fm, but I've got concerns about its age, ownership and maintenance. I don't want to be on the wrong end of a scream test when the wrong (right?) server rack gets decommissioned.
So, would I recommend pursuing this? Probably not, pretty definitely, probably not. It's, I think, as close as it can be to being an accurate but imperfect representation of what I listen to regularly. With that imperfect accuracy in mind I've replaced play counts on [my now page](https://coryd.dev/now) where this is all displayed with the genres I've associated with each artist[^5]. I _like_ where this is at. I'd **love** it if Apple would take away my crazy wall and give me a timestamp though. So, would I recommend pursuing this? Probably not, pretty definitely, probably not. It's, I think, as close as it can be to being an accurate but imperfect representation of what I listen to regularly. With that imperfect accuracy in mind I've replaced play counts on [my now page](https://coryd.dev/now) where this is all displayed with the genres I've associated with each artist[^5]. I _like_ where this is at. I'd **love** it if Apple would take away my crazy wall and give me a timestamp though.

View file

@ -4408,10 +4408,10 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.3.11, postcss@^8.4.23, postcss@^8.4.29: postcss@^8.3.11, postcss@^8.4.23, postcss@^8.4.30:
version "8.4.29" version "8.4.30"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.29.tgz#33bc121cf3b3688d4ddef50be869b2a54185a1dd" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.30.tgz#0e0648d551a606ef2192a26da4cabafcc09c1aa7"
integrity sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw== integrity sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==
dependencies: dependencies:
nanoid "^3.3.6" nanoid "^3.3.6"
picocolors "^1.0.0" picocolors "^1.0.0"