Add VIB Rank, stars, VIB_score decimal, and rating count to anime list based on API data
当前为
// ==UserScript==
// @name VIBDataListInsertion
// @namespace https://jirehlov.com
// @version 0.1.3
// @description Add VIB Rank, stars, VIB_score decimal, and rating count to anime list based on API data
// @include /^https?://(bangumi\.tv|bgm\.tv|chii\.in)/(.+?/list|.+?/tag|.+?/browser|subject_search|index)(/|\?).+$/
// @author Jirehlov
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const processedElements = new Set();
let isFetchingData = false;
async function addVIBRankAndInfoToElement(innerElement) {
if (processedElements.has(innerElement)) {
return;
}
const aElement = innerElement.parentElement.querySelector('a[href^="/subject/"]');
if (!aElement) {
return;
}
const match = aElement.getAttribute('href').match(/\/(\d+)$/);
if (!match) {
return;
}
const id = match[1];
const apiUrl = `https://api.jirehlov.com/vib/${id}`;
if (isFetchingData) {
setTimeout(() => {
addVIBRankAndInfoToElement(innerElement);
}, 300);
return;
}
isFetchingData = true;
try {
const response = await fetch(apiUrl, { redirect: 'manual' });
if (response.status === 301) {
return;
}
if (response.ok) {
const data = await response.json();
const vibRank = data.VIB_rank;
const vibScore = data.VIB_score;
const vibRankElement = document.createElement('span');
vibRankElement.classList.add('rank');
vibRankElement.innerHTML = `<small>VIB Rank </small>${vibRank}`;
vibRankElement.style.right = '85px';
const starsElement = document.createElement('span');
starsElement.classList.add('starstop-s');
const starCount = Math.round(vibScore);
starsElement.innerHTML = `<span class="starlight stars${starCount}"></span>`;
const vibScoreDecimal = parseFloat(vibScore).toFixed(1);
const vibEnum = data.VIB_enum;
const ratingInfoElement = document.createElement('p');
ratingInfoElement.classList.add('rateInfo');
ratingInfoElement.appendChild(vibRankElement);
ratingInfoElement.appendChild(starsElement);
ratingInfoElement.innerHTML += `<small class="fade"> ${vibScoreDecimal}</small> <span class="tip_j">(${vibEnum}人VIB评分)</span>`;
innerElement.appendChild(ratingInfoElement);
processedElements.add(innerElement);
}
} catch (error) {
console.error(error);
} finally {
isFetchingData = false;
}
}
const observer = new MutationObserver((mutationsList, observer) => {
mutationsList.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('inner')) {
addVIBRankAndInfoToElement(node);
}
});
}
});
});
const initialInnerElements = document.querySelectorAll('.inner');
initialInnerElements.forEach(addVIBRankAndInfoToElement);
const browserItemList = document.getElementById('browserItemList');
if (browserItemList) {
observer.observe(browserItemList, { childList: true, subtree: true });
}
})();