Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dancek/ac8e1eb309a994623a464668228e4ab7 to your computer and use it in GitHub Desktop.
Save dancek/ac8e1eb309a994623a464668228e4ab7 to your computer and use it in GitHub Desktop.
Helmet search from Goodreads to-read shelf
<h1>Helmet search from Goodreads to-read shelf</h1>
<p>Goodreads user id: <input id="user" /> <button onclick="refresh()">Go!</button></p>
<p>(note: you need to set profile visible to 'anyone' in <a href="https://www.goodreads.com/user/edit?tab=settings" target="_blank">Goodreads settings</a>)</p>
<hr/>
<table id="books">
</table>
<pre id="debug"></pre>
function fetchGoodreadsShelf(id) {
const url = `https://webtask.it.auth0.com/api/run/wt-hannu-hartikainen-gmail-com-1/goodreads?id=${id}`;
return fetch(url)
.then(response => {
if (!response.ok) throw response;
return response.json()
});
}
function getBookFromReview(review) {
const book = review.book;
console.log(book.title, book); // for debugging
const out = {
isbn13: book.isbn13,
title: book.title,
author: book.authors.author.name, // TODO: multiple authors
rating: book.average_rating,
url: book.link
}
return out;
}
function printDebug(data) {
document.getElementById('debug').innerText = JSON.stringify(data, null, 2);
return data;
}
function createTd(text, href) {
const td = document.createElement('td');
const textNode = document.createTextNode(text);
var content;
if (href) {
content = document.createElement('a');
content.setAttribute('href', href);
content.setAttribute('target', '_blank');
content.appendChild(textNode);
} else {
content = textNode;
}
td.appendChild(content);
return td;
}
const SURNAME_RE = /(.*) ([^ ]*)/
function surnameFirst(author) {
const [_, firstname, surname] = author.match(SURNAME_RE);
return `${surname}, ${firstname}`;
}
// strip goodreads additions like series name and number
function strippedTitle(title) {
return title.replace(/ *\(.*, #.*\)/, '');
}
function authorSearchLink(book) {
return `http://luettelo.helmet.fi/search~S9*fin/?searchtype=a&searcharg=${surnameFirst(book.author)}`;
}
function titleSearchLink(book) {
return `http://luettelo.helmet.fi/search~S9*fin/?searchtype=t&searcharg=${strippedTitle(book.title)}`;
}
function createRowFromBook(book) {
const tr = document.createElement('tr');
tr.appendChild(createTd(book.rating, book.url))
tr.appendChild(createTd(book.author, authorSearchLink(book)));
tr.appendChild(createTd(book.title, titleSearchLink(book)));
return tr;
}
function insertRows(rows) {
const table = document.getElementById('books')
const docFrag = document.createDocumentFragment();
rows.map(row => docFrag.appendChild(row))
while(table.firstChild) {
table.removeChild(table.firstChild);
}
table.appendChild(docFrag);
}
function setMsg(msg) {
document.getElementById('books').innerHTML = `<tr><td>${msg}</td></tr>`;
}
function init() {
const id = localStorage.getItem('goodreadsUser') || '20719991';
document.getElementById('user').value = id;
}
function refresh() {
const id = document.getElementById('user').value;
localStorage.setItem('goodreadsUser', id)
setMsg(`Fetching Goodreads to-read shelf for user ${id}...`);
fetchGoodreadsShelf(id)
.catch(() => setMsg("Couldn't fetch data from Goodreads!"))
.then(json => json.reviews.review) // the structure: wtf
.then(reviews => reviews.map(getBookFromReview))
//.then(printDebug)
.then(books => books.map(createRowFromBook))
.then(insertRows)
// TODO: handle processing errors
}
// run automatically
init();
refresh();
/* // webtask code:
var Request = require('request');
var xml2js = require('xml2js@0.4.8');
var parser = new xml2js.Parser({
explicitRoot: false,
explicitArray: false
});
module.exports = function (ctx, done) {
var id = ctx.data.id || 20719991;
var options = {
url: `https://www.goodreads.com/review/list/${id}.xml?key=${ctx.secrets.GOODREADS_API_KEY}&v=2&shelf=to-read&per_page=200`,
time: true
};
console.log('Requesting', options.url);
Request.get(options, function (err, res, body) {
parser.parseString(body, function(err_, json) {
delete json.Request.key;
done(err_, json);
});
});
};
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment