Transform MAL into Rotten Tomatoes
Pada tanggal
// ==UserScript==
// @name Average Reviews Calculator for MAL
// @namespace Transform MAL into Rotten Tomatoes
// @version 0.3
// @description Transform MAL into Rotten Tomatoes
// @author Only_Brad
// @include /^https:\/\/myanimelist\.net\/(anime|manga)\/[\d]+\/.*\/reviews/
// @run-at document-end
// @grant GM_addStyle
// ==/UserScript==
(async function(){
const
REVIEWS_TAB_SELECTOR = "#content > table > tbody > tr > td:nth-child(2) > div.js-scrollfix-bottom-rel",
SCORE_TABLES_SELECTOR = "table.borderClass",
OVERALL_RATING_SELECTOR = "tbody > tr > td:nth-child(2) > strong",
SEPERATOR_SELECTOR = ".reviews-horiznav-nav-sort-block";
const
currentUrl = window.location.href,
firstPageUrl = getFirstPageUrl(),
currentPage = getCurrentPage(),
score = setPlaceholderScore();
showAverageOverallScore();
function setPlaceholderScore() {
const separator = document.querySelector(SEPERATOR_SELECTOR);
const score = document.createElement("div");
score.style = "padding: 15px 0 15px 10px;";
score.textContent = "Calculating total average review score...";
separator.insertAdjacentElement("afterend",score);
return score;
}
async function showAverageOverallScore() {
const overallScores = await getAllOverallScore();
const average = overallScores.reduce((acc,val)=>acc+val,0)/overallScores.length;
score.textContent = "Average score: "+average.toFixed(2);
}
async function getAllOverallScore() {
const NB_OF_SIMULTANOUS_DL = 5;
const overallScores = [];
let httpRequests = [];
let i = 1;
let loopCount = 1;
while (true) {
for (i; i <= NB_OF_SIMULTANOUS_DL * loopCount; i++) {
httpRequests.push(getDocument(i));
}
const documents = await Promise.all(httpRequests);
for (const currentDocument of documents) {
if (hasReviews(currentDocument))
overallScores.push(getOverallScores(currentDocument));
else
return overallScores.flat();
}
httpRequests = [];
loopCount++;
}
}
async function getDocument(pageNumber) {
let currentDocument;
if(pageNumber === currentPage) currentDocument = document;
else {
const url = pageNumber === 1 ? firstPageUrl : `${firstPageUrl}?p=${pageNumber}`;
const response = await fetch(url);
const html = await response.text();
currentDocument = new DOMParser().parseFromString(html,"text/html");
}
return currentDocument;
}
function getOverallScores(document) {
const reviewsTab = document.querySelector(REVIEWS_TAB_SELECTOR);
const scoreTables = reviewsTab.querySelectorAll(SCORE_TABLES_SELECTOR);
return [...scoreTables].map(table => parseInt(table.querySelector(OVERALL_RATING_SELECTOR).textContent));
}
function hasReviews(document) {
const reviewsTab = document.querySelector(REVIEWS_TAB_SELECTOR);
const scoreTables = reviewsTab.querySelectorAll(SCORE_TABLES_SELECTOR);
return scoreTables.length > 0;
}
function getFirstPageUrl() {
const PAGE_REGEX = /\?p=[\d]+/;
const search = currentUrl.search(PAGE_REGEX);
if(search !== -1) return currentUrl.substring(0,search);
return currentUrl;
}
function getCurrentPage() {
const PAGE_REGEX = /\?p=[\d]+/;
const match = currentUrl.match(PAGE_REGEX);
if(match) return parseInt(match[1]);
else return 1;
}
})()