Skip to content

Instantly share code, notes, and snippets.

@fallaciousreasoning
Created December 23, 2021 10:51
Show Gist options
  • Save fallaciousreasoning/7b67c929ac36f37f3b17bd5d66c1f90a to your computer and use it in GitHub Desktop.
Save fallaciousreasoning/7b67c929ac36f37f3b17bd5d66c1f90a to your computer and use it in GitHub Desktop.
A script which adds a button to Goodreads for setting the Read date to the shevled date.
// ==UserScript==
// @name Goodreads Set ReadDate
// @namespace Violentmonkey Scripts
// @match https://www.goodreads.com/review/list/*
// @grant none
// @version 1.0
// @author -
// @description 20/12/2021, 12:05:54 pm
// ==/UserScript==
const shelfName = 'read';
const reviewIdRegex = /reviewEditor.summon\(this, (\d+),.*reading_session_id: "(.*?)"/
const csrfToken = document.querySelector('#reviewEditForm input[name="authenticity_token"]').value;
const setReadDate = async (reviewId, sessionId, date) => {
const response = await fetch(`https://www.goodreads.com/review/update/${reviewId}`, {
method: 'POST',
credentals: 'include',
headers: {
'X-CSRF-Token': csrfToken
},
body: new URLSearchParams({
'_reading_session_id':sessionId,
'review[read_at(1i)]':date.getFullYear(),
'review[read_at(2i)]':date.getMonth() +1,
'review[read_at(3i)]': date.getDate(),
'view':'table',
'shelf':'read',
'format':'json'
})
});
}
const getReviewId = (dateReadColumn) => {
const editLink = dateReadColumn.querySelector('a.floatingBoxLink.smallText');
const editClick = editLink.getAttribute('onclick');
const match = reviewIdRegex.exec(editClick);
if (!match) {
console.log(`Failed to extract reviewId from ${editClick}`);
return;
}
return {
reviewId: match[1],
sessionId: match[2],
};
}
const updateDateText = (dateReadEl, date) => {
const greyText =dateReadEl.querySelector('.greyText');
greyText?.remove();
let dateText = dateReadEl.querySelector('.date_read_value');
if (!dateText) {
dateText = document.createElement('span');
dateText.setAttribute('class', 'date_read_value');
dateReadEl.prepend(dateText);
}
dateText.innerText = date.toLocaleString('en-us',{month:'short', day: 'numeric', year:'numeric'});
}
const makeLinkButton = (dateReadEl, { reviewId, sessionId }, date) => {
const link = document.createElement('a');
link.href = '#';
link.setAttribute('class', 'floatingBoxLink smallText');
link.innerText = `[use shelved]`;
link.addEventListener('click', async e => {
e.preventDefault();
console.log(`Setting read date for ${reviewId} to ${date}`);
await setReadDate(reviewId, sessionId, date);
console.log('Done!');
updateDateText(dateReadEl, date);
});
return link;
}
setTimeout(() => {
const books = document.querySelectorAll('.bookalike.review');
for (const book of books) {
const dateRead = book.querySelector('.field.date_read .editable_date');
const reviewId = getReviewId(dateRead);
if (!reviewId) continue;
const dateAdded = book.querySelector('.field.date_added')?.innerText;
if (!dateAdded) continue;
const date = new Date(dateAdded);
const setDateButton = makeLinkButton(dateRead, reviewId, date);
dateRead.appendChild(setDateButton);
}
}, 1000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment