tianteng

各种开车网站的优化,javbus,javlib

Version au 15/08/2024. Voir la dernière version.

  1. // ==UserScript==
  2. // @name tianteng
  3. // @namespace https://greasyfork.org/xmlspy
  4. // @version 2.0.0
  5. // @author xmlspy
  6. // @description 各种开车网站的优化,javbus,javlib
  7. // @license MIT
  8. // @include *
  9. // @match *
  10. // @require https://registry.npmmirror.com/jquery/3.7.1/files/dist/jquery.min.js#sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=
  11.  
  12. // @resource ldbutton/index.min.css https://cdn.jsdelivr.net/npm/ldbutton@2.0.4/index.min.css
  13. // @resource ldloader/index.min.css https://cdn.jsdelivr.net/npm/ldloader@3.0.3/index.min.css
  14. // @resource tabbyjs/dist/css/tabby-ui.min.css https://cdn.jsdelivr.net/npm/tabbyjs@12.0.3/dist/css/tabby-ui.min.css
  15. // @connect *
  16. // @grant GM.setClipboard
  17. // @grant GM.xmlHttpRequest
  18. // @grant GM_addStyle
  19. // @grant GM_deleteValue
  20. // @grant GM_getResourceText
  21. // @grant GM_getValue
  22. // @grant GM_info
  23. // @grant GM_openInTab
  24. // @grant GM_setClipboard
  25. // @grant GM_setValue
  26. // @grant GM_xmlhttpRequest
  27. // @run-at document-start
  28. // ==/UserScript==
  29.  
  30. // https://cdn.jsdelivr.net/npm/ldloader@3.0.3/index.min.js
  31. // prettier-ignore
  32. !function(){var u;function t(t,n){var r,e={}.hasOwnProperty;for(r in n)e.call(n,r)&&(t[r]=n[r]);return t}(u=function(r){var e=this;return null==r&&(r={}),this.opt=t({activeClass:"running",baseZ:4e3,autoZ:!1,className:"",atomic:!0},r),this._toggler="function"==typeof r.toggler?r.toggler:function(){},r.zmgr&&this.zmgr(r.zmgr),["root","container"].map(function(t){var n;if(r[t])return n=Array.isArray(r[t])?r[t]:r[t]instanceof NodeList?Array.from(r[t]):[r[t]],e[t]=n.map(function(t){var n="string"==typeof t?document.querySelector(t):t;return n||console.warn("[ldloader] warning: no node found for "+t),n})}),this.container||(this.container=this.root?this.root.map(function(t){return t.parentNode}):[document.body]),this.root||(this.root=this.container.map(function(t){var n=document.createElement("div");return t.appendChild(n),n})),this.root.map(function(t){if(t.classList.add.apply(t.classList,(e.opt.className||"").split(" ").filter(function(t){return t})),t.classList.remove(r.activeClass),r.inactiveClass)return t.classList.add(r.inactiveClass)}),this.running=!1,this.count=0,this}).prototype=t(Object.create(Object.prototype),{zmgr:function(t){return null!=t?this._zmgr=t:this._zmgr},isOn:function(){return this.running},on:function(t){return this.toggle(!0,t=null==t?0:t)},off:function(t,n){return this.toggle(!1,t=null==t?0:t,n=null==n?!1:n)},cancel:function(t){if(clearTimeout(this.handle),null!=t)return this.toggle(t)},flash:function(t,n){var r=this;return null==t&&(t=1e3),null==n&&(n=0),this.toggle(!0,n).then(function(){return r.toggle(!1,t+n)})},render:function(){var t,r,e=this;return this.running&&this.opt.ctrl&&this.opt.ctrl.step?(this.render.runid=t=Math.random(),this.render.start=0,this.opt.ctrl.init&&this.root.map(function(t){return e.opt.ctrl.init.call(t)}),r=function(n){return e.render.start||(e.render.start=n),e.root.map(function(t){return e.opt.ctrl.step.call(t,n-e.render.start)}),e.render.runid===t?requestAnimationFrame(function(t){return r(t)}):e.opt.ctrl.done?e.root.map(function(t){return e.opt.ctrl.done.call(t,n-e.render.start)}):void 0},requestAnimationFrame(function(t){return r(t)})):this.render.runid=-1},toggle:function(r,e,o){var i,s=this;return null==e&&(e=0),null==o&&(o=!1),i=null==r?this.root[0].classList.contains(this.opt.activeClass)?-1:1:r?1:-1,this.handle&&this.cancel(),e?new Promise(function(t,n){return s.handle=setTimeout(function(){return s.toggle(r).then(function(){return t()})},e)}):new Promise(function(t,n){var r,e;return s.count=0<(r=s.count+i)?r:0,(o||s.opt.atomic||!(2<=s.count||1===s.count&&i<0))&&(s.root.map(function(t){if(t.classList.toggle(s.opt.activeClass,0<i),s.opt.inactiveClass)return t.classList.toggle(s.opt.inactiveClass,i<0)}),s.running=r=s.root[0].classList.contains(s.opt.activeClass),s.opt.ctrl&&s.render(),s.opt.autoZ)&&(e=s._zmgr||u._zmgr,r?(s.z=e.add(s.opt.baseZ),s.root.map(function(t){return t.style.zIndex=s.z})):e.remove(s.z)),t()}).then(function(){return s._toggler(0<i)})}}),t(u,{_zmgr:{add:function(t){return(this.s||(this.s=[])).push(t=Math.max(t||0,((t=this.s)[t.length-1]||0)+1)),t},remove:function(t){if(!((t=(this.s||(this.s=[])).indexOf(t))<0))return this.s.splice(t,1)}},zmgr:function(t){return null!=t?this._zmgr=t:this._zmgr}}),"undefined"!=typeof module&&null!==module?module.exports=u:"undefined"!=typeof window&&null!==window&&(window.ldloader=u)}.call(this);
  33.  
  34. // https://cdn.jsdelivr.net/npm/tabbyjs@12.0.3/dist/js/tabby.min.js
  35. /*! tabbyjs v12.0.3 | (c) 2019 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/tabby */
  36. // prettier-ignore
  37. Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector),Element.prototype.closest||(Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector),Element.prototype.closest=function(e){var t=this;if(!document.documentElement.contains(this))return null;do{if(t.matches(e))return t;t=t.parentElement}while(null!==t);return null}),(function(e,t){"function"==typeof define&&define.amd?define([],(function(){return t(e)})):"object"==typeof exports?module.exports=t(e):e.Tabby=t(e)})("undefined"!=typeof global?global:"undefined"!=typeof window?window:this,(function(e){"use strict";var t={idPrefix:"tabby-toggle_",default:"[data-tabby-default]"},r=function(t){if(t&&"true"!=t.getAttribute("aria-selected")){var r=document.querySelector(t.hash);if(r){var o=(function(e){var t=e.closest('[role="tablist"]');if(!t)return{};var r=t.querySelector('[role="tab"][aria-selected="true"]');if(!r)return{};var o=document.querySelector(r.hash);return r.setAttribute("aria-selected","false"),r.setAttribute("tabindex","-1"),o?(o.setAttribute("hidden","hidden"),{previousTab:r,previousContent:o}):{previousTab:r}})(t);!(function(e,t){e.setAttribute("aria-selected","true"),e.setAttribute("tabindex","0"),t.removeAttribute("hidden"),e.focus()})(t,r),o.tab=t,o.content=r,(function(t,r){var o;"function"==typeof e.CustomEvent?o=new CustomEvent("tabby",{bubbles:!0,cancelable:!0,detail:r}):(o=document.createEvent("CustomEvent")).initCustomEvent("tabby",!0,!0,r),t.dispatchEvent(o)})(t,o)}}},o=function(e,t){var o=(function(e){var t=e.closest('[role="tablist"]'),r=t?t.querySelectorAll('[role="tab"]'):null;if(r)return{tabs:r,index:Array.prototype.indexOf.call(r,e)}})(e);if(o){var n,i=o.tabs.length-1;["ArrowUp","ArrowLeft","Up","Left"].indexOf(t)>-1?n=o.index<1?i:o.index-1:["ArrowDown","ArrowRight","Down","Right"].indexOf(t)>-1?n=o.index===i?0:o.index+1:"Home"===t?n=0:"End"===t&&(n=i),r(o.tabs[n])}};return function(n,i){var a,l,u={};u.destroy=function(){var e=l.querySelectorAll("a");Array.prototype.forEach.call(e,(function(e){var t=document.querySelector(e.hash);t&&(function(e,t,r){e.id.slice(0,r.idPrefix.length)===r.idPrefix&&(e.id=""),e.removeAttribute("role"),e.removeAttribute("aria-controls"),e.removeAttribute("aria-selected"),e.removeAttribute("tabindex"),e.closest("li").removeAttribute("role"),t.removeAttribute("role"),t.removeAttribute("aria-labelledby"),t.removeAttribute("hidden")})(e,t,a)})),l.removeAttribute("role"),document.documentElement.removeEventListener("click",c,!0),l.removeEventListener("keydown",s,!0),a=null,l=null},u.setup=function(){if(l=document.querySelector(n)){var e=l.querySelectorAll("a");l.setAttribute("role","tablist"),Array.prototype.forEach.call(e,(function(e){var t=document.querySelector(e.hash);t&&(function(e,t,r){e.id||(e.id=r.idPrefix+t.id),e.setAttribute("role","tab"),e.setAttribute("aria-controls",t.id),e.closest("li").setAttribute("role","presentation"),t.setAttribute("role","tabpanel"),t.setAttribute("aria-labelledby",e.id),e.matches(r.default)?e.setAttribute("aria-selected","true"):(e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1"),t.setAttribute("hidden","hidden"))})(e,t,a)}))}},u.toggle=function(e){var t=e;"string"==typeof e&&(t=document.querySelector(n+' [role="tab"][href*="'+e+'"]')),r(t)};var c=function(e){var t=e.target.closest(n+' [role="tab"]');t&&(e.preventDefault(),r(t))},s=function(e){var t=document.activeElement;t.matches(n+' [role="tab"]')&&(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Up","Down","Left","Right","Home","End"].indexOf(e.key)<0||o(t,e.key))};return a=(function(){var e={};return Array.prototype.forEach.call(arguments,(function(t){for(var r in t){if(!t.hasOwnProperty(r))return;e[r]=t[r]}})),e})(t,i||{}),u.setup(),(function(t){if(!(e.location.hash.length<1)){var o=document.querySelector(t+' [role="tab"][href*="'+e.location.hash+'"]');r(o)}})(n),document.documentElement.addEventListener("click",c,!0),l.addEventListener("keydown",s,!0),u}}));
  38.  
  39. (function ($, Tabby, ldloader) {
  40. 'use strict';
  41.  
  42. var _GM = /* @__PURE__ */ (() => typeof GM != "undefined" ? GM : void 0)();
  43. var _GM_addStyle = /* @__PURE__ */ (() => typeof GM_addStyle != "undefined" ? GM_addStyle : void 0)();
  44. var _GM_deleteValue = /* @__PURE__ */ (() => typeof GM_deleteValue != "undefined" ? GM_deleteValue : void 0)();
  45. var _GM_getResourceText = /* @__PURE__ */ (() => typeof GM_getResourceText != "undefined" ? GM_getResourceText : void 0)();
  46. var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  47. var _GM_info = /* @__PURE__ */ (() => typeof GM_info != "undefined" ? GM_info : void 0)();
  48. var _GM_openInTab = /* @__PURE__ */ (() => typeof GM_openInTab != "undefined" ? GM_openInTab : void 0)();
  49. var _GM_setClipboard = /* @__PURE__ */ (() => typeof GM_setClipboard != "undefined" ? GM_setClipboard : void 0)();
  50. var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  51. var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
  52. function getUrlParam(url, name) {
  53. const urlObj = new URL(url);
  54. return urlObj.searchParams.get(name);
  55. }
  56. function drawImage(ImgObj, maxWidth, maxHeight) {
  57. var image = new Image();
  58. image.src = ImgObj.src;
  59. var tempWidth;
  60. var tempHeight;
  61. if (image.width > 0 && image.height > 0) {
  62. if (image.width / image.height >= maxWidth / maxHeight) {
  63. if (image.width > maxWidth) {
  64. tempWidth = maxWidth;
  65. tempHeight = image.height * maxWidth / image.width;
  66. } else {
  67. tempWidth = image.width;
  68. tempHeight = image.height;
  69. }
  70. } else {
  71. if (image.height > maxHeight) {
  72. tempHeight = maxHeight;
  73. tempWidth = image.width * maxHeight / image.height;
  74. } else {
  75. tempWidth = image.width;
  76. tempHeight = image.height;
  77. }
  78. }
  79. ImgObj.height = tempHeight;
  80. ImgObj.width = tempWidth;
  81. ImgObj.alt = image.width + "×" + image.height;
  82. }
  83. }
  84. function appendCopyButton(chePai, toAppendElement, callback) {
  85. var copyButton = document.createElement("button");
  86. copyButton.innerHTML = "复 制";
  87. copyButton.setAttribute("id", "copyButton");
  88. toAppendElement.appendChild(copyButton);
  89. document.addEventListener("click", (e) => {
  90. if (e.target.getAttribute("id") === "copyButton") {
  91. _GM.setClipboard(chePai, "text");
  92. }
  93. });
  94. callback && callback(copyButton, chePai, toAppendElement);
  95. }
  96. function addPasteAndSearchButton($searchButton, $searchInput, callback) {
  97. const styleMap = { "margin-left": "5px" };
  98. $searchButton[0] && $searchButton[0].computedStyleMap().forEach((value, key) => {
  99. styleMap[key] = value;
  100. });
  101. let $pasteAndSearchButton = $(
  102. `<input type="button" value="粘贴&搜索" id="pasteAndSearch"></input>`
  103. );
  104. $pasteAndSearchButton.css(styleMap);
  105. $searchButton.after($pasteAndSearchButton);
  106. $pasteAndSearchButton.click(() => {
  107. navigator.clipboard.readText().then((clipText) => {
  108. if (clipText != null && $.trim(clipText) != "") {
  109. $searchInput.val($.trim(clipText));
  110. $searchButton.click();
  111. }
  112. });
  113. });
  114. return $pasteAndSearchButton;
  115. }
  116. let seq = 0;
  117. function debug(str, title) {
  118. {
  119. if (!str) {
  120. str = "";
  121. }
  122. if (!Array.isArray(str)) {
  123. str = [str];
  124. }
  125. seq++;
  126. console.log(
  127. `%ctianteng ${_GM_info.script.version}】 ${title ? title : "debug"}:`,
  128. "color: yellow;font-size: large;font-weight: bold;background-color: darkblue;",
  129. seq,
  130. ...str
  131. );
  132. }
  133. }
  134. function pasteAndSearchEventHandler(searchButton, searchInput, pasteAndSearchButton) {
  135. pasteAndSearchButton.on("click", () => {
  136. navigator.clipboard.readText().then((clipText) => {
  137. if (clipText != null && $.trim(clipText) != "") {
  138. searchInput.val($.trim(clipText));
  139. searchButton.trigger("click");
  140. }
  141. });
  142. });
  143. }
  144. function observe(target, options, callback) {
  145. return new MutationObserver(callback).observe(target, options);
  146. }
  147. function interceptEventListener(interceptorAdd, interceptorRemove) {
  148. const ep = EventTarget.prototype;
  149. if (!ep.addEventListenerOriginal) {
  150. ep.addEventListenerOriginal = ep.addEventListener;
  151. ep.addEventListener = function(type, callback, options) {
  152. if (this) {
  153. if (interceptorAdd) {
  154. const result = interceptorAdd(this, type, callback, options);
  155. if (result === true) {
  156. return;
  157. }
  158. }
  159. this.allListeners = this.allListeners || [];
  160. this.allListeners.push({ type, callback, options });
  161. this.addEventListenerOriginal.apply(this, arguments);
  162. } else {
  163. debug(
  164. `[this] is bad. type: ${type} callback: ${callback} options: ${options}`,
  165. "addEventListenerHook"
  166. );
  167. }
  168. };
  169. }
  170. if (!ep.removeEventListenerOriginal) {
  171. ep.removeEventListenerOriginal = ep.removeEventListener;
  172. ep.removeEventListener = function(type, callback, options) {
  173. if (this) {
  174. {
  175. debug(
  176. `[this] is bad. type: ${type} callback: ${callback} options: ${options}`,
  177. "removeEventListenerHook"
  178. );
  179. }
  180. }
  181. };
  182. }
  183. }
  184. function makeRequestHeaders(headers) {
  185. return $.extend(
  186. {
  187. Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
  188. "Accept-Encoding": "gzip, deflate, br",
  189. "Accept-Language": "zh-CN,zh;q=0.9",
  190. "Cache-Control": "max-age=0",
  191. "Sec-Ch-Ua": '"Chromium";v="119", "Not?A_Brand";v="24"',
  192. "Sec-Ch-Ua-Mobile": "?0",
  193. "Sec-Ch-Ua-Platform": "Windows",
  194. "Sec-Fetch-Dest": "document",
  195. "Sec-Fetch-Mode": "navigate",
  196. "Sec-Fetch-Site": "same-origin",
  197. "Sec-Fetch-User": "?1",
  198. "Upgrade-Insecure-Requests": "1",
  199. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.160 Safari/537.36"
  200. },
  201. headers
  202. );
  203. }
  204. class HandlerExecutor {
  205. constructor(handler) {
  206. this.handler = handler;
  207. this.execute = this.execute.bind(this);
  208. this.checkCondition = this.checkCondition.bind(this);
  209. }
  210. execute() {
  211. if (!this.handler) {
  212. throw new Error("handler is not defined");
  213. }
  214. const { name, condition, handle } = this.handler;
  215. if (!name) {
  216. throw new Error("handler name is not defined");
  217. }
  218. if (condition === null || condition === void 0) {
  219. throw new Error("handler condition is not defined");
  220. }
  221. if (!handle) {
  222. throw new Error("handler handle is not defined");
  223. }
  224. const result = this.checkCondition(condition);
  225. if (result.success === true) {
  226. handle(condition, result.keyOrIndex);
  227. }
  228. return result;
  229. }
  230. /**
  231. *
  232. * @param {RegExp|Function|boolean|string|jQuery|Array<any>} condition
  233. * @returns {Result}
  234. */
  235. checkCondition(condition) {
  236. if ($.type(condition) === "regexp") {
  237. return new Result(condition.test(window.location.href));
  238. }
  239. if ($.isFunction(condition)) {
  240. return new Result(condition() === true);
  241. }
  242. if ($.type(condition) === "boolean") {
  243. return new Result(condition === true);
  244. }
  245. if ($.type(condition) === "string") {
  246. return new Result(document.querySelector(condition) != null);
  247. }
  248. if (condition instanceof $) {
  249. return new Result(condition.length > 0);
  250. }
  251. if ($.isPlainObject(condition)) {
  252. for (const key in condition) {
  253. if (this.checkCondition(condition[key]).success) {
  254. return new Result(true, key);
  255. }
  256. }
  257. }
  258. if ($.isArray(condition)) {
  259. for (const [index, value] of condition) {
  260. if (this.checkCondition(value).success) {
  261. return new Result(true, index);
  262. }
  263. }
  264. }
  265. return new Result(false);
  266. }
  267. }
  268. class Result {
  269. constructor(success, keyOrIndex) {
  270. this.success = success;
  271. this.keyOrIndex = keyOrIndex;
  272. }
  273. }
  274. class Handler {
  275. constructor() {
  276. if (this.constructor === Handler) {
  277. throw new TypeError("Can not construct abstract class.");
  278. }
  279. this.handle = this.handle.bind(this);
  280. }
  281. get name() {
  282. throw new Error("not implemented");
  283. }
  284. get condition() {
  285. throw new Error("not implemented");
  286. }
  287. handle(condition, keyOrIndex) {
  288. throw new Error("not implemented");
  289. }
  290. }
  291. class BaiduHandler extends Handler {
  292. get name() {
  293. return "百度";
  294. }
  295. get condition() {
  296. return /baidu\.com/;
  297. }
  298. handle(condition, keyOrIndex) {
  299. debug("添加 粘贴并搜索 按钮", this.name);
  300. const searchButton = $(`[type="submit"]`);
  301. const searchInput = $(`#kw`);
  302. if (searchButton.length === 0 || searchInput.length === 0) {
  303. debug("找不到搜索按钮或搜索输入框", this.name);
  304. debug("serachButton.length:{serachButton.length}", this.name);
  305. debug("searchInput.length:{searchInput.length}", this.name);
  306. return;
  307. }
  308. const pasteAndSearchButton = searchButton.clone();
  309. pasteAndSearchButton.val("粘贴&搜索").removeAttr("id").attr("type", "button");
  310. searchButton.parent().append(pasteAndSearchButton);
  311. searchButton.parent().css("width", "auto");
  312. _GM_addStyle(`
  313. #head_wrapper .s_form {
  314. width: auto;
  315. height: 100%;
  316. margin: 0 auto;
  317. text-align: center;
  318. }
  319. #head_wrapper .s_btn_wr .wrapper_new{
  320. width:auto;
  321. }
  322. `);
  323. pasteAndSearchEventHandler(searchButton, searchInput, pasteAndSearchButton);
  324. }
  325. }
  326. class OsChinaHandler extends Handler {
  327. get name() {
  328. return "开源中国";
  329. }
  330. get condition() {
  331. return /oschina\.net/;
  332. }
  333. handle(condition, keyword) {
  334. debug("修改首页某些链接无法中键点击问题.", "开源中国");
  335. $(`[data-href]`).each(function() {
  336. const $this = $(this);
  337. const href = $this.attr("data-href");
  338. const classCss = $this.attr("class");
  339. const title = $this.attr("title");
  340. const innerHtml = this.innerHTML;
  341. const html = `<a target="_blank" title="${title}" href="${href}" class="${classCss}">${innerHtml}</a>`;
  342. $this.replaceWith(html);
  343. });
  344. debug("删除url中的重定向.", "开源中国");
  345. $('a[href*="/action/GoToLink?url"]').each(function() {
  346. let href = $(this).attr("href");
  347. if (href) {
  348. let url = getUrlParam(href, "url");
  349. $(this).attr("href", url);
  350. }
  351. });
  352. }
  353. }
  354. class GiteeHandler extends Handler {
  355. get name() {
  356. return "gitee";
  357. }
  358. get condition() {
  359. return /gitee\.com/;
  360. }
  361. handle(condition, keyword) {
  362. debug("删除url中的重定向.", "gitee");
  363. $('a[href*="/link?target"]').each(function(index) {
  364. let href = $(this).attr("href");
  365. if (href) {
  366. let url = getUrlParam(href, "target");
  367. $(this).attr("href", url);
  368. }
  369. });
  370. }
  371. }
  372. class ZhihuHandler extends Handler {
  373. get name() {
  374. return "知乎";
  375. }
  376. get condition() {
  377. return /zhihu\.com/;
  378. }
  379. handle(condition, keyOrIndex) {
  380. debug("添加 粘贴并搜索 按钮", "知乎");
  381. const searchButton = $(`button[class*="SearchBar-searchButton"]`);
  382. const searchInput = $(`#Popover1-toggle`);
  383. addPasteAndSearchButton(searchButton, searchInput);
  384. }
  385. }
  386. class WnacgHandler extends Handler {
  387. get name() {
  388. return "绅士漫画";
  389. }
  390. get condition() {
  391. return $('head>title:contains("紳士漫畫")');
  392. }
  393. handle(condition, keyword) {
  394. if (location.href.includes("photos-index-aid")) {
  395. debug("明细页面添加搜索框", "紳士漫畫");
  396. const searchInput = `
  397. <div class="search" style="float:right;">
  398. <form id="album_search q-form" action="/search/" method="get" _lpchecked="1">
  399. <div class="input-append" id="q-input">
  400. <input type="text" class="search-query ui-autocomplete-input tips"
  401. name="q" value="" title="搜索漫畫" autocomplete="off"
  402. role="textbox" aria-autocomplete="list" aria-haspopup="true">
  403. <input style="display:none" type="radio" name="f" value="_all" checked="">
  404. <input style="display:none" name="s" value="create_time_DESC">
  405. <input style="display:none" name="syn" value="yes">
  406. <button type="" name=""></button>
  407. </div>
  408. </form>
  409. </div>
  410. `;
  411. $("#bodywrap").prepend(searchInput);
  412. }
  413. if (location.href.includes("photos-slide-aid")) {
  414. debug("下拉阅读页面,图片由一列改为两列", "紳士漫畫");
  415. const nodeToObserve = document.querySelector("#img_list");
  416. $(nodeToObserve).css({
  417. width: "100%",
  418. display: "flex",
  419. "flex-wrap": "wrap",
  420. "justify-content": "flex-start",
  421. "overflow-x": "hidden"
  422. });
  423. const imgWidth = document.documentElement.clientWidth / 2 - 10;
  424. const imgHeight = document.documentElement.clientHeight - 50;
  425. new MutationObserver((mutations, observer) => {
  426. $("#img_list>div").css({
  427. flex: "1",
  428. "background-color": "#cacaca",
  429. margin: "0 5px 5px 0",
  430. width: "calc((100% - 10px) / 2)",
  431. "min-width": "calc((100% - 10px) / 2)",
  432. "max-width": "calc((100% - 10px) / 2)"
  433. });
  434. $("#img_list>div>img").on("load", (e) => {
  435. drawImage(e.target, imgWidth, imgHeight);
  436. });
  437. }).observe(nodeToObserve, { childList: true });
  438. }
  439. if ($("input.search-query").length > 0) {
  440. debug("为搜索框后面添加 粘贴&搜索 按钮", "紳士漫畫");
  441. const searchInput = $("[name=q]");
  442. const searchButton = $("#q-input > button");
  443. const pasteAndSearchButton = $(
  444. `<button style="float:right;height:30px;">粘贴&amp;搜索</button>`
  445. );
  446. $("#bodywrap").prepend(pasteAndSearchButton);
  447. pasteAndSearchEventHandler(searchButton, searchInput, pasteAndSearchButton);
  448. }
  449. }
  450. }
  451. const domainConfig = {
  452. javbus: { url: "https://www.fanbus.help" },
  453. javlib: { url: "https://www.y78k.com" },
  454. ciligege: { url: "https://www.ciligege2.com" },
  455. // https://tellme.pw/btsow https://btsow.com
  456. btsow: { url: "https://btsow.motorcycles" },
  457. btsearch: { url: "https://www.btsearch.love" },
  458. // 最新地址發布(請收藏):u9a9.link ,永久域名 u9a9.com,u9a9.net,u9a9.ru,u9a9.xyz,u9a9.org,u9a9.me
  459. // Email: u9a9.com#protonmail.com
  460. u9a9: { url: "https://y.u9a9y.xyz" },
  461. skrbt: { url: "https://skrbtqx.top" }
  462. };
  463. domainConfig.javbus.searchUrl = `${domainConfig.javbus.url}/search?q=%s`;
  464. domainConfig.javlib.searchUrl = `${domainConfig.javlib.url}/search?q=%s`;
  465. domainConfig.ciligege.searchUrl = `${domainConfig.ciligege.url}/search/%s/1`;
  466. domainConfig.btsow.searchUrl = `${domainConfig.btsow.url}/search/%s`;
  467. domainConfig.btsearch.searchUrl = `${domainConfig.btsearch.url}/search?q=%s`;
  468. domainConfig.u9a9.searchUrl = `${domainConfig.u9a9.url}/?type=2&search=%s`;
  469. domainConfig.skrbt.searchUrl = `${domainConfig.skrbt.url}/search?keyword=%s`;
  470. class FakeCookie extends Map {
  471. constructor(fullCookieString) {
  472. super();
  473. this.fullCookieString = fullCookieString;
  474. }
  475. get fullCookieString() {
  476. let result = "";
  477. this.forEach((value, key, self) => {
  478. result = result.concat(key).concat("=").concat(value).concat(";");
  479. });
  480. return result === "" ? result : result.substring(0, result.length - 1);
  481. }
  482. set fullCookieString(str) {
  483. if (str) {
  484. let items = str.split(";");
  485. items.map((element, index) => element.trim()).filter((element, index, self) => self.indexOf(element) === index).forEach((element) => {
  486. const pair = element.split("=");
  487. this.set(pair[0], pair[1]);
  488. });
  489. }
  490. }
  491. /**
  492. * 把newCookie合并到当前实例中.如果newCookie中的key与当前的实例重复,这使用newCookie中的覆盖.
  493. * @param {String|FakeCookie} newCookie 要合并的新cookie,类型为String或者FakeCookie.
  494. * 如果类型为String,表示包含全部cookie内容的字符串;
  495. */
  496. merge(newCookie) {
  497. if (!newCookie) {
  498. return;
  499. }
  500. let newFakeCookie;
  501. if (typeof newCookie === "string") {
  502. newFakeCookie = new FakeCookie(newCookie);
  503. } else if (newCookie instanceof FakeCookie) {
  504. newFakeCookie = newCookie;
  505. } else {
  506. throw new TypeError("Invalid type.");
  507. }
  508. newFakeCookie.forEach((value, key, self) => this.set(key, value));
  509. }
  510. }
  511. let fakeCookie = new FakeCookie();
  512. function getSearchResultFromSkrbt(chepai, callback) {
  513. const skrbtUrl = domainConfig.skrbt.url;
  514. const searchUrl = domainConfig.skrbt.searchUrl.replace("%s", chepai);
  515. function getResponseHeader(response, name) {
  516. if (response && response.responseHeaders && name) {
  517. var arr = response.responseHeaders.trim().split(/[\r\n]+/);
  518. var headerMap = {};
  519. arr.forEach(function(line) {
  520. var parts = line.split(": ");
  521. var header = parts.shift();
  522. var value = parts.join(": ");
  523. headerMap[header] = value;
  524. });
  525. return headerMap[name];
  526. }
  527. return null;
  528. }
  529. function onResponseHeaderRecieved(response) {
  530. if (response.readyState === response.HEADERS_RECEIVED) {
  531. console.log(response.responseHeaders);
  532. const setCookie = getResponseHeader(response, "Set-Cookie");
  533. fakeCookie.merge(setCookie);
  534. }
  535. }
  536. const timeoutIds = [];
  537. function clearTimeouts() {
  538. timeoutIds.forEach((timeoutId) => clearTimeout(timeoutId));
  539. }
  540. function successHandler(response, callback2) {
  541. clearTimeouts();
  542. const $container = $(response.responseText).find(".col-md-6:eq(2)");
  543. const data = $.map($container.find(".list-unstyled"), (item) => {
  544. const title = $(item).find("a.rrt.common-link").html();
  545. const detailHref = $(item).find("a.rrt.common-link").attr("href");
  546. const fileSize = $(item).find("li.rrmi > span:nth-child(2)").text();
  547. const fileCount = $(item).find("li.rrmi > span:nth-child(3)").text();
  548. const timeIncluded = $(item).find("li.rrmi > span:nth-child(4)").text();
  549. return {
  550. name: title,
  551. detailUrl: domainConfig.skrbt.url + detailHref,
  552. //明细页面地址
  553. size: fileSize,
  554. // 文件总大小
  555. fileCount,
  556. // 文件总数
  557. date: timeIncluded
  558. // 收入时间
  559. };
  560. });
  561. callback2({
  562. result: 0,
  563. data
  564. // html: $container.html(),
  565. });
  566. }
  567. _GM_xmlhttpRequest({
  568. method: "get",
  569. headers: makeRequestHeaders({ Referer: skrbtUrl }),
  570. url: searchUrl,
  571. onerror: function(e) {
  572. console.log(e);
  573. },
  574. onload: function(response) {
  575. console.log(response);
  576. if (response.finalUrl.includes("/search?")) {
  577. console.log("-----------OK");
  578. successHandler(response, callback);
  579. } else if (response.finalUrl.includes("/challenge")) {
  580. waitRecaptcha();
  581. } else {
  582. console.log("错误");
  583. clearTimeouts();
  584. callback({ result: 1, message: "" });
  585. }
  586. },
  587. onreadystatechange: onResponseHeaderRecieved
  588. });
  589. function waitRecaptcha() {
  590. var remain = 10;
  591. var startTime = (/* @__PURE__ */ new Date()).getTime();
  592. timeoutIds.unshift(setTimeout(timeoutHandler, 1e3));
  593. timeoutIds.unshift(setTimeout(doChallange, 1e3));
  594. function timeoutHandler() {
  595. console.log("timeoutHandler");
  596. remain = remain - 1;
  597. console.log(`remain: ${remain}`);
  598. if (remain > 0) {
  599. timeoutIds.unshift(setTimeout(timeoutHandler, 1e3));
  600. } else {
  601. doSubmit(randomString(100));
  602. }
  603. }
  604. function doChallange() {
  605. console.log("doChallange");
  606. var aywcUid = genOrGetAywcUid();
  607. var genApi = skrbtUrl + "/anti/recaptcha/v4/gen?aywcUid=" + aywcUid + "&_=" + (/* @__PURE__ */ new Date()).getTime();
  608. _GM_xmlhttpRequest({
  609. method: "get",
  610. responseType: _GM_xmlhttpRequest.RESPONSE_TYPE_JSON,
  611. headers: makeRequestHeaders({
  612. Referer: `${skrbtUrl}/recaptcha/v4/challenge?url=${skrbtUrl}&s=1`
  613. }),
  614. url: genApi,
  615. onerror: function(e) {
  616. console.log(/* @__PURE__ */ new Date() + ": " + e);
  617. timeoutIds.unshift(setTimeout(doChallange, 1e3));
  618. console.log(e);
  619. },
  620. onload: function(response) {
  621. const genResult = response.response;
  622. if (genResult.errno == 0) {
  623. doSubmit(genResult.token);
  624. } else {
  625. timeoutIds.unshift(setTimeout(doChallange, 1e3));
  626. }
  627. },
  628. onreadystatechange: onResponseHeaderRecieved
  629. });
  630. }
  631. function doSubmit(token) {
  632. console.log("doSubmit");
  633. var costtime = (/* @__PURE__ */ new Date()).getTime() - startTime;
  634. _GM_xmlhttpRequest({
  635. method: "get",
  636. headers: makeRequestHeaders({
  637. Referer: `${skrbtUrl}/recaptcha/v4/challenge?url=${skrbtUrl}&s=1`
  638. }),
  639. url: `${skrbtUrl}/anti/recaptcha/v4/verify?token=${token}&aywcUid=${genOrGetAywcUid()}&costtime=${costtime}`,
  640. onerror: function(e) {
  641. console.log(e);
  642. clearTimeouts();
  643. callback({ result: 2, message: "" });
  644. },
  645. onload: function(response) {
  646. console.log("-----doSubmit OK");
  647. console.log(response);
  648. if (response.finalUrl.includes("search?")) {
  649. successHandler(response, callback);
  650. } else {
  651. console.log("错误");
  652. clearTimeouts();
  653. callback({ result: 3, message: "" });
  654. }
  655. },
  656. onreadystatechange: onResponseHeaderRecieved
  657. });
  658. }
  659. function genOrGetAywcUid() {
  660. const unifyidKey = "aywcUid";
  661. let aywcUid = fakeCookie.get(unifyidKey);
  662. if (isEmpty(aywcUid)) {
  663. aywcUid = randomString(10) + "_" + formatDate("yyyyMMddhhmmss", /* @__PURE__ */ new Date());
  664. fakeCookie.set(unifyidKey, aywcUid);
  665. }
  666. return aywcUid;
  667. }
  668. function isEmpty(x) {
  669. if (x == null || x == void 0 || x == "") {
  670. return true;
  671. } else {
  672. return false;
  673. }
  674. }
  675. function randomString(len, charSet) {
  676. charSet = charSet || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  677. var randomString2 = "";
  678. for (var i = 0; i < len; i++) {
  679. var randomPoz = Math.floor(Math.random() * charSet.length);
  680. randomString2 += charSet.substring(randomPoz, randomPoz + 1);
  681. }
  682. return randomString2;
  683. }
  684. function formatDate(fmt, date) {
  685. var o = {
  686. "M+": date.getMonth() + 1,
  687. "d+": date.getDate(),
  688. "h+": date.getHours(),
  689. "m+": date.getMinutes(),
  690. "s+": date.getSeconds(),
  691. "q+": Math.floor((date.getMonth() + 3) / 3),
  692. S: date.getMilliseconds()
  693. };
  694. if (/(y+)/.test(fmt)) {
  695. fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  696. }
  697. for (var k in o) {
  698. if (new RegExp("(" + k + ")").test(fmt)) {
  699. fmt = fmt.replace(
  700. RegExp.$1,
  701. RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
  702. );
  703. }
  704. }
  705. return fmt;
  706. }
  707. }
  708. }
  709. const magnetTabsConfig = {
  710. id: "tianteng-magnet-tabs",
  711. tabs: [
  712. {
  713. id: "tianteng-tab-skrbt",
  714. title: "SKRBT",
  715. url: domainConfig.skrbt.searchUrl,
  716. default: true,
  717. type: 1
  718. },
  719. {
  720. id: "tianteng-tab-btsow",
  721. title: "BTSOW",
  722. url: domainConfig.btsow.searchUrl,
  723. extractor: function(doc, itemCallback) {
  724. const data = [];
  725. $("div.data-list>.row[class=row]", doc).each(function(index, item) {
  726. const detailUrl = "https:" + $("a", item).attr("href");
  727. const name = $("a>div:first", item).html();
  728. let magnet = $("a", item).attr("href").split("/magnet/detail/hash/")[1];
  729. magnet = `magnet:?xt=urn:btih:${magnet}`;
  730. const size = $(item).children("div").first().text().replace("文件大小:", "");
  731. const date = $(item).children("div").last().text().replace("时间:", "");
  732. const record = {
  733. detailUrl,
  734. name,
  735. magnet,
  736. size,
  737. date
  738. };
  739. data.push(record);
  740. itemCallback && itemCallback(record, index, item);
  741. });
  742. return data;
  743. }
  744. },
  745. {
  746. id: "tianteng-tab-ciligege",
  747. title: "CiLiGeGe",
  748. url: domainConfig.ciligege.searchUrl,
  749. extractor: function(doc, itemCallback) {
  750. const data = [];
  751. $("div.bt-list>.bt-card", doc).each(function(index, item) {
  752. const detailUrl = domainConfig.ciligege.url + $("a", item).attr("href");
  753. const name = $("a", item).html();
  754. let magnet = $("a", item).attr("href").replace("/search/", "");
  755. magnet = `magnet:?xt=urn:btih:${magnet}`;
  756. const size = $("div.bt-card-body>span", item).first().text().replace("文件大小:", "");
  757. const date = $("div.bt-card-body>span", item).last().text().replace("时间:", "");
  758. const record = {
  759. detailUrl,
  760. name,
  761. magnet,
  762. size,
  763. date
  764. };
  765. data.push(record);
  766. itemCallback && itemCallback(record, index, item);
  767. });
  768. return data;
  769. }
  770. },
  771. {
  772. id: "tianteng-tab-u9a9",
  773. title: "U9A9",
  774. url: domainConfig.u9a9.searchUrl,
  775. extractor: function(doc, itemCallback) {
  776. const data = [];
  777. $("tbody>tr", doc).each(function(index, item) {
  778. const a = $("td", item).eq(1).find("a");
  779. const detailUrl = domainConfig.u9a9.url + a.attr("href");
  780. const name = a.html();
  781. let magnet = $("td", item).eq(2).find("a").eq(1).attr("href");
  782. const size = $("td", item).eq(3).text();
  783. const date = $("td", item).eq(4).text();
  784. const record = {
  785. detailUrl,
  786. name,
  787. magnet,
  788. size,
  789. date
  790. };
  791. data.push(record);
  792. itemCallback && itemCallback(record, index, item);
  793. });
  794. return data;
  795. }
  796. }
  797. ]
  798. };
  799. class MagnetTab {
  800. /**
  801. *
  802. * @param {string} chepai 车牌号
  803. * @param {Function} onAttach 回调函数,function(tabContainer),
  804. * 参数tabContainer是整个MagnetTab的根节点,可以在此函数中把tabContainer插入到页面中
  805. * @param {object} tabsConfig 配置
  806. */
  807. constructor(chepai, onAttach, tabsConfig) {
  808. _GM_addStyle(_GM_getResourceText("tabbyjs/dist/css/tabby-ui.min.css"));
  809. this.chepai = chepai;
  810. if (tabsConfig) {
  811. this.tabsConfig = tabsConfig;
  812. } else {
  813. this.tabsConfig = magnetTabsConfig;
  814. }
  815. this.onAttach = onAttach;
  816. this.init();
  817. }
  818. getConfig(id) {
  819. for (let i = 0; this.tabsConfig.tabs.length; i++) {
  820. const config = this.tabsConfig.tabs[i];
  821. if (id === config.id) {
  822. return config;
  823. }
  824. }
  825. return null;
  826. }
  827. /**
  828. *
  829. * <ul id="tianteng-magnet-tabs">
  830. * <li><a data-tabby-default href="#tianteng-tab-skrbt">tab上的文字</a></li>
  831. * <li><a href="#hermione">tab上的文字</a></li>
  832. * <li><a href="#neville">tab上的文字</a></li>
  833. * </ul>
  834. *
  835. * <div id="tianteng-tab-skrbt">tab内容,是个table</div>
  836. * <div id="hermione">tab内容,是个table</div>
  837. * <div id="neville">tab内容,是个table</div>
  838. */
  839. init() {
  840. $(document).on("click", "button.tianteng-click, button.tianteng-copy", (e) => {
  841. if (this.currentTabConfig.type === 1 && this.currentTabConfig.id === "tianteng-tab-skrbt") {
  842. const button = e.target;
  843. const magnet = button.dataset["tiantengMagnet"];
  844. if (magnet !== "undefined") {
  845. if ($(button).attr("class").includes("tianteng-copy")) {
  846. _GM_setClipboard(magnet, "text");
  847. } else {
  848. _GM_openInTab(magnet);
  849. }
  850. e.preventDefault();
  851. e.stopImmediatePropagation();
  852. e.stopPropagation();
  853. return false;
  854. } else {
  855. _GM_xmlhttpRequest({
  856. method: "get",
  857. headers: makeRequestHeaders({ Referer: `${domainConfig.skrbt.url}/search` }),
  858. url: button.dataset["tiantengMagnetUrl"],
  859. onerror: function(e2) {
  860. console.log("获取磁链失败,等会儿再试一试! 若仍然有问题请刷新网页.");
  861. },
  862. onload: function(response) {
  863. const magnet2 = $(response.responseText).find("#magnet").attr("href");
  864. if (magnet2) {
  865. button.dataset["tiantengMagnet"] = magnet2;
  866. if ($(button).attr("class").includes("tianteng-copy")) {
  867. button.nextElementSibling.dataset["tiantengMagnet"] = magnet2;
  868. _GM_setClipboard(magnet2, "text");
  869. } else {
  870. button.previousElementSibling.dataset["tiantengMagnet"] = magnet2;
  871. _GM_openInTab(magnet2);
  872. }
  873. e.preventDefault();
  874. e.stopImmediatePropagation();
  875. e.stopPropagation();
  876. } else {
  877. console.log("获取磁链失败,等会儿再试一试! 若仍然有问题请刷新网页.");
  878. console.log(response);
  879. }
  880. }
  881. });
  882. }
  883. } else {
  884. const button = e.target;
  885. const magnet = button.dataset["tiantengMagnet"];
  886. if ($(button).attr("class").includes("tianteng-copy")) {
  887. _GM_setClipboard(magnet, "text");
  888. } else {
  889. _GM_openInTab(magnet);
  890. }
  891. e.preventDefault();
  892. e.stopImmediatePropagation();
  893. e.stopPropagation();
  894. return false;
  895. }
  896. });
  897. const fragment = document.createDocumentFragment();
  898. const ul = document.createElement("ul");
  899. ul.id = this.tabsConfig.id;
  900. fragment.append(ul);
  901. let defaultTabConfig;
  902. let defaultTab;
  903. let defaultTabContent;
  904. this.tabsConfig.tabs.forEach((tab, index, array) => {
  905. const li = document.createElement("li");
  906. const a = document.createElement("a");
  907. a.href = `#${tab.id}`;
  908. a.text = tab.title;
  909. li.append(a);
  910. ul.append(li);
  911. const div = document.createElement("div");
  912. div.id = tab.id;
  913. div.dataset["tiantengTabConfig"] = JSON.stringify(tab);
  914. div.dataset["tiantengChepai"] = this.chepai;
  915. div.tiantengTabConfig = tab;
  916. fragment.append(div);
  917. if (tab.default === true) {
  918. a.dataset["tabbyDefault"] = "";
  919. defaultTabConfig = tab;
  920. defaultTab = a;
  921. defaultTabContent = div;
  922. }
  923. });
  924. const tabsContainer = document.createElement("div");
  925. tabsContainer.id = "tianteng-tabs-container";
  926. tabsContainer.append(fragment);
  927. this.onAttach(tabsContainer);
  928. $(tabsContainer).before(`
  929. <style id='tianteng-tab-style'>
  930. #tianteng-tabs-container {
  931. background-color:white;
  932. margin-top:10px;
  933. margin-bottom:10px;
  934. padding:12px;
  935. }
  936. #tianteng-tabs-container strong,
  937. #tianteng-tabs-container em,
  938. #tianteng-tabs-container .high-light,
  939. #tianteng-tabs-container .highlight{
  940. font-weight:normal;
  941. color:#F00;
  942. }
  943. #tianteng-tabs-container tr:hover{
  944. background-color:#d7e7f4;
  945. }
  946. #tianteng-tabs-container th,
  947. #tianteng-tabs-container td{
  948. text-align:center;
  949. padding:10px,10px !important;
  950. }
  951. </style>`);
  952. this.tabby = new Tabby(`#${this.tabsConfig.id}`);
  953. document.addEventListener(
  954. "tabby",
  955. (event) => {
  956. const tab = event.detail.tab;
  957. const content = event.detail.content;
  958. this.currentTabConfig = content.tiantengTabConfig;
  959. this.buildHtml(tab, content);
  960. },
  961. false
  962. );
  963. this.currentTabConfig = defaultTabConfig;
  964. this.buildHtml(defaultTab, defaultTabContent);
  965. }
  966. buildHtml(tab, tabContent) {
  967. if ($(tabContent).data("tiantengStatus") === "ok") {
  968. return;
  969. }
  970. let tabConfig = tabContent.tiantengTabConfig;
  971. let tableHtml = `
  972. <table class="tianteng-magnet-table"
  973. style="border-collapse: collapse;text-align:center;width:100%;">
  974. <thead style="position:sticky;top:0;background-color:#f5f5f5;">
  975. <tr>
  976. <th style="border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: none; border-bottom: none; text-align:left;">
  977. 磁力名称</th>
  978. <th style="border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: none; border-bottom: none;">
  979. 档案大小</th>
  980. <th style="border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: none; border-bottom: none;">
  981. 分享日期</th>
  982. </tr>
  983. </thead>
  984. <tbody class="tianteng-magnet-tbody">
  985. {{tbody}}
  986. </tbody>
  987. </table>`;
  988. const searchUrl = tabConfig.url.replace("%s", this.chepai);
  989. if (tabConfig.type === 1 && tabConfig.id === "tianteng-tab-skrbt") {
  990. getSearchResultFromSkrbt(this.chepai, function(data) {
  991. if (data.result == 0) {
  992. let tbodyHtml = "";
  993. data.data.forEach(function(record, index, array) {
  994. tbodyHtml += `
  995. <tr>
  996. <td style="border: 1px solid #ccc; text-align:left; width:70%;">
  997. <a style="color:#333" target="_blank"
  998. title="打开磁链明细页面"
  999. href="${record.detailUrl}">
  1000. ${record.name}
  1001. </a>
  1002. <button class="btn btn-danger tianteng-copy"
  1003. type="button"
  1004. data-tianteng-magnet-url="${record.detailUrl}"
  1005. data-tianteng-magnet="${record.magnet}">复制磁链</button>
  1006. <button class="btn btn-danger tianteng-click"
  1007. type="button"
  1008. data-tianteng-magnet-url="${record.detailUrl}"
  1009. data-tianteng-magnet="${record.magnet}">打开磁链</button>
  1010. </td>
  1011. <td style="border: 1px solid #ccc;">${record.size}</td>
  1012. <td style="border: 1px solid #ccc;">${record.date}</td>
  1013. </tr>
  1014. `;
  1015. });
  1016. tableHtml = tableHtml.replace("{{tbody}}", tbodyHtml);
  1017. $(tabContent).append(tableHtml);
  1018. $(tabContent).data("tiantengStatus", "ok");
  1019. }
  1020. });
  1021. } else {
  1022. _GM_xmlhttpRequest({
  1023. method: "GET",
  1024. url: searchUrl,
  1025. headers: makeRequestHeaders({ Referer: searchUrl }),
  1026. onerror: function() {
  1027. debug(arguments, "onerror");
  1028. },
  1029. ontimeout: function() {
  1030. debug(arguments, "ontimeout");
  1031. },
  1032. onreadystatechange: function() {
  1033. debug(arguments, "onreadystatechange");
  1034. },
  1035. onabort: function() {
  1036. debug(arguments, "onabort");
  1037. },
  1038. onloadstart: function() {
  1039. debug(arguments, "onloadstart");
  1040. },
  1041. onprogress: function() {
  1042. debug(arguments, "onprogress");
  1043. },
  1044. onload: function(response) {
  1045. debug(arguments, "onload");
  1046. const doc = $(response.responseText);
  1047. let tbodyHtml = "";
  1048. tabConfig.extractor(doc, (record, index, item) => {
  1049. tbodyHtml += `
  1050. <tr>
  1051. <td style="border: 1px solid #ccc; text-align:left; width:70%;">
  1052. <a style="color:#333" target="_blank"
  1053. title="打开磁链明细页面"
  1054. href="${record.detailUrl}">
  1055. ${record.name}
  1056. </a>
  1057. <button class="btn btn-danger tianteng-copy"
  1058. type="button"
  1059. data-tianteng-magnet="${record.magnet}">复制磁链</button>
  1060. <button class="btn btn-danger tianteng-click"
  1061. type="button"
  1062. data-tianteng-magnet="${record.magnet}">打开磁链</button>
  1063. </td>
  1064. <td style="border: 1px solid #ccc;">${record.size}</td>
  1065. <td style="border: 1px solid #ccc;">${record.date}</td>
  1066. </tr>
  1067. `;
  1068. });
  1069. tableHtml = tableHtml.replace("{{tbody}}", tbodyHtml);
  1070. $(tabContent).append(tableHtml);
  1071. $(tabContent).data("tiantengStatus", "ok");
  1072. }
  1073. });
  1074. }
  1075. }
  1076. // end buildHtml
  1077. }
  1078. class JavlibHandler extends Handler {
  1079. get name() {
  1080. return "javlib";
  1081. }
  1082. get condition() {
  1083. return $('head>title:contains("JAVLibrary")');
  1084. }
  1085. handle(condition, keyOrIndex) {
  1086. debug("所有页面", "Javlib");
  1087. debug("删除广告", "Javlib");
  1088. $(".socialmedia,#bottombanner13,#topbanner11,#sidebanner11").remove();
  1089. $("#leftmenu>div>ul:nth-child(2)>li:nth-child(2)").remove();
  1090. debug("调节UI", "Javlib");
  1091. $("#content").css("padding-top", "10px");
  1092. $("#toplogo").css("height", "50px");
  1093. $("#toplogo").find('img[src*="logo-top"]').attr("height", "40");
  1094. debug("添加 粘贴&搜索 按钮", "Javlib");
  1095. const styleMap = {};
  1096. $("#idsearchbutton")[0] && $("#idsearchbutton")[0].computedStyleMap().forEach((value, key) => {
  1097. styleMap[key] = value;
  1098. });
  1099. const $pasteAndSearchButton = $(
  1100. `<input type="button" value="粘贴&搜索" id="pasteAndSearch"></input>`
  1101. );
  1102. $pasteAndSearchButton.css(styleMap);
  1103. $pasteAndSearchButton.on("click", () => {
  1104. navigator.clipboard.readText().then((clipText) => {
  1105. if (clipText != null && $.trim(clipText) != "") {
  1106. $("#idsearchbox").val(clipText);
  1107. $("#idsearchbutton").trigger("click");
  1108. }
  1109. });
  1110. });
  1111. $("#idsearchbutton").parent().append($pasteAndSearchButton);
  1112. debug("添加 打开skrbt 连接", "Javlib");
  1113. $(".advsearch").append(
  1114. `&nbsp;&nbsp;
  1115. <a href="${domainConfig.skrbt.url}"
  1116. target="_blank"
  1117. class="tianteng-search-anchor"
  1118. title="打开后自动搜索剪贴板中的内容">打开skrbt</a>`
  1119. );
  1120. debug("删除url重定向", "Javlib");
  1121. $.each($("a[href^='redirect.php?url']"), function(index, a) {
  1122. var url = getUrlParam(a.href, "url");
  1123. a.href = url;
  1124. if (!a.href.startsWith("https")) {
  1125. a.href = a.href.replace("http", "https");
  1126. }
  1127. a.text = a.text + " " + a.href + " ";
  1128. if (a.href.includes("yimuhe")) {
  1129. $(a).parentsUntil("tr").closest(".t").css("background-color", "#6B6C83");
  1130. a.style = "font-size:20px;";
  1131. } else {
  1132. a.style = "font-size:20px;";
  1133. }
  1134. });
  1135. if (/.*\?v=.*/.test(location.href)) {
  1136. debug("详情页面", "Javlib");
  1137. debug("添加 复制车牌 按钮", "Javlib");
  1138. let chePai = document.querySelector("#video_id > table > tbody > tr > td.text").innerText;
  1139. let toAppendElement = document.querySelector("#video_id > table > tbody > tr > td.text");
  1140. appendCopyButton(chePai, toAppendElement);
  1141. debug("添加 javbus中查询 链接", "Javlib");
  1142. let trTag = document.querySelector("#video_id > table > tbody > tr");
  1143. let javdbQueryId = "javdbQueryId";
  1144. trTag.innerHTML = [
  1145. trTag.innerHTML,
  1146. '<td><a id="',
  1147. javdbQueryId,
  1148. '"href="',
  1149. domainConfig.javbus.url,
  1150. "/",
  1151. chePai,
  1152. '">javbus中查询</a></td>'
  1153. ].join("");
  1154. debug("添加 用SkrBt搜索 链接", "Javlib");
  1155. $(trTag).append(`
  1156. <td>
  1157. <a
  1158. class="tianteng-search-anchor"
  1159. href="${domainConfig.skrbt.url}/search?keyword=${chePai}"
  1160. data-tianteng-keyword="${chePai}">
  1161. SkrBt搜索
  1162. </a>
  1163. </td>
  1164. `);
  1165. $(".tianteng-search-anchor").on("click mouseup", function() {
  1166. const keyword = $(this).data("tiantengKeyword");
  1167. if (keyword) {
  1168. _GM_setValue("tiantengKeyword", keyword);
  1169. }
  1170. });
  1171. debug("删除名称中的链接", "Javlib");
  1172. const videoTitleNode = document.querySelector("#video_title > h3 > a");
  1173. if (videoTitleNode) {
  1174. const videoTitle = videoTitleNode.getInnerHTML();
  1175. videoTitleNode.parentNode.innerText = videoTitle;
  1176. }
  1177. debug("添加磁链tab", "Javlib");
  1178. new MagnetTab(chePai, (fragment) => {
  1179. $("#video_favorite_edit").after(fragment);
  1180. });
  1181. }
  1182. }
  1183. }
  1184. class JavbusHandler extends Handler {
  1185. get name() {
  1186. return "javbus";
  1187. }
  1188. get condition() {
  1189. return {
  1190. a1: $('head>title:contains("JavBus")'),
  1191. // /genre/hd , /genre/sub
  1192. a2: $("body > nav > div > div.navbar-header.mh50 > a > img[alt='JavBus']"),
  1193. // 论坛
  1194. luntan: "#toptb.jav-nav"
  1195. };
  1196. }
  1197. handle(condition, keyOrIndex) {
  1198. debug(`keyOrIndex:${keyOrIndex}`);
  1199. debug("添加 粘贴&搜索 按钮", "javbus");
  1200. const searchButton = $(`button[onclick="searchs('search-input')"]:first`);
  1201. const searchInput = $("#search-input:first");
  1202. addPasteAndSearchButton(searchButton, searchInput);
  1203. $(".nav>li>a").attr("style", "padding-left:8px;padding-right:8px;");
  1204. debug("添加 打开skrbt 链接", "javbus");
  1205. $(".nav-title.nav-inactive:last,ul.nav.navbar-nav:first").append(`
  1206. <li class="hidden-md hidden-sm">
  1207. <a href="${domainConfig.skrbt.url}" target="_blank">打开skrbt</a>
  1208. </li>
  1209. `);
  1210. debug("添加 打开今日新帖 按钮", "javbus");
  1211. let todayNewButton = $(
  1212. `<button id="tiantengNewButton"
  1213. class="jav-button btn btn-default ld-ext-right"
  1214. title="打开老司机福利讨论区的今日新帖,最多30个"
  1215. style="margin-top:7px;">
  1216.  
  1217. <span>打开今日新帖</span>
  1218. <div class="ld ldld bare"
  1219. style="width:1em;height:1em">
  1220. </div>
  1221. </button>`
  1222. );
  1223. _GM_addStyle(_GM_getResourceText("ldloader/index.min.css"));
  1224. _GM_addStyle(_GM_getResourceText("ldbutton/index.min.css"));
  1225. $(".nav-title.nav-inactive:last,ul.nav.navbar-nav:first").append(todayNewButton);
  1226. let loading = new ldloader({ root: "#tiantengNewButton" });
  1227. todayNewButton.on("click", function() {
  1228. if (loading.running) {
  1229. debug("正在加载数据,忽略点击...", "javbus");
  1230. return;
  1231. }
  1232. loading.toggle();
  1233. todayNewButton.attr("disabled", "true");
  1234. const origin = location.origin;
  1235. const talkUrl = `${origin}/forum/forum.php?mod=forumdisplay&fid=2&filter=author&orderby=dateline&dateline=86400`;
  1236. const now = /* @__PURE__ */ new Date();
  1237. const today = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;
  1238. async function getPostData(url, date, pageNum) {
  1239. const r = await _GM.xmlHttpRequest({
  1240. url,
  1241. headers: {
  1242. Accept: `text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7`,
  1243. "Accept-Encoding": "gzip, deflate, br",
  1244. "Accept-Language": "zh-CN,zh;q=0.9",
  1245. "Cache-Control": "max-age=0"
  1246. }
  1247. }).catch((e) => {
  1248. loading.off();
  1249. todayNewButton.attr("disabled", false);
  1250. console.error(e);
  1251. debug(e, "javbus");
  1252. alert("获取数据出现错误!!");
  1253. });
  1254. const data = $(r.responseXML);
  1255. const result = [];
  1256. $(".post_inforight", data).each(function() {
  1257. const date2 = $("span.dateline>span", $(this)).attr("title");
  1258. if (date2 === today) {
  1259. let postUrl = $("a.s", $(this)).attr("href");
  1260. result.push(`${origin}/forum/${postUrl}`);
  1261. }
  1262. });
  1263. return result;
  1264. }
  1265. getPostData(talkUrl).then(function(urlArray) {
  1266. if (urlArray.length === 0) {
  1267. debug("没有新的帖子", "javbus");
  1268. alert("没有新的帖子.");
  1269. }
  1270. $(urlArray).each(function() {
  1271. _GM_openInTab(this, true);
  1272. });
  1273. loading.off();
  1274. todayNewButton.attr("disabled", false);
  1275. });
  1276. });
  1277. let chePaiNode = document.querySelector(
  1278. "body > div.container > div.row.movie > div.col-md-3.info > p:nth-child(1) > span:nth-child(2)"
  1279. );
  1280. if (chePaiNode) {
  1281. debug("添加复制车牌号按钮", "javbus");
  1282. const chePai = chePaiNode.innerText.trim();
  1283. const toAppendElement = document.querySelector(
  1284. "body > div.container > div.row.movie > div.col-md-3.info > p:nth-child(1)"
  1285. );
  1286. appendCopyButton(
  1287. chePai,
  1288. toAppendElement,
  1289. (copyButton) => copyButton.className = "jav-button btn btn-default"
  1290. );
  1291. debug("删除磁力链接中的onclick事件", "javbus");
  1292. setInterval(() => $("#magnet-table td").removeAttr("onclick"), 1e3);
  1293. debug("添加 在javlibrary中打开", "javabus");
  1294. const javLibLink = `<a href="${domainConfig.javlib.url}/cn/vl_searchbyid.php?keyword=${chePai}">在javlib中打开</a>`;
  1295. $(toAppendElement).append(javLibLink);
  1296. new MagnetTab(chePai, (fragment) => {
  1297. $("div.row.movie").after(fragment);
  1298. });
  1299. }
  1300. if (location.href.includes("mod=viewthread")) {
  1301. let toAlienMagnet = function(magnet, alien) {
  1302. alien = alien ? alien : "-";
  1303. let part1 = magnet.slice(0, 21);
  1304. let part2 = magnet.slice(21);
  1305. return `${part1}${alien}${part2}`;
  1306. }, toNormalMagnet = function(magnet, alien) {
  1307. alien = alien ? alien : "-";
  1308. return magnet.replace(alien, "");
  1309. }, getMagnetRegExp = function(alien) {
  1310. if (alien) {
  1311. return new RegExp(
  1312. `(?:magnet:\\?xt=urn:btih:)?(?:(?:[0-9a-f]{1}${alien}[0-9a-f]{39})|(?:[2-7a-zA-Z]${alien}[2-7a-zA-Z]{31}))`,
  1313. "gim"
  1314. );
  1315. } else {
  1316. return /(?:magnet:\?xt=urn:btih:)?(?:[0-9a-fA-F]{40}|[2-7a-zA-Z]{32})/gim;
  1317. }
  1318. }, completeMagnet = function(magnet) {
  1319. if (!magnet) {
  1320. return magnet;
  1321. }
  1322. if (magnet.length === 32 || magnet.length === 40) {
  1323. return `magnet:?xt=urn:btih:${magnet}`;
  1324. }
  1325. return magnet;
  1326. };
  1327. debug("调整样式", "论坛明细页面");
  1328. _GM_addStyle(`
  1329. #p_btn {
  1330. padding:0;
  1331. }
  1332. .mtw {
  1333. margin-top: 0px !important;
  1334. }
  1335. .mbm {
  1336. margin-bottom: 10px !important;
  1337. }
  1338. .pi {
  1339. overflow: hidden;
  1340. margin-bottom: 0;
  1341. padding: 0;
  1342. height: 16px;
  1343. border-bottom: 1px dashed #CDCDCD;
  1344. }
  1345. .pct {
  1346. padding-bottom: 0;
  1347. }
  1348. .t_fsz {
  1349. min-height: auto;
  1350. }
  1351. .nthread_postinfo {
  1352. margin: 0 -16px;
  1353. border-top: 10px solid #f5f5f5;
  1354. padding: 10px 40px;
  1355. }
  1356. .pcb .cm .psth {
  1357. margin-bottom: 0px;
  1358. }
  1359. .pcb .psth {
  1360. width: 100%;
  1361. font-size: 17px !important;
  1362. line-height: 28px;
  1363. font-weight: normal;
  1364. color: #454545;
  1365. background: none;
  1366. border-bottom: 1px solid #CECECE;
  1367. padding: 0;
  1368. margin: 10px 0 0;
  1369. }
  1370. .pstl {
  1371. clear: left;
  1372. padding: 0em 0;
  1373. }
  1374. hin .pob {
  1375. padding-bottom: 0px !important;
  1376. }
  1377. .plc{padding-top:14px}
  1378. `);
  1379. debug("为磁链添加按钮", "论坛明细页面");
  1380. $(document).on("click", 'button[class*="tianteng-button"]', function(e) {
  1381. let button = $(e.target);
  1382. let buttonType = button.data("tiantengButton");
  1383. if (buttonType === "copy") {
  1384. let magnet = button.data("tiantengMagnet");
  1385. _GM.setClipboard(toNormalMagnet(magnet), "text");
  1386. return;
  1387. }
  1388. if (buttonType === "click") {
  1389. let magnet = button.data("tiantengMagnet");
  1390. setTimeout(() => window.open(toNormalMagnet(magnet)), 500);
  1391. return;
  1392. }
  1393. if (buttonType === "copyAll") {
  1394. let postId = button.data("tiantengPostId");
  1395. let magnets = "";
  1396. $(`[data-tianteng-button="copy"]`, $(`#${postId}`)).each(function() {
  1397. let magnet = $(this).data("tiantengMagnet");
  1398. magnets = magnets + toNormalMagnet(magnet) + "\n";
  1399. });
  1400. _GM.setClipboard(magnets, "text");
  1401. return;
  1402. }
  1403. if (buttonType === "clickAll") {
  1404. let postId = button.data("tiantengPostId");
  1405. $(`[data-tianteng-button="copy"]`, $(`#${postId}`)).each(function() {
  1406. let magnet = $(this).data("tiantengMagnet");
  1407. magnet = toNormalMagnet(magnet);
  1408. setTimeout(() => window.open(toNormalMagnet(magnet)), 500);
  1409. });
  1410. return;
  1411. }
  1412. if (buttonType === "copyAllNot") {
  1413. let postId = button.data("tiantengPostMessageId");
  1414. let magnets = "";
  1415. $(`[data-tianteng-button="copy"]`, $(`#${postId}`)).each(function() {
  1416. let magnet = $(this).data("tiantengMagnet");
  1417. magnets = magnets + toNormalMagnet(magnet) + "\n";
  1418. });
  1419. _GM.setClipboard(magnets, "text");
  1420. return;
  1421. }
  1422. if (buttonType === "clickAllNot") {
  1423. let postId = button.data("tiantengPostMessageId");
  1424. $(`[data-tianteng-button="copy"]`, $(`#${postId}`)).each(function() {
  1425. let magnet = $(this).data("tiantengMagnet");
  1426. magnet = toNormalMagnet(magnet);
  1427. setTimeout(() => window.open(toNormalMagnet(magnet)), 500);
  1428. });
  1429. return;
  1430. }
  1431. });
  1432. let magnetRegExp = getMagnetRegExp();
  1433. $(`div[id^="post_"] a[href^="magnet:?xt=urn:btih:"]`).each(function() {
  1434. let magnetAlien = completeMagnet($(this).attr("href"));
  1435. magnetAlien = toAlienMagnet(magnetAlien);
  1436. let html = this.outerHTML.replace(
  1437. magnetRegExp,
  1438. (match, offset, str) => toAlienMagnet(completeMagnet(match), "@")
  1439. );
  1440. html = html.replace("href", `data-tianteng-status="ok" href`);
  1441. html = `${html}
  1442. <button style="margin:0;padding:3px;"
  1443. class="jav-button tianteng-button"
  1444. data-tianteng-button="copy"
  1445. data-tianteng-magnet="${magnetAlien}"
  1446. type="button">复制磁链
  1447. </button>
  1448. <button style="margin:0;padding:3px;"
  1449. class="jav-button tianteng-button"
  1450. data-tianteng-button="click"
  1451. data-tianteng-magnet="${magnetAlien}"
  1452. type="button">打开磁链
  1453. </button>`;
  1454. this.outerHTML = html;
  1455. });
  1456. $('div[id^="post_"]').each(function() {
  1457. const treeWalker = document.createTreeWalker(this, NodeFilter.SHOW_TEXT);
  1458. while (treeWalker.nextNode()) {
  1459. const node = treeWalker.currentNode;
  1460. if (node.nodeValue && magnetRegExp.test(node.nodeValue)) {
  1461. node.nodeValue = node.nodeValue.replace(
  1462. magnetRegExp,
  1463. (match, offset, str) => toAlienMagnet(completeMagnet(match), "tianteng")
  1464. );
  1465. }
  1466. }
  1467. });
  1468. $('div[id^="post_"]').each(function() {
  1469. let magnetAlienRegExp = getMagnetRegExp("tianteng");
  1470. let html = this.innerHTML;
  1471. html = html.replace(magnetAlienRegExp, function(match) {
  1472. match = toNormalMagnet(match, "tianteng");
  1473. let magnetAlien = toAlienMagnet(match);
  1474. return `
  1475. <a href="${match}" data-tianteng-status="ok">${match}</a>
  1476. <button style="margin:0;padding:3px;"
  1477. class="jav-button tianteng-button"
  1478. data-tianteng-button="copy"
  1479. data-tianteng-magnet="${magnetAlien}"
  1480. type="button">复制磁链
  1481. </button>
  1482. <button style="margin:0;padding:3px;"
  1483. class="jav-button tianteng-button"
  1484. data-tianteng-button="click"
  1485. data-tianteng-magnet="${magnetAlien}"
  1486. type="button">打开磁链
  1487. </button>`;
  1488. });
  1489. magnetAlienRegExp = getMagnetRegExp("@");
  1490. html = html.replace(magnetAlienRegExp, function(match) {
  1491. return toNormalMagnet(match, "@");
  1492. });
  1493. this.innerHTML = html;
  1494. const postId = $(this).attr("id");
  1495. const id = postId.replace("post_", "");
  1496. const postMessageId = `postmessage_${id}`;
  1497. if ($(`[data-tianteng-button="copy"]`, $(`#${postId}`)).length > 0) {
  1498. let allButtonHtml = `
  1499. <button style="margin:0;padding:5px;"
  1500. class="jav-button tianteng-button"
  1501. data-tianteng-button="copyAll"
  1502. data-tianteng-post-id="${postId}"
  1503. data-tianteng-post-message-id="${postMessageId}"
  1504. type="button">复制所有磁链
  1505. </button>
  1506. <button style="margin:0;padding:5px;"
  1507. class="jav-button tianteng-button"
  1508. data-tianteng-button="clickAll"
  1509. data-tianteng-post-id="${postId}"
  1510. data-tianteng-post-message-id="${postMessageId}"
  1511. type="button">打开所有磁链
  1512. </button>
  1513. <button style="margin:0;padding:5px;margin-left:10px;"
  1514. class="jav-button tianteng-button"
  1515. data-tianteng-button="copyAllNot"
  1516. data-tianteng-post-id="${postId}"
  1517. data-tianteng-post-message-id="${postMessageId}"
  1518. type="button">复制所有磁链(不含点评)
  1519. </button>
  1520. <button style="margin:0;padding:5px;"
  1521. class="jav-button tianteng-button"
  1522. data-tianteng-button="clickAllNot"
  1523. data-tianteng-post-id="${postId}"
  1524. data-tianteng-post-message-id="${postMessageId}"
  1525. type="button">打开所有磁链(不含点评)
  1526. </button>`;
  1527. $(`#${postMessageId}`).prepend(allButtonHtml + "<br><br>");
  1528. $(`#${postMessageId}`).append("<br><br>" + allButtonHtml);
  1529. }
  1530. });
  1531. }
  1532. }
  1533. }
  1534. class BtsowHandler extends Handler {
  1535. get name() {
  1536. return "BTSOW";
  1537. }
  1538. get condition() {
  1539. return $('head>title:contains("BTSOW")');
  1540. }
  1541. handle(condition, keyOrIndex) {
  1542. function allPages() {
  1543. const form = $("form.fullsearch-form");
  1544. form.each(function() {
  1545. const me = $(this);
  1546. if ($(".tianteng-paste-search", me).length === 0) {
  1547. const searchButton = $(`:submit`, me);
  1548. const pasteAndSearchButton = $(`
  1549. <button type="button" class="btn btn-default tianteng-paste-search">
  1550. 粘贴&搜索
  1551. </button>`);
  1552. searchButton.after(pasteAndSearchButton);
  1553. }
  1554. });
  1555. }
  1556. function searchPage() {
  1557. if (location.pathname.startsWith("/search")) {
  1558. debug("添加 复制磁链,打开磁链 按钮", "btsow-搜索结果列表");
  1559. let buttonsHtml = `
  1560. <button class="btn btn-danger copy" type="button">复制磁链</button>
  1561. <button class="btn btn-danger click" type="button">打开磁链</button>`;
  1562. $("div.data-list>div.row>a>div.file").each((index, el) => {
  1563. if ($(el).find("button.copy").length === 0) {
  1564. $(el).append(buttonsHtml);
  1565. }
  1566. });
  1567. }
  1568. }
  1569. debug("添加 粘贴&搜索 按钮", "btsow-所有页面");
  1570. allPages();
  1571. $(document).on("click", "button.tianteng-paste-search", function(e) {
  1572. const me = $(this);
  1573. navigator.clipboard.readText().then((text) => {
  1574. if (text != null && $.trim(text) != "") {
  1575. me.parent().prev().val($.trim(text));
  1576. me.parentsUntil(".container")[2].submit();
  1577. }
  1578. });
  1579. e.preventDefault();
  1580. e.stopImmediatePropagation();
  1581. e.stopPropagation();
  1582. return false;
  1583. });
  1584. searchPage();
  1585. if (location.pathname.startsWith("/search")) {
  1586. debug("添加 复制磁链,打开磁链 按钮", "btsow-搜索结果列表");
  1587. $(document).on("click", "button.copy, button.click", function(e) {
  1588. let magnet = $(this).parent().parent().attr("href").split("/")[6];
  1589. magnet = `magnet:?xt=urn:btih:${magnet}`;
  1590. if ($(this).attr("class").includes("copy")) {
  1591. _GM_setClipboard(magnet, "text");
  1592. } else if ($(this).attr("class").includes("click")) {
  1593. _GM_openInTab(magnet);
  1594. }
  1595. e.preventDefault();
  1596. e.stopImmediatePropagation();
  1597. e.stopPropagation();
  1598. });
  1599. }
  1600. const nodeToObserve = document.querySelector("body");
  1601. new MutationObserver((mutationRecords, observer) => {
  1602. allPages();
  1603. searchPage();
  1604. }).observe(nodeToObserve, { childList: true });
  1605. }
  1606. }
  1607. class SkrbtHandler extends Handler {
  1608. get name() {
  1609. return "skrbt";
  1610. }
  1611. get condition() {
  1612. return $(`head>link[rel='shortcut icon'][href*='skrbt']`);
  1613. }
  1614. handle(condition, keyOrIndex) {
  1615. debug("添加 粘贴&搜索 按钮", "skrbt");
  1616. const $searchButton = $("button.search-btn");
  1617. const $searchInput = $(`input.search-input[name='keyword']`);
  1618. const $pasteAndSearchButton = addPasteAndSearchButton($searchButton, $searchInput);
  1619. $pasteAndSearchButton.removeAttr("style");
  1620. $pasteAndSearchButton.css("margin-left", "3px");
  1621. $pasteAndSearchButton.attr("class", $searchButton.attr("class"));
  1622. if (location.pathname === "/") {
  1623. const keyword = _GM_getValue("tiantengKeyword", null);
  1624. if (keyword) {
  1625. debug("搜索存储的内容", "skrbt-首页");
  1626. _GM_deleteValue("tiantengKeyword");
  1627. $searchInput.val(keyword);
  1628. $searchButton.click();
  1629. } else {
  1630. debug("搜索剪贴板中的内容", "skrbt-首页");
  1631. $pasteAndSearchButton.click();
  1632. }
  1633. }
  1634. debug("删除广告", "skrbt");
  1635. function removeAd() {
  1636. const $container = $(".col-md-6:eq(2)");
  1637. $container.remove(".label.label-primary");
  1638. $container.find('a.rrt.common-link[href^="http"]').parent().parent().remove();
  1639. }
  1640. removeAd();
  1641. if (location.href.includes("search")) {
  1642. debug("添加 复制磁链和打开磁链 按钮", "skrbt-搜索结果列表页面");
  1643. let buttonsHtml = `
  1644. <span class="rrmiv"><button class="btn btn-danger tianteng-button-copy" type="button">复制磁链</button></span>
  1645. <span class="rrmiv"><button class="btn btn-danger tianteng-button-click" type="button">打开磁链</button></span>`;
  1646. addButtonsForSkrbt(buttonsHtml, $(".col-md-6:eq(2)"), (el) => {
  1647. const classValue = $(el).attr("class");
  1648. if (classValue && classValue.includes("tianteng-button-copy")) {
  1649. return "copy";
  1650. }
  1651. if (classValue && classValue.includes("tianteng-button-click")) {
  1652. return "click";
  1653. }
  1654. return "other";
  1655. });
  1656. const nodeToObserve = document.querySelectorAll(".col-md-6")[2];
  1657. new MutationObserver((mutationRecords, observer) => {
  1658. $("a.rrt.common-link").each((index, el) => {
  1659. if ($(el).parent().find(".btn.btn-danger.tianteng-button-copy").length === 0) {
  1660. $(el).after(buttonsHtml);
  1661. }
  1662. });
  1663. removeAd();
  1664. }).observe(nodeToObserve, { childList: true });
  1665. }
  1666. }
  1667. }
  1668. function addButtonsForSkrbt(buttonsHtml, delegateElement, buttonTypeCallback) {
  1669. delegateElement.find("a.rrt.common-link").after(buttonsHtml);
  1670. delegateElement.on("click", '[class*="tianteng-button"]', (event) => {
  1671. const buttonType = buttonTypeCallback(event.target);
  1672. if ("copy" !== buttonType && "click" !== buttonType) {
  1673. return;
  1674. }
  1675. let liNode = $(event.target).parent().parent();
  1676. const exeButtonClick = (e) => {
  1677. if ("copy" === buttonType) {
  1678. navigator.clipboard.writeText(liNode.find(".magnet").attr("href"));
  1679. } else {
  1680. _GM_openInTab(liNode.find(".magnet").attr("href"));
  1681. }
  1682. e.preventDefault();
  1683. e.stopImmediatePropagation();
  1684. e.stopPropagation();
  1685. return false;
  1686. };
  1687. if (liNode.find(".magnet").length != 0) {
  1688. return exeButtonClick(event);
  1689. }
  1690. let detailUrl = liNode.find("a.rrt.common-link").attr("href");
  1691. detailUrl = `${location.origin}${detailUrl}`;
  1692. $.get(detailUrl, function(data, textStatus, jqXHR) {
  1693. liNode.find("#errorTip").remove();
  1694. const magnet = $(data).find("#magnet").attr("href");
  1695. if (magnet) {
  1696. const aHtml = '<a class="magnet" href="' + magnet + '">' + magnet + "</a>";
  1697. liNode.append(aHtml);
  1698. return exeButtonClick(event);
  1699. } else {
  1700. liNode.append(
  1701. '<span id="errorTip">1.获取磁链失败,等会儿再试一试! 若仍然有问题请刷新网页.</span>'
  1702. );
  1703. event.preventDefault();
  1704. event.stopImmediatePropagation();
  1705. event.stopPropagation();
  1706. return false;
  1707. }
  1708. }).fail(function(e) {
  1709. liNode.append(
  1710. '<span id="errorTip">2.获取磁链失败,等会儿再试一试! 若仍然有问题请刷新网页.</span>'
  1711. );
  1712. event.preventDefault();
  1713. event.stopImmediatePropagation();
  1714. event.stopPropagation();
  1715. console.log(e);
  1716. return false;
  1717. });
  1718. });
  1719. }
  1720. class JinManTianTangHandler extends Handler {
  1721. get name() {
  1722. return "禁漫天堂";
  1723. }
  1724. get condition() {
  1725. return $(`head>title`)[0] && $(`head>title`)[0].text.endsWith("禁漫天堂");
  1726. }
  1727. handle(condition, keyOrIndex) {
  1728. observe(document, { childList: true, subtree: true }, () => {
  1729. debug(" 删除广告", "禁漫天堂");
  1730. $(".top-nav, .div-bf-pv").remove();
  1731. $("#Comic_Top_Nav").css("top", "-1px");
  1732. $("div.e8c78e-4_b").remove();
  1733. if (location.pathname === "/albums") {
  1734. const childNodes = document.querySelector("#wrapper > div.container").childNodes;
  1735. var forEach = Array.prototype.forEach;
  1736. forEach.call(childNodes, function(node) {
  1737. if (node.nodeName === "#text" && node.nodeValue.includes("中間廣告")) {
  1738. node.nodeValue = "";
  1739. }
  1740. });
  1741. }
  1742. });
  1743. }
  1744. }
  1745. debug(document.querySelector("title"));
  1746. interceptEventListener((target, type, callback, options) => {
  1747. if (target.className && target.className.includes && target.className.includes("apo")) {
  1748. debug("禁止点击广告", "松鼠症倉庫");
  1749. return true;
  1750. }
  1751. });
  1752. $(() => {
  1753. const handlerList = [
  1754. BaiduHandler,
  1755. OsChinaHandler,
  1756. GiteeHandler,
  1757. ZhihuHandler,
  1758. WnacgHandler,
  1759. JavlibHandler,
  1760. JavbusHandler,
  1761. BtsowHandler,
  1762. SkrbtHandler,
  1763. JinManTianTangHandler
  1764. ];
  1765. const executor = new HandlerExecutor();
  1766. for (const handler of handlerList) {
  1767. const instance = new handler();
  1768. const className = instance.constructor.name;
  1769. executor.handler = instance;
  1770. const result = executor.execute();
  1771. const resultJson = JSON.stringify(result);
  1772. debug(`执行 ${instance.name}(${className}), result: ${resultJson}`, "main");
  1773. }
  1774. });
  1775.  
  1776. })(jQuery, Tabby, ldloader);