🏠 Home 

Add manga baka-updates links to nyaa

Adds manga links rating and cover from mangaupdates.com to nyaa.si tracker


Install this script?
// ==UserScript==
// @name        Add manga baka-updates links to nyaa
// @namespace   Violentmonkey Scripts
// @match       https://nyaa.si/*
// @match       https://nyaa.land/*
// @match       https://nyaa.iss.one/*
// @grant       GM.xmlHttpRequest
// @connect     api.mangaupdates.com
// @version     2.2.1
// @author      szq2
// @description Adds manga links rating and cover from mangaupdates.com to nyaa.si tracker
// @license     0BSD
// ==/UserScript==
const fetchRating = true; // Enable fetching series rating and link
const fetchRatingDelay = 2000; // ms
const target = "_blank"; // Target attribute for links, e.g., _blank for a new tab
const re = /^(?:\[.*\])?\s*([^(\[]+?) *((v(olume)?)?[\d\-+ ]+)?( +[\(\[].*)?$/i; // Regex to parse book title
// Fetch JSON helper
const fetchJSON = (url, data) => new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: "POST",
url: url,
headers: {
"Content-Type": "application/json",
},
data: data,
responseType: 'json',
anonymous: true,
onload: response => resolve(response.response),
onerror: err => reject(err),
timeout: 2000,
});
});
// Delay helper
const delay = (time) => new Promise(res => setTimeout(res, time));
// Fetch series details from MangaUpdates API
async function fetchSeriesDetails(title) {
const apiEndpoint = 'https://api.mangaupdates.com/v1/series/search';
// Send API request
const data = await fetchJSON(apiEndpoint, JSON.stringify({
search: title,
stype: 'title',
}));
// Check if r###lts are returned
if (data.total_hits === 0 || !data.r###lts || data.r###lts.length === 0) {
throw new Error(`No series found for: ${title}`);
}
// Extract the first r###lt
const firstR###lt = data.r###lts[0];
const coverPage = firstR###lt.record.image.url.thumb || firstR###lt.record.image.url.original;
const seriesTitle = firstR###lt.hit_title;
const rating = `${firstR###lt.record.year} ${(firstR###lt.record.bayesian_rating || "")}`;
const seriesLink = firstR###lt.record.url;
const fragment = document.createDocumentFragment();
const linkImg = document.createElement("a");
linkImg.href = seriesLink;
linkImg.target = target;
linkImg.title = seriesTitle;
const img = document.createElement("img");
img.src = coverPage;
linkImg.appendChild(img);
fragment.appendChild(linkImg);
const linkRating = document.createElement("a");
linkRating.href = seriesLink;
linkRating.target = target;
linkRating.title = firstR###lt.record.description;
linkRating.textContent = `[${rating}] `;
fragment.appendChild(linkRating);
return fragment;
}
// Main function
(function () {
'use strict';
let book = 0;
// Iterate through all relevant book links
for (let a of document.querySelectorAll("tr > td:nth-child(1) > a[title*='Literature']")) {
a = a.parentElement.nextElementSibling.lastElementChild;
const titleMatch = a.innerText.match(re);
if (!titleMatch) continue;
const title = titleMatch[1];
const url = `https://www.mangaupdates.com/series?search=${encodeURIComponent(title)}`;
// Create [m] link
const mangalink = document.createElement("span");
const basicLink = document.createElement("a");
basicLink.href = url;
basicLink.title = title;
basicLink.target = target;
basicLink.textContent = "[m] ";
mangalink.appendChild(basicLink);
a.insertAdjacentElement("beforebegin", mangalink);
// If ratings fetching is enabled, fetch and update
if (fetchRating) {
delay((book + Math.random()) * fetchRatingDelay)
.then(() => fetchSeriesDetails(title))
.then(fragment => {
// Replace the basic [m] link with the detailed UI
mangalink.textContent = ""; // Clear the placeholder
mangalink.appendChild(fragment);
})
.catch(error => {
console.error('Error fetching series details:', error);
});
}
book++;
}
})();