Skip to content

Instantly share code, notes, and snippets.

@maxpatiiuk
Last active April 23, 2023 14:31
Show Gist options
  • Save maxpatiiuk/809c59bc2b40d53e3e07910088fb536b to your computer and use it in GitHub Desktop.
Save maxpatiiuk/809c59bc2b40d53e3e07910088fb536b to your computer and use it in GitHub Desktop.
Export Goodreads reading stats for plotting by Google Sheets
/*
* This script is now deprecated as it integrated into my Google Chrome extension:
* https://chrome.google.com/webstore/detail/goodreads-stats/hdpkeldenopncgodhpjdlpngmnaijpjf?hl=en&authuser=0
*
* The extension adds easy export functionality to Goodreads, along with plotting capabilities
*/
/*
* Open this page:
* https://www.goodreads.com/review/list/83169518?ref=nav_mybooks
* (replace id with your user id)
* Turn on infinite scroll
* Scroll all the way down to load all entries
* Open Chrome DevTools
* Run the following script:
*/
const monthFormatter = new Intl.DateTimeFormat(undefined, { month: 'long' });
const months = Array.from({ length: 12 }, (_, month) =>
monthFormatter.format(new Date(0, month, 2, 0, 0, 0))
);
Object.entries(
document.body.getElementsBySelector('#booksBody .date_read .date_row span')
.map(d=>d.textContent)
.reduce((dates, date) => {
if (!date.includes(',')) {
const dateParts = date.split(' ');
date = `${dateParts[0]} 1, ${dateParts[1]}`;
}
let [monthDay, year] = date.split(',');
year = year.trim();
if (year === 'set') return dates;
let [month, day] = monthDay.split(' ');
if (day[0] === '0') day = day.slice(1);
dates[year] ??= Object.fromEntries(
months.map((month) => [
month,
Object.fromEntries(
Array.from({
length: new Date(year, months.indexOf(month), 0).getDate() - 1,
}).map((_, day) => [day + 1, 0])
),
])
);
dates[year][month] ??= {};
dates[year][month][day] ??= 0;
dates[year][month][day] += 1;
return dates;
}, {})
)
.map(([year, yearData]) =>
Object.entries(yearData).reduce(
([yearTotal, entries], [month, monthData]) => {
const [monthTotal, monthEntries] = Object.entries(monthData).reduce(
([total, entries], [day, count]) => [
total + count,
[
...entries,
[`${year} ${month} ${day}`, yearTotal + total + count],
],
],
[0, []]
);
return [yearTotal + monthTotal, [...entries, ...monthEntries]];
},
[0, []]
)
)
.flat(2)
.filter(Array.isArray)
.map((row) => row.join('\t'))
.join('\n');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment