Hides book reviews under a certain amount of stars
// ==UserScript==
// @name Goodreads - No Negative Reviews
// @version 2.0.0
// @author petracoding
// @namespace petracoding
// @grant none
// @license MIT
// @include https://www.goodreads.com/*
// @include http://www.goodreads.com/*
// @include https://goodreads.com/*
// @include http://goodreads.com/*
// @description Hides book reviews under a certain amount of stars
// ==/UserScript==
// SETTINGS:
/* *** Hiding Bad Reviews *** */
// How many stars (at least) should a review have for it to be SHOWN? (Default: 3)
const minRatingToShow = 3;
// Hide bad reviews of unread books?
const hideReviewsOfUnreadBooks = true; // true or false
// Hide your friends' reviews too?
const hideReviewsOfFriends = true; // true or false
// Hide reviews without a star rating?
const hideReviewsWithoutStarRating = false; // true or false
/* *** Hiding Good Reviews *** */
// Hide positive reviews of books you dislike?
const hideGoodReviewsOfBooksIDislike = false; // true or false
// How many stars (at most) do you give books you dislike?
const maxRatingOfBooksIDislike = 2;
/* *** Misc. Options: *** */
// Hide the "Community Reviews" overview?
const hideReviewOverview = false; // true or false
// Hide images in reviews?
const hideImagesInReviews = false; // true or false
// DO NOT CHANGE ANYTHING BELOW HERE.
const wrapper = document.querySelector(".ReviewsList");
let hideGoodReviewsInstead = false;
if (wrapper) {
const isBookRead = checkIfBookIsRead();
if (!hideReviewsOfUnreadBooks && !isBookRead) return;
const isDisliked = checkIfBookIsDisliked();
if (hideGoodReviewsOfBooksIDislike && isDisliked) {
hideGoodReviewsInstead = true;
}
addCSS();
searchForReviews();
if (hideReviewOverview) {
doHideReviewOverview();
}
setTimeout(() => {
searchForReviews();
document.addEventListener("scroll", searchForReviews);
}, 1000);
}
function addCSS() {
var styleSheet = document.createElement("style");
styleSheet.setAttribute("type", "text/css");
document.head.appendChild(styleSheet);
styleSheet.innerText = `.no-negative-reviews-hidden { height: 0 !important; overflow: hidden; }` + (hideImagesInReviews ? `.ReviewText__content .gr-hostedUserImg { display: none !important; }` : ``);
}
// Functionality:
function searchForReviews() {
const reviewElements = document.querySelectorAll(".ReviewCard:not(.no-negative-reviews-done)");
if (reviewElements.length > 0) {
hideReviews(reviewElements);
}
if (hideReviewsOfFriends) {
doHideReviewsOfFriends();
}
}
function hideReviews(reviewEls) {
[...reviewEls].forEach((reviewEl) => {
if (shouldReviewBeHidden(reviewEl)) {
reviewEl.classList.add("no-negative-reviews-hidden");
}
reviewEl.classList.add("no-negative-reviews-done");
});
reviewCount = 0;
searchForReviews();
}
function doHideReviewOverview() {
const overviewEl = document.querySelector(".ReviewsSectionStatistics");
if (overviewEl) {
overviewEl.style.display = "none";
}
}
function doHideReviewsOfFriends() {
const friendReviews = document.querySelectorAll(".ShelvingSocialSignalCard");
[...friendReviews].forEach(reviewEl => {
if (shouldReviewBeHidden(reviewEl)) {
reviewEl.style.display = "none";
}
});
}
// Helpers:
function shouldReviewBeHidden(reviewEl) {
if (!reviewEl) return false;
// do not hide liked reviews
const isLiked = reviewEl.querySelector(".SocialFooter__action .Button--active");
if (isLiked) return false;
// (don't) hide reviews form friends
if (!hideReviewsOfFriends) {
const isByFriend = reviewEl.querySelector('.FollowButton [aria-label*="Friends"]');
if (isByFriend) return false;
}
// (don't) hide reviews without star rating
const ratingWrapper = reviewEl.querySelector(".RatingStars");
if (!ratingWrapper) {
return hideReviewsWithoutStarRating;
}
const rating = ratingWrapper.querySelectorAll(".RatingStar__fill:first-child").length;
if (hideGoodReviewsInstead) {
if (rating > maxRatingOfBooksIDislike) {
return true;
} else {
return false;
}
} else {
if (rating < minRatingToShow) {
return true;
} else {
return false;
}
}
}
function checkIfBookIsRead() {
const el1 = document.querySelector(".BookActions");
if (!el1) return false;
const el2 = el1.querySelector(".BookActions__button:first-child");
if (!el2) return false;
const el3 = el2.querySelector(".Button");
if (!el3) return false;
const label = el3.getAttribute("aria-label").replace("Shelved as '", "").replace("'. Tap to edit shelf for this book", "").toLowerCase();
if (label == 'read' || label == 'currently reading') {
return true;
}
return false;
}
function checkIfBookIsDisliked() {
const el1 = document.querySelector(".BookActions");
if (!el1) return false;
const ratingWrapper = el1.querySelector(".BookRatingStars");
if (!ratingWrapper) return false;
const rating = ratingWrapper.querySelectorAll(".RatingStar__fill--selectable:first-child").length;
if (rating == 0) {
return false;
}
if (rating <= maxRatingOfBooksIDislike) {
return true;
}
return false;
}