- // ==UserScript==
- // @name Find on Nyaa
- // @namespace MALFindNya
- // @version 2.8
- // @description Will open nyaa on a new window and search for the anime title
- // @author Samu
- // @match https://myanimelist.net/anime/*
- // @match https://myanimelist.net/anime.php?id=*
- // @match https://anilist.co/*
- // @match https://kitsu.io/*
- // @match https://*.anime-planet.com/*
- // @match https://*.animenewsnetwork.com/*
- // @match https://anidb.net/*
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_registerMenuCommand
- // @grant GM_addStyle
- // ==/UserScript==
-
- /**
- icon source
- https://icons8.com/icon/82838/external-link
- **/
-
- //** SETTINGS **//
- let sortBy = "seeders"; // "comments", "size", "id", "seeders", "leechers", or "downloads"
- let filter = "0"; // 0 = No Filter | 1 = No remakes | 2 = Trusted Only
- let category = "AnimeEnglishTranslated"; // Check values below
- let favoriteGroups = ["Judas", "Erai-raws"]; // List is ordered, favorite should be first
- let searchPrefix = "";
- let searchSufix = "";
- //** END OF SETTINGS **//
-
- // Category values
- const cat = {
- Allcategories: "0_0",
- Anime: "1_0",
- AnimeMusicVideo: "1_1",
- AnimeEnglishTranslated: "1_2",
- AnimeNonEnglishTranslated: "1_3",
- Raw: "1_4",
- Audio: "2_0",
- Lossless: "2_1",
- Lossy: "2_2",
- Literature: "3_0",
- LiteratureEnglishTranslated: "3_1",
- LiteratureNonEnglishTranslated: "3_2",
- LiteratureRaw: "3_3",
- LiveAction: "4_0",
- LiveActionEnglishTranslated: "4_1",
- IdolPromotionalVideo: "4_2",
- LiveActionNonEnglishTranslated: "4_3",
- LiveActionRaw: "4_4",
- Pictures: "5_0",
- Graphics: "5_1",
- Photos: "5_2",
- Software: "6_0",
- Applications: "6_1",
- Games: "6_2",
- };
-
- const buttonId = "FindOnNyaaButtonId";
- const imgKey = "ImgData";
-
- let css = `
- #${buttonId} {
- margin-left: 10px;
- height: 10px;
- width: 10px;
- display: inline-flex;
- transform: scale(1.8);
- vertical-align: top;
- margin-top: 7px;
- }
-
- #${buttonId} svg {
- fill: #000;
- }
-
- #${buttonId}.dark-theme svg {
- fill: #fff;
- }
- `;
-
- GM_addStyle(css);
-
- const sites = [
- {
- host: "myanimelist.net",
- selector: ".title-name",
- isDark: () => document.documentElement.classList.contains("dark-mode"),
- },
- {
- host: "anilist.co",
- path: "/anime/",
- selector: ".page-content .header .content > h1",
- isDark: () => document.body.classList.contains("site-theme-dark"),
- },
- {
- host: "kitsu.io",
- path: "/anime/",
- selector: ".media--title h3",
- isDark: () => {
- var theme = 'light';
- if (window.localStorage) {
- var cacheStorage = window.localStorage.getItem('storage:last-used');
- if (cacheStorage) {
- theme = JSON.parse(cacheStorage).theme || theme;
- }
- }
- return theme === "dark";
- },
- },
- {
- host: "anime-planet.com",
- path: "/anime/",
- selector: "#siteContainer h1",
- isDark: () => document.documentElement.classList.contains("darkmode"),
- },
- {
- host: "animenewsnetwork.com",
- path: "/encyclopedia/anime.php",
- selector: "#page_header",
- filter: /\([a-zA-Z0-9 ]+\)/,
- isDark: () => false,
- },
- {
- host: "anidb.net",
- path: "/anime/",
- selector: "h1.anime",
- filter: /^Anime:\s/,
- isDark: () => true,
- },
- ];
-
-
- let buttonIcon = getIcon();
-
- (function() {
- 'use strict';
-
- GM_registerMenuCommand("Add Custom Icon", uploadImage, "h");
- if (typeof buttonIcon !== "string") {
- GM_registerMenuCommand("Remove Custom Icon", removeImage, "h");
- }
-
- let pushState = history.pushState;
- let replaceState = history.replaceState;
-
- history.pushState = function() {
- pushState.apply(history, arguments);
- window.dispatchEvent(new Event('pushstate'));
- window.dispatchEvent(new Event('locationchange'));
- };
-
- history.replaceState = function() {
- replaceState.apply(history, arguments);
- window.dispatchEvent(new Event('replacestate'));
- window.dispatchEvent(new Event('locationchange'));
- };
-
- window.addEventListener('popstate', function() {
- window.dispatchEvent(new Event('locationchange'))
- });
-
- let host = window.location.host;
- let path = window.location.pathname;
-
- window.addEventListener('locationchange', function() {
- path = window.location.pathname;
- lookForTitleElement(host, path);
- });
-
- lookForTitleElement(host, path);
-
- })();
-
- function lookForTitleElement(host, path) {
-
- for (let i = 0; i < sites.length; i++) {
- let site = sites[i];
- if (host.endsWith(site.host) && (site.path == undefined || path.startsWith(site.path))) {
- waitForElm(site.selector).then(elm => init(elm, site.isDark(), site.filter));
- break;
- }
- }
-
- let nyaaButton = document.getElementById(buttonId);
- if (nyaaButton != null) {
- nyaaButton.parentElement.removeChild(nyaaButton);
- }
-
- }
-
- function init(element, dark = false, filter) {
- let url = createUrl(element, filter);
- let nyaaButton = document.getElementById(buttonId);
- if (nyaaButton == null) {
- nyaaButton = createButton(url);
- element.appendChild(nyaaButton);
- } else {
- nyaaButton.setAttribute("href", url);
- }
-
- if (dark) {
- nyaaButton.classList.add("dark-theme");
- }
- }
-
- function createButton(url) {
- let button = document.createElement("a");
- button.id = buttonId;
- button.setAttribute("href", url);
- button.setAttribute("target", "_blank");
- button.setAttribute("rel", "noopener");
- button.setAttribute("title", "Search on Nyaa");
- if (typeof buttonIcon === "string") {
- button.innerHTML = buttonIcon;
- } else {
- button.appendChild(buttonIcon);
- }
- return button;
- }
-
- function createUrl(element, titleFilter) {
- let textFragment = ":~:text=" + favoriteGroups.join("&text=");
- let title = element.textContent.replace(titleFilter, "").trim().replace(/[^a-zA-Z0-9]+/g, "+").trim();
- let query = [searchPrefix, title, searchSufix].join(" ").trim();
- let queryURI = encodeURI(query);
- let baseUrl = "https://nyaa.si/";
- let path = `?f=${filter}&c=${cat[category]}&s=${sortBy}&o=desc&q=${queryURI}`;
- return baseUrl + path + "#" + textFragment;
- }
-
- function waitForElm(selector) {
- return new Promise(resolve => {
- if (document.querySelector(selector)) {
- return resolve(document.querySelector(selector));
- }
-
- const observer = new MutationObserver(mutations => {
- if (document.querySelector(selector)) {
- resolve(document.querySelector(selector));
- observer.disconnect();
- }
- });
-
- observer.observe(document.body, {
- childList: true,
- subtree: true
- });
- });
- }
-
- function getIcon() {
- let userImg = GM_getValue(imgKey);
-
- if (userImg == null) {
- return `<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M 5 3 C 3.9069372 3 3 3.9069372 3 5 L 3 19 C 3 20.093063 3.9069372 21 5 21 L 19 21 C 20.093063 21 21 20.093063 21 19 L 21 12 L 19 12 L 19 19 L 5 19 L 5 5 L 12 5 L 12 3 L 5 3 z M 14 3 L 14 5 L 17.585938 5 L 8.2929688 14.292969 L 9.7070312 15.707031 L 19 6.4140625 L 19 10 L 21 10 L 21 3 L 14 3 z"/></svg>`;
- }
-
- let imgElement = document.createElement("img");
- imgElement.src = userImg;
- return imgElement;
- }
-
- function uploadImage() {
- let input = document.createElement("input");
- input.type = "file";
- input.addEventListener("change", onImageUploaded);
- input.click();
- }
-
- function onImageUploaded(e) {
- let file = this.files[0];
-
- new Promise((resolve, reject) => {
- const reader = new FileReader()
- reader.onloadend = () => resolve(reader.result)
- reader.onerror = reject
- reader.readAsDataURL(file)
- })
- .then(result => {
- GM_setValue(imgKey, result);
- window.location.reload();
- })
- .catch(err => alert(err));
- }
-
- function removeImage() {
- GM_setValue(imgKey, null);
- window.location.reload();
- }