// ==UserScript== // @name Show Pitchfork Ratings for Albums // @version 2.0.0 // @namespace https://github.com/csavio/pitchfork-ratings/ // @include https://www.pitchforkmedia.com/* // @include https://pitchforkmedia.com/* // @include https://www.pitchfork.com/* // @include https://pitchfork.com/* // @description Display the album ratings at the top level color-coded so you can decide which reviews you want to read without clicking // @downloadURL none // ==/UserScript== const debugmode = false; const styles = ` `; const spotifySvg = ` `; const loccheck = setInterval(checkLoc, 300); let firstrun = true; let initloc = window.location.href; const ratingChecked = []; if (debugmode === true) { debugger; } async function getLinks(mylinks, counter) { mylinks = mylinks || ''; counter = counter || 0; const tempLink = mylinks.replace(/https:\/\/pitchfork\.com/, ''); if (document.querySelectorAll(`a[href="${tempLink}] span.rating`).length === 0) { // Pure JavaScript using fetch try { const response = await fetch(mylinks); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const html = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const element = doc.querySelector('p[class*="Rating-"]'); if (element) { let rating = element.textContent; rating = parseFloat(rating); let spanclass = ''; if (rating > 5.0 && rating <= 6.9) { spanclass = 'orange'; } else if (rating > 6.9) { spanclass = 'green'; } else { spanclass = 'red'; } const album = encodeURIComponent(doc.querySelector(`h1[data-testid="ContentHeaderHed"]`).textContent); const artist = encodeURIComponent(doc.querySelector(`a[href^="/artists"]`).textContent) document.querySelector(`a[href="${tempLink}"]`).insertAdjacentHTML( 'beforeend', `${(Number.isInteger(rating)) ? rating + '.0' : rating} ${spotifySvg}` ); } else { return null; } } catch (error) { console.error("Error fetching or parsing HTML:", error); return null; } } } function checkLoc() { var loc = window.location.href; // Only do something if the location has changed and it is an album review listing if ((firstrun || loc != initloc) && window.location.href.match(/(\/reviews\/)|(\/best\/)/)) { document.querySelector('head').insertAdjacentHTML('beforeend', styles); firstrun = false; setTimeout(function () { document.querySelectorAll("a[href^='/reviews/albums/']").forEach(async (node) => { const myhref = node.href; // There are two links so make sure the rating is added only once if (node.href.match(/reviews\/albums\/[\w\d.]+/) && !ratingChecked.includes(myhref)) { ratingChecked.push(myhref); await getLinks(myhref); } }); }, 2000); } initloc = window.location.href; }