Skip to content

Instantly share code, notes, and snippets.

@andre-st
Last active October 20, 2021 11:42
Show Gist options
  • Save andre-st/592825fe9a5b2eafc5a73feb80ade649 to your computer and use it in GitHub Desktop.
Save andre-st/592825fe9a5b2eafc5a73feb80ade649 to your computer and use it in GitHub Desktop.
Shows Goodreads.com ratings on Amazon.de product pages #injectjs
//////////////////////////////////////////////////////////////////////////////
//
// AMAZON.DE WITH GOODREADS.COM RATINGS
//
// Replaces Ruben Martinez's "Goodreads Ratings for Amazon" extension.
//
mixin( ["https://www.amazon.de/"], () =>
{
// There are often e-book editions on Goodreads when there are no paper editions.
// The e-book ASIN isn't similar to ISBN, as opposed to the paper book ASIN.
const detailDiv = document.getElementById( 'detailBullets_feature_div' );
const isbn10 = detailDiv && (detailDiv.innerText.match( /ISBN-10.*?([0-9X\-]+)/ ) || ['', ''])[1];
const isbn13 = detailDiv && (detailDiv.innerText.match( /ISBN-13.*?([0-9X\-]+)/ ) || ['', ''])[1];
const ebookUrl = document.querySelector( 'ol:not(.a-carousel) a[href*="ebook/dp/"]' );
const ebookAsin = ebookUrl && (ebookUrl.getAttribute( 'href' ).match( /dp\/([^\/]+)/ ) || ['', ''])[1];
const titleLongElm = document.getElementById( 'productTitle' ); // "Title: Subtitle (Publisher)" no GR search results
const title = titleLongElm ? titleLongElm.innerText.match( /^[^(:]+/ )[0] : ''; // "Title "
const altGoodUrl = 'https://www.goodreads.com/search?q=' + encodeURIComponent( title ) + '&search[field]=title';
// The Goodreads search engine doesn't support the logical operator 'or',
// and it doesn't try to get the ISBN-10 from ISBN-13 or vice versa.
// So we have to query ISBN-10, ISBN-13 and e-book ASIN individually.
const queryUrls = [];
if( isbn10 ) queryUrls.push( 'https://www.goodreads.com/book/isbn?isbn=' + isbn10 );
if( isbn13 ) queryUrls.push( 'https://www.goodreads.com/book/isbn?isbn=' + isbn13 );
if( ebookAsin ) queryUrls.push( 'https://www.goodreads.com/book/isbn?isbn=' + ebookAsin );
console.log( queryUrls );
if( queryUrls.length == 0 ) return; // Not a book or poorly catalogued
// Our area to display ratings:
// Our default text is the initial state and also the last state if our queries fail!
const amzLangElm = document.querySelector( '[data-language]' ); // May differ from the browser settings (for me)
const amzLang = amzLangElm && amzLangElm.getAttribute( 'data-language' ) || undefined; // "de-DE"
const amzDiv = document.getElementById( 'averageCustomerReviews_feature_div' );
const ourDiv = document.createElement( 'div' );
ourDiv.innerHTML = '<a href="' + altGoodUrl + '" style="color: #ec8c14; text-decoration: underline; font-weight: bold">Goodreads-Search</a>';
amzDiv.append( ourDiv, amzDiv.nextSibling );
// Concurrent Goodreads queries result in better response time for user:
var _bestNumRatings = -1; // GR book might exist but 0 ratings
queryUrls.forEach( u => getUrl( u, text =>
{
const url = (text.match( /meta content='([^']+)' property='og:url'/ ) || ['', '' ])[1];
const ratstr = (text.match( /itemprop="ratingValue">\s*([0-9.]+)/ ) || ['', '0'])[1];
const nratstr = (text.match( /itemprop="ratingCount" content="([0-9.]+)"/ ) || ['', '0'])[1];
const nrevstr = (text.match( /itemprop="reviewCount" content="([0-9.]+)"/ ) || ['', '0'])[1];
const r = parseFloat( ratstr ) || 0;
const nrat = parseInt ( nratstr ) || 0;
const nrev = parseInt ( nrevstr ) || 0;
const rint = r % 1 > 0.6 ? Math.ceil( r ) : Math.floor( r ); // frac via modulo
const rhalf = r % 1 >= 0.2 && r % 1 <= 0.6 ? '-5' : '';
const rhtm = '<i class="a-icon a-icon-star a-star-' + rint + rhalf + '"></i>';
if( !url || _bestNumRatings >= nrat ) return; // Only query-result with most ratings
_bestNumRatings = nrat;
// More or less language-neutral strings due to Locales, just Anglicisms:
ourDiv.innerHTML = rhtm + '<a style="margin-left: 37px" href="'
+ unxss( url ) + '">'
+ nrat.toLocaleString( amzLang ) + ' Goodreads-Ratings, '
+ nrev.toLocaleString( amzLang ) + ' Reviews</a>';
}));
}, { runAsContentScript: true });
@andre-st
Copy link
Author

andre-st commented Mar 15, 2021

Can be used with the Javascript injection extension https://github.com/andre-st/chrome-injectjs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment