Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save zonca/e91085c6fcc74bc98f6acbe8074fe8b9 to your computer and use it in GitHub Desktop.

Select an option

Save zonca/e91085c6fcc74bc98f6acbe8074fe8b9 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Audible filter (>=4.0, >=500, skip "Not rated yet")
// @namespace https://audible.com/
// @version 2.4
// @description Hide entire Audible book rows failing thresholds
// @match https://www.audible.com/*
// @run-at document-end
// @grant none
// ==/UserScript==
(function () {
"use strict";
const MIN_RATING = 4.0;
const MIN_REVIEWS = 500;
const BOOK_SELECTOR = 'li.productListItem[id^="product-list-item-"], li.bc-list-item.productListItem';
function getBook(el) {
return el.closest(BOOK_SELECTOR);
}
function parseRating(text) {
const m = text.match(/(\d(?:\.\d)?)\s*out of 5 stars/i);
return m ? parseFloat(m[1]) : null;
}
function parseReviews(text) {
const m = text.match(/([\d,]+)\s+ratings?/i);
return m ? parseInt(m[1].replace(/,/g, ""), 10) : null;
}
function shouldHide(rating, reviews, rawText) {
if (/not rated yet/i.test(rawText)) return true;
if (rating !== null && rating < MIN_RATING) return true;
if (reviews !== null && reviews < MIN_REVIEWS) return true;
return false;
}
function filterBooks(root) {
const rows = root.querySelectorAll(BOOK_SELECTOR);
rows.forEach((row) => {
const text = row.innerText;
const rating = parseRating(text);
const reviews = parseReviews(text);
if (shouldHide(rating, reviews, text)) {
row.style.display = "none";
}
});
}
function badge() {
if (document.getElementById("audible-filter-badge")) return;
const b = document.createElement("div");
b.id = "audible-filter-badge";
b.textContent = "Audible filter ≥4.0★, ≥500 ratings, no 'Not rated yet'";
Object.assign(b.style, {
position: "fixed",
top: "6px",
right: "6px",
background: "#000",
color: "#fff",
padding: "4px 6px",
fontSize: "11px",
zIndex: 999999,
});
document.body.appendChild(b);
}
badge();
filterBooks(document);
const obs = new MutationObserver((m) =>
m.forEach((x) =>
x.addedNodes.forEach((n) => n.nodeType === 1 && filterBooks(n))
)
);
obs.observe(document.body, { childList: true, subtree: true });
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment