Find on Nyaa

Will open nyaa on a new window and search for the anime title

目前为 2023-07-30 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Find on Nyaa
  3. // @namespace MALFindNya
  4. // @version 2.8
  5. // @description Will open nyaa on a new window and search for the anime title
  6. // @author Samu
  7. // @match https://myanimelist.net/anime/*
  8. // @match https://myanimelist.net/anime.php?id=*
  9. // @match https://anilist.co/*
  10. // @match https://kitsu.io/*
  11. // @match https://*.anime-planet.com/*
  12. // @match https://*.animenewsnetwork.com/*
  13. // @match https://anidb.net/*
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @grant GM_registerMenuCommand
  17. // @grant GM_addStyle
  18. // ==/UserScript==
  19.  
  20. /**
  21. icon source
  22. https://icons8.com/icon/82838/external-link
  23. **/
  24.  
  25. //** SETTINGS **//
  26. let sortBy = "seeders"; // "comments", "size", "id", "seeders", "leechers", or "downloads"
  27. let filter = "0"; // 0 = No Filter | 1 = No remakes | 2 = Trusted Only
  28. let category = "AnimeEnglishTranslated"; // Check values below
  29. let favoriteGroups = ["Judas", "Erai-raws"]; // List is ordered, favorite should be first
  30. let searchPrefix = "";
  31. let searchSufix = "";
  32. //** END OF SETTINGS **//
  33.  
  34. // Category values
  35. const cat = {
  36. Allcategories: "0_0",
  37. Anime: "1_0",
  38. AnimeMusicVideo: "1_1",
  39. AnimeEnglishTranslated: "1_2",
  40. AnimeNonEnglishTranslated: "1_3",
  41. Raw: "1_4",
  42. Audio: "2_0",
  43. Lossless: "2_1",
  44. Lossy: "2_2",
  45. Literature: "3_0",
  46. LiteratureEnglishTranslated: "3_1",
  47. LiteratureNonEnglishTranslated: "3_2",
  48. LiteratureRaw: "3_3",
  49. LiveAction: "4_0",
  50. LiveActionEnglishTranslated: "4_1",
  51. IdolPromotionalVideo: "4_2",
  52. LiveActionNonEnglishTranslated: "4_3",
  53. LiveActionRaw: "4_4",
  54. Pictures: "5_0",
  55. Graphics: "5_1",
  56. Photos: "5_2",
  57. Software: "6_0",
  58. Applications: "6_1",
  59. Games: "6_2",
  60. };
  61.  
  62. const buttonId = "FindOnNyaaButtonId";
  63. const imgKey = "ImgData";
  64.  
  65. let css = `
  66. #${buttonId} {
  67. margin-left: 10px;
  68. height: 10px;
  69. width: 10px;
  70. display: inline-flex;
  71. transform: scale(1.8);
  72. vertical-align: top;
  73. margin-top: 7px;
  74. }
  75.  
  76. #${buttonId} svg {
  77. fill: #000;
  78. }
  79.  
  80. #${buttonId}.dark-theme svg {
  81. fill: #fff;
  82. }
  83. `;
  84.  
  85. GM_addStyle(css);
  86.  
  87. const sites = [
  88. {
  89. host: "myanimelist.net",
  90. selector: ".title-name",
  91. isDark: () => document.documentElement.classList.contains("dark-mode"),
  92. },
  93. {
  94. host: "anilist.co",
  95. path: "/anime/",
  96. selector: ".page-content .header .content > h1",
  97. isDark: () => document.body.classList.contains("site-theme-dark"),
  98. },
  99. {
  100. host: "kitsu.io",
  101. path: "/anime/",
  102. selector: ".media--title h3",
  103. isDark: () => {
  104. var theme = 'light';
  105. if (window.localStorage) {
  106. var cacheStorage = window.localStorage.getItem('storage:last-used');
  107. if (cacheStorage) {
  108. theme = JSON.parse(cacheStorage).theme || theme;
  109. }
  110. }
  111. return theme === "dark";
  112. },
  113. },
  114. {
  115. host: "anime-planet.com",
  116. path: "/anime/",
  117. selector: "#siteContainer h1",
  118. isDark: () => document.documentElement.classList.contains("darkmode"),
  119. },
  120. {
  121. host: "animenewsnetwork.com",
  122. path: "/encyclopedia/anime.php",
  123. selector: "#page_header",
  124. filter: /\([a-zA-Z0-9 ]+\)/,
  125. isDark: () => false,
  126. },
  127. {
  128. host: "anidb.net",
  129. path: "/anime/",
  130. selector: "h1.anime",
  131. filter: /^Anime:\s/,
  132. isDark: () => true,
  133. },
  134. ];
  135.  
  136.  
  137. let buttonIcon = getIcon();
  138.  
  139. (function() {
  140. 'use strict';
  141.  
  142. GM_registerMenuCommand("Add Custom Icon", uploadImage, "h");
  143. if (typeof buttonIcon !== "string") {
  144. GM_registerMenuCommand("Remove Custom Icon", removeImage, "h");
  145. }
  146.  
  147. let pushState = history.pushState;
  148. let replaceState = history.replaceState;
  149.  
  150. history.pushState = function() {
  151. pushState.apply(history, arguments);
  152. window.dispatchEvent(new Event('pushstate'));
  153. window.dispatchEvent(new Event('locationchange'));
  154. };
  155.  
  156. history.replaceState = function() {
  157. replaceState.apply(history, arguments);
  158. window.dispatchEvent(new Event('replacestate'));
  159. window.dispatchEvent(new Event('locationchange'));
  160. };
  161.  
  162. window.addEventListener('popstate', function() {
  163. window.dispatchEvent(new Event('locationchange'))
  164. });
  165.  
  166. let host = window.location.host;
  167. let path = window.location.pathname;
  168.  
  169. window.addEventListener('locationchange', function() {
  170. path = window.location.pathname;
  171. lookForTitleElement(host, path);
  172. });
  173.  
  174. lookForTitleElement(host, path);
  175.  
  176. })();
  177.  
  178. function lookForTitleElement(host, path) {
  179.  
  180. for (let i = 0; i < sites.length; i++) {
  181. let site = sites[i];
  182. if (host.endsWith(site.host) && (site.path == undefined || path.startsWith(site.path))) {
  183. waitForElm(site.selector).then(elm => init(elm, site.isDark(), site.filter));
  184. break;
  185. }
  186. }
  187.  
  188. let nyaaButton = document.getElementById(buttonId);
  189. if (nyaaButton != null) {
  190. nyaaButton.parentElement.removeChild(nyaaButton);
  191. }
  192.  
  193. }
  194.  
  195. function init(element, dark = false, filter) {
  196. let url = createUrl(element, filter);
  197. let nyaaButton = document.getElementById(buttonId);
  198. if (nyaaButton == null) {
  199. nyaaButton = createButton(url);
  200. element.appendChild(nyaaButton);
  201. } else {
  202. nyaaButton.setAttribute("href", url);
  203. }
  204.  
  205. if (dark) {
  206. nyaaButton.classList.add("dark-theme");
  207. }
  208. }
  209.  
  210. function createButton(url) {
  211. let button = document.createElement("a");
  212. button.id = buttonId;
  213. button.setAttribute("href", url);
  214. button.setAttribute("target", "_blank");
  215. button.setAttribute("rel", "noopener");
  216. button.setAttribute("title", "Search on Nyaa");
  217. if (typeof buttonIcon === "string") {
  218. button.innerHTML = buttonIcon;
  219. } else {
  220. button.appendChild(buttonIcon);
  221. }
  222. return button;
  223. }
  224.  
  225. function createUrl(element, titleFilter) {
  226. let textFragment = ":~:text=" + favoriteGroups.join("&text=");
  227. let title = element.textContent.replace(titleFilter, "").trim().replace(/[^a-zA-Z0-9]+/g, "+").trim();
  228. let query = [searchPrefix, title, searchSufix].join(" ").trim();
  229. let queryURI = encodeURI(query);
  230. let baseUrl = "https://nyaa.si/";
  231. let path = `?f=${filter}&c=${cat[category]}&s=${sortBy}&o=desc&q=${queryURI}`;
  232. return baseUrl + path + "#" + textFragment;
  233. }
  234.  
  235. function waitForElm(selector) {
  236. return new Promise(resolve => {
  237. if (document.querySelector(selector)) {
  238. return resolve(document.querySelector(selector));
  239. }
  240.  
  241. const observer = new MutationObserver(mutations => {
  242. if (document.querySelector(selector)) {
  243. resolve(document.querySelector(selector));
  244. observer.disconnect();
  245. }
  246. });
  247.  
  248. observer.observe(document.body, {
  249. childList: true,
  250. subtree: true
  251. });
  252. });
  253. }
  254.  
  255. function getIcon() {
  256. let userImg = GM_getValue(imgKey);
  257.  
  258. if (userImg == null) {
  259. 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>`;
  260. }
  261.  
  262. let imgElement = document.createElement("img");
  263. imgElement.src = userImg;
  264. return imgElement;
  265. }
  266.  
  267. function uploadImage() {
  268. let input = document.createElement("input");
  269. input.type = "file";
  270. input.addEventListener("change", onImageUploaded);
  271. input.click();
  272. }
  273.  
  274. function onImageUploaded(e) {
  275. let file = this.files[0];
  276.  
  277. new Promise((resolve, reject) => {
  278. const reader = new FileReader()
  279. reader.onloadend = () => resolve(reader.result)
  280. reader.onerror = reject
  281. reader.readAsDataURL(file)
  282. })
  283. .then(result => {
  284. GM_setValue(imgKey, result);
  285. window.location.reload();
  286. })
  287. .catch(err => alert(err));
  288. }
  289.  
  290. function removeImage() {
  291. GM_setValue(imgKey, null);
  292. window.location.reload();
  293. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址