「蜜柑计划」列表过滤(简繁/画质)

过滤蜜柑计划列表,按照简繁/画质过滤

As of 2024-05-03. See the latest version.

  1. // ==UserScript==
  2. // @name 「蜜柑计划」列表过滤(简繁/画质)
  3. // @namespace https://www.wdssmq.com/
  4. // @version 1.0.2
  5. // @author 沉冰浮水
  6. // @description 过滤蜜柑计划列表,按照简繁/画质过滤
  7. // @license MIT
  8. // @null ----------------------------
  9. // @contributionURL https://github.com/wdssmq#%E4%BA%8C%E7%BB%B4%E7%A0%81
  10. // @contributionAmount 5.93
  11. // @null ----------------------------
  12. // @link https://github.com/wdssmq/userscript
  13. // @link https://afdian.net/@wdssmq
  14. // @link https://greasyfork.org/zh-CN/users/6865-wdssmq
  15. // @null ----------------------------
  16. // @noframes
  17. // @run-at document-end
  18. // @match https://mikanani.me/Home/Bangumi/*
  19. // @match https://mikanime.tv/Home/Bangumi/*
  20. // @match https://feedly.com/i/subscription/feed*
  21. // @grant GM_getValue
  22. // @grant GM_setValue
  23. // @grant GM_registerMenuCommand
  24. // @grant GM_unregisterMenuCommand
  25. // @grant GM_setClipboard
  26. // ==/UserScript==
  27.  
  28. /* eslint-disable */
  29. /* jshint esversion: 6 */
  30.  
  31. (function () {
  32. 'use strict';
  33.  
  34. const gm_name = "Mikan_Proj";
  35.  
  36. // ---------------------------------------------------
  37. const _log = (...args) => console.log(`[${gm_name}]|`, ...args);
  38. function $na(e) {
  39. return document.querySelectorAll(e);
  40. }
  41.  
  42. const _config = {
  43. data: {},
  44. dataDef: {
  45. pickRules: [
  46. {
  47. name: "Kirara Fantasia",
  48. regex: "Baha\\s",
  49. },
  50. {
  51. name: "漫猫字幕组&爱恋字幕组",
  52. regex: "1080p.+简中",
  53. },
  54. {
  55. name: "华盟字幕社&千夏字幕组",
  56. regex: "简体",
  57. },
  58. {
  59. name: "北宇治字幕组",
  60. regex: "简日内嵌",
  61. }
  62. ]
  63. },
  64. optToggle: (opt, ret = false) => {
  65. },
  66. menuCommand: () => {
  67. },
  68. load: () => {
  69. _config.data = GM_getValue("config", _config.dataDef);
  70. },
  71. };
  72.  
  73. _config.load();
  74.  
  75. // 添加批量复制磁力链接功能
  76. function fnAddBatchCopy($th, magnetList) {
  77. const $btn = document.createElement("button");
  78. $btn.innerText = "批量复制";
  79. $btn.addEventListener("click", () => {
  80. const magnetStr = magnetList.join("\n");
  81. GM_setClipboard(magnetStr);
  82. $btn.innerText = "复制成功";
  83. _log(`已复制 ${magnetStr}`);
  84. }, false);
  85. // appendChild 2 elements
  86. $th.appendChild($btn);
  87. }
  88.  
  89. // 过滤磁力链接中的 tr
  90. function fnRemoveTracker(magnet) {
  91. const regex = /&tr=.+?(?=&|$)/g;
  92. return magnet.replace(regex, "");
  93. }
  94.  
  95. // 通过正则表达式筛选文本
  96. function fnPickByRegex(text, regex = null) {
  97. // 如果没有正则表达式,直接返回 true
  98. if (!regex) {
  99. return true;
  100. }
  101. const oRegex = new RegExp(regex, "i");
  102. // _log("fnPickByRegex() oRegex\n", oRegex);
  103. return oRegex.test(text);
  104. }
  105.  
  106.  
  107. function _pick(name, $table) {
  108. const pickRules = _config.data.pickRules;
  109. // 数组中查找 name 对应的规则
  110. const curRule = pickRules.find((rule) => {
  111. return name == rule.name;
  112. });
  113. // _log("_pick() curRule: ", curRule);
  114. // _log("_pick() name: ", name);
  115. // _log("_pick() -----\n","-----");
  116. const $listTr = $table.querySelectorAll("tr");
  117. // _log($listTr.length);
  118. let $curTh = null;
  119. // let $lstTh = null;
  120. let magnetList = [];
  121. $listTr.forEach(($tr, i) => {
  122. if ($tr.innerText.includes("番组名")) {
  123. $curTh = $tr.querySelector("th");
  124. // $lstTh = $curTh;
  125. // _log("fnMain() $curTh\n", $curTh);
  126. fnAddBatchCopy($curTh, magnetList);
  127. magnetList = [];
  128. // return;
  129. }
  130. const $curA = $tr.querySelector(".magnet-link-wrap");
  131. const $curB = $tr.querySelector(".js-magnet");
  132. if (!$curA) {
  133. return;
  134. }
  135. const curText = $curA.innerText.toLowerCase();
  136. // data-clipboard-text
  137. let magnet = $curB.getAttribute("data-clipboard-text");
  138. magnet = fnRemoveTracker(magnet);
  139. if (fnPickByRegex(curText, curRule?.regex)) {
  140. magnetList.push(magnet);
  141. } else {
  142. $tr.remove();
  143. }
  144. });
  145. }
  146.  
  147. // 遍历 nodeList
  148. function fnEachNodeList(nodeList, fn) {
  149. // 倒序遍历
  150. for (let i = nodeList.length - 1; i >= 0; i--) {
  151. fn(nodeList[i], i);
  152. }
  153. }
  154.  
  155. // 按发布组获取信息
  156. function fnGetGroupInfo() {
  157. const arrGroup = [];
  158. // 获取全部 div.subgroup-text
  159. const $listGroup = $na(".subgroup-text");
  160. fnEachNodeList($listGroup, ($group, i) => {
  161. const $groupTitle = $group.querySelector("div.dropdown-toggle span") || $group.querySelector("a");
  162. const groupName = $groupTitle.innerText;
  163. const $groupTable = $group.nextElementSibling;
  164. arrGroup.push({
  165. name: groupName,
  166. $table: $groupTable,
  167. });
  168. });
  169. return arrGroup;
  170. }
  171.  
  172. // main
  173. function fnMain() {
  174. const arrGroup = fnGetGroupInfo();
  175. // _log("arrGroup", arrGroup);
  176. arrGroup.forEach((group) => {
  177. _pick(group.name, group.$table);
  178. // _log("group", group);
  179. });
  180. }
  181.  
  182. // 自动展开更多
  183. function fnAutoExpand() {
  184. const $listBtn = $na(".js-expand-episode");
  185. fnEachNodeList($listBtn, ($btn, i) => {
  186. $btn.click();
  187. });
  188. setTimeout(() => {
  189. fnMain();
  190. }, 3000);
  191. }
  192.  
  193. fnAutoExpand();
  194.  
  195.  
  196. // fnElChange($n(".central-container"),
  197. // () => {
  198. // fnMain();
  199. // }
  200. // )
  201.  
  202. // import _feedly from "./_feedly";
  203.  
  204. // _feedly.regAction(fnEachNodeList, fnFilter, _filter);
  205.  
  206. })();