离线磁链一键下载

在磁力搜索列表中直接提取磁链,并在旁显示离线下载按钮。点击按钮后,如果当前页面不在目标离线服务页面,则保存磁链并打开目标离线页面;若已在目标页面,则自动调用离线下载操作(offFunc)。

  1. // ==UserScript==
  2. // @name 离线磁链一键下载
  3. // @namespace https://example.com
  4. // @version 1.2
  5. // @description 在磁力搜索列表中直接提取磁链,并在旁显示离线下载按钮。点击按钮后,如果当前页面不在目标离线服务页面,则保存磁链并打开目标离线页面;若已在目标页面,则自动调用离线下载操作(offFunc)。
  6. // @author YourName
  7. // @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js
  8. // @grant GM_xmlhttpRequest
  9. // @grant GM_openInTab
  10. // @grant GM_notification
  11. // @grant GM_setClipboard
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // @run-at document-end
  15. // @match *://*/*
  16. // @exclude http://www.toodledo.com/tasks/*
  17. // @exclude *://*.google.*/*
  18. // @exclude *://mega.*/*
  19. // @exclude *://*.mega.*/*
  20. // @exclude *://*.youku.com/v_*
  21. // @exclude *://*pan.baidu.com
  22. // @exclude *://*.iqiyi.com/v_*
  23. // @exclude *://*.iqiyi.com/w_*
  24. // @exclude *://*.iqiyi.com/a_*
  25. // @exclude *://*.le.com/ptv/vplay/*
  26. // @exclude *://v.qq.com/x/cover/*
  27. // @exclude *://v.qq.com/x/page/*
  28. // @exclude *://v.qq.com/tv/*
  29. // @exclude *://*.tudou.com/listplay/*
  30. // @exclude *://*.tudou.com/albumplay/*
  31. // @exclude *://*.tudou.com/programs/view/*
  32. // @exclude *://*.mgtv.com/b/*
  33. // @exclude *://film.sohu.com/album/*
  34. // @exclude *://tv.sohu.com/v/*
  35. // @exclude *://*.bilibili.com/video/*
  36. // @exclude *://*.bilibili.com/bangumi/play/*
  37. // @exclude *://*.baofeng.com/play/*
  38. // @exclude *://vip.pptv.com/show/*
  39. // @exclude *://v.pptv.com/show/*
  40. // @exclude *://www.le.com/ptv/vplay/*
  41. // @exclude *://www.wasu.cn/Play/show/*
  42. // @exclude *://m.v.qq.com/x/cover/*
  43. // @exclude *://m.v.qq.com/x/page/*
  44. // @exclude *://m.v.qq.com/*
  45. // @exclude *://m.iqiyi.com/*
  46. // @exclude *://m.iqiyi.com/kszt/*
  47. // @exclude *://m.youku.com/alipay_video/*
  48. // @exclude *://m.mgtv.com/b/*
  49. // @exclude *://m.tv.sohu.com/v/*
  50. // @exclude *://m.film.sohu.com/album/*
  51. // @exclude *://m.le.com/ptv/vplay/*
  52. // @exclude *://m.pptv.com/show/*
  53. // @exclude *://m.acfun.cn/v/*
  54. // @exclude *://m.bilibili.com/video/*
  55. // @exclude *://m.bilibili.com/anime/*
  56. // @exclude *://m.bilibili.com/bangumi/play/*
  57. // @exclude *://m.wasu.cn/Play/show/*
  58. // @exclude *://www.youtube.com
  59. // @exclude *://www.youtube.com/
  60. // @exclude *://www.youtube.com/watch*
  61. // @license MIT
  62. // ==/UserScript==
  63.  
  64. (function(){
  65. 'use strict';
  66.  
  67. // 存储兼容:如无 GM_getValue/GM_setValue 则使用 localStorage
  68. var storage = {
  69. getItem: function(key, cb){
  70. if(typeof GM_getValue === "function"){
  71. cb(GM_getValue(key));
  72. } else {
  73. cb(localStorage.getItem(key));
  74. }
  75. },
  76. setItem: function(key, val){
  77. if(typeof GM_setValue === "function"){
  78. GM_setValue(key, val);
  79. } else {
  80. localStorage.setItem(key, val);
  81. }
  82. },
  83. delItem: function(key){
  84. if(typeof GM_setValue === "function"){
  85. GM_setValue(key, "");
  86. } else {
  87. localStorage.removeItem(key);
  88. }
  89. }
  90. };
  91.  
  92. // _unsafeWindow 兼容
  93. var _unsafeWindow = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
  94.  
  95. // 全局变量存储当前磁链
  96. window.curlink = "";
  97.  
  98. // ----------【第一部分】扫描页面并提取磁链,添加离线下载按钮----------
  99. $(document).ready(function(){
  100. $('a').each(function(){
  101. var $a = $(this);
  102. var href = $a.attr('href');
  103. if(!href) return;
  104. // 避免重复添加
  105. if($a.find('.offline-btn').length > 0) return;
  106.  
  107. if(/^magnet:\?xt=urn:btih:/i.test(href)){
  108. appendOfflineButton($a, href);
  109. } else {
  110. var hash = null;
  111. var reg1 = /(?:^|\/|&|-|\.|\?|=|:)([a-fA-F0-9]{40})/;
  112. var reg2 = /\/([a-zA-Z2-7]{32})$/;
  113. if(reg1.test(href)){
  114. hash = href.match(reg1)[1];
  115. } else if(reg2.test(href)){
  116. hash = reg2.exec(href)[1];
  117. hash = base32To16(hash).toUpperCase();
  118. }
  119. if(hash){
  120. var magnetLink = 'magnet:?xt=urn:btih:' + hash;
  121. appendOfflineButton($a, magnetLink);
  122. } else {
  123. // 对于链接中未直接显示磁链的情况,尝试加载二级页面异步提取
  124. if(typeof GM_xmlhttpRequest !== 'undefined'){
  125. GM_xmlhttpRequest({
  126. method: 'GET',
  127. url: href,
  128. onload: function(response) {
  129. if(response.status === 200){
  130. var htmlTxt = response.responseText;
  131. var m = htmlTxt.match(/href="(magnet:\?xt=urn:btih:[^"]{40,})/i);
  132. if(m && m[1]){
  133. appendOfflineButton($a, m[1]);
  134. } else {
  135. console.log(href + ' 无磁力链接');
  136. }
  137. }
  138. },
  139. onerror: function(err) {
  140. console.log('请求失败:' + href);
  141. }
  142. });
  143. }
  144. }
  145. }
  146. });
  147. });
  148.  
  149. // 添加离线按钮(样式参考第二脚本)
  150. function appendOfflineButton($anchor, magnetLink) {
  151. var btn = $('<a class="whx-a offline-btn" title="一键离线下载\n' + magnetLink + '" target="_blank"></a>');
  152. btn.css({
  153. 'display': 'inline-block',
  154. 'margin-left': '5px',
  155. 'background-size': '20px',
  156. 'border-radius': '50%',
  157. 'border': '0',
  158. 'vertical-align': 'middle',
  159. 'outline': 'none',
  160. 'padding': '0',
  161. 'height': '26px',
  162. 'width': '26px',
  163. 'cursor': 'pointer',
  164. 'background-position': 'center',
  165. 'background-repeat': 'no-repeat',
  166. 'background-color': '#f2f2f2'
  167. });
  168. var downIconBg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAAARVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc6ur3AAAAFnRSTlMAYM5vMOA/ENGegK2olI6G1b97Z0sXENA+jAAAAKFJREFUKM+FklkSxCAIRHFfss3K/Y86iQSDVqzpH7FfgQpCVfAmGx+gl9JI0qrxrcNLzooEbKUG4EKWdkCiDRV0N0RTrZ5wvdgTTgp4SzCAHxAPZkAM5GOJWuuT7FE5OVPOBFLTYb3Oc2YB5uJ8+G6pgkTGt74ntcCJHiwFLHw10Tdc93jlGXGvSRtsHNpuPs+/o1ODfxAtSL0f7HPC+L/9AF60G3QxO1UaAAAAAElFTkSuQmCC";
  169. btn.css('background-image', 'url("' + downIconBg + '")');
  170. // 点击按钮时,将磁链赋给全局 curlink,并调用 showDiskIcons 显示离线服务选择面板
  171. btn.on('click', function(e){
  172. e.preventDefault();
  173. e.stopPropagation();
  174. window.curlink = magnetLink;
  175. var offset = btn.offset();
  176. showDiskIcons(magnetLink, offset.top, offset.left);
  177. });
  178. $anchor.append(btn);
  179. }
  180.  
  181. // base32转16进制函数
  182. function base32To16(str){
  183. if(str.length % 8 !== 0 || /[0189]/.test(str)){
  184. return str;
  185. }
  186. str = str.toUpperCase();
  187. var bin = "", newStr = "", i;
  188. for(i = 0; i < str.length; i++){
  189. var charCode = str.charCodeAt(i);
  190. if(charCode < 65) charCode -= 24;
  191. else charCode -= 65;
  192. charCode = '0000' + charCode.toString(2);
  193. charCode = charCode.substr(charCode.length - 5);
  194. bin += charCode;
  195. }
  196. for(i = 0; i < bin.length; i += 4){
  197. newStr += parseInt(bin.substring(i, i+4), 2).toString(16);
  198. }
  199. return newStr;
  200. }
  201.  
  202. // ----------【第二部分】离线下载面板及服务调用----------
  203. // 添加离线下载面板容器
  204. var parentDiv = $("<div id='offlinePanel' style='display:none;position:absolute;z-index:9999999;overflow:visible;text-align:left;'></div>");
  205. $("body").append(parentDiv);
  206.  
  207. $("<style>").prop("type", "text/css").html(`
  208. a.whx-a,a.whx-a-node{
  209. display:inline-block;
  210. margin-left:5px;
  211. background-size:20px!important;
  212. border-radius:50%;
  213. border:0!important;
  214. vertical-align:middle;
  215. transition:margin-top 0.25s ease;
  216. outline:none!important;
  217. padding:0!important;
  218. height:26px!important;
  219. width:26px!important;
  220. cursor: pointer;
  221. background-position:center!important;
  222. background-repeat:no-repeat!important;
  223. }
  224. `).appendTo("head");
  225.  
  226. // 离线服务配置:包含 regex、url、offFunc、bgColor 和 bgImg
  227. var services = [
  228. {
  229. name: "百度网盘",
  230. regex: /pan\.baidu\.com/,
  231. url: "https://pan.baidu.com/disk/home",
  232. offFunc: function(delLink){
  233. var gsi = setInterval(function() {
  234. var newOffBtn = document.querySelector('[data-id=downloadLink]');
  235. if(newOffBtn){
  236. clearInterval(gsi);
  237. newOffBtn.click();
  238. var bsl = setInterval(function() {
  239. newOffBtn.click();
  240. var offLink = document.querySelector('div.nd-download-link div[role=dialog] input');
  241. if(offLink){
  242. clearInterval(bsl);
  243. var beginOffline = function(){
  244. if(curlink.length === 0) return;
  245. offLink = document.querySelector('div.nd-download-link div[role=dialog] input');
  246. if(Object.prototype.toString.call(curlink) === '[object Array]')
  247. offLink.value = curlink.shift();
  248. else{
  249. offLink.value = curlink;
  250. curlink = "";
  251. }
  252. var event = document.createEvent('HTMLEvents');
  253. event.initEvent("input", false, true);
  254. offLink.dispatchEvent(event);
  255. delLink();
  256. var baiduPathStr, isBt = /^magnet|torrent$/.test(offLink.value);
  257. storage.getItem("baiduPath", function(v){
  258. baiduPathStr = v;
  259. if(baiduPathStr){
  260. _unsafeWindow.require("function-widget-1:offlineDownload/util/newOfflineDialog.js").obtain()._checkPath = baiduPathStr;
  261. }
  262. });
  263. $("div.nd-download-link div[role=dialog]").find("button.nd-download-link__action>span:contains('确定')").click();
  264. if(isBt){
  265. var i = 0, bsb = setInterval(function(){
  266. var btList = document.querySelector('div[aria-label="链接任务"]');
  267. if(btList && !$(btList).is(":hidden")){
  268. clearInterval(bsb);
  269. if($(".nd-remote-download__list-select>span").html() == "全选")
  270. $(".nd-remote-download__file-list .u-checkbox__original")[0].click();
  271. btList.querySelectorAll('button.nd-remote-download__save-btn')[0].click();
  272. } else if(++i > 50){
  273. clearInterval(bsb);
  274. }
  275. }, 200);
  276. }
  277. };
  278. setTimeout(beginOffline, 500);
  279. }
  280. }, 500);
  281. }
  282. }, 500);
  283. },
  284. bgColor: "ffffff",
  285. bgImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAABjFBMVEX////7+/v+/v/8/Pwyf/wzc/w0bvza5f4xffz5+//0+P8ybPz8/f4yevw0cPwza/z39/cwe/UxdfzSPyr4+v/2+f/m7/53nv0vf/wvce9pof1tlPwxf/gzfPYwePPp8f7Z5/7S4v7P4P7L3f7I2f2Gtf2Rr/1hkP0yd/1FiPwygfxAdPxspftYkvUtc/Dg6f7C2f7F1f54oP1flf0/hfwsbu7i7f/w9f7b5v7X5f7V4v6nyv6oxv6jwP6Ns/2Lsf1/rv1+ov1zof1xof10nf1jm/1djP0xe/2NufxalvxHj/xPhvxKgPxHffw+efw0ePyXu/mqxPg5hfiTtvdyo/dgmfdOj/dBhfVflfQvefT+9fOIqvMyefNMhvFIgO9MeePyycVjZbzKb3DaZVa/Q0Dx9f+Bp/1olv1gkPw0dvzg6Pu2zPk0gflNjPctc/c9gfX88/JJfO3n3+ni2unHxuSGktNpdtBJY8paashRW71nXqp7YpyDYJKpaIKPU33AVFXARkTVTTvFQjrUPypKwHq1AAACAklEQVQ4y4WTB3OqQBSFF3BpAk+KIBixJ2rs0fTee68vvbzee+9//O1Cio46npmFPfd8d2cY9gIASMJHUESDKFQmAZJAUKCFKELA/WSr3A3d/tZnAF99C8fVHYhiosbxxflsdr7I15SIWiCe3exA2szGmwOJXTkUkvHaTTQD9NyBLO/t7OzJ8kFObwKs2/bRdrSvL7p9ZNvrjQC/n8/nwngXzuXz+3wDED42zS13u2Wax+EGQD+pmhvudsOsnuj1gBAZSp5+/XRIYkMeVu1XyaGIcAfoycVM4Pn3qx9vcW3gRUcmE8gsJvUboNfyeDyBwLd/6sX7wtNnC45DD6vXBbRx1sOmrQ+/VFX9efomhFzFstLoNa45QKzCijMx/vXZpar+/fKSZecWijwfmxHZSgzFFBgWxXQUIJ39UX9/nhPFngHsomlRHEYxRY6mlCkOl+5fXp2vraV6IgCLm1JSoyQGxhRlUnCAi/PUEwXnWMKkooxhAIxAuNSPS+8+Qgi7GOB3zutfgnAExQSIr0JoMJw2GJSghPLSo4eDGscYEK7Gna/gy7QkLRvTK5JEP2bAgy4vvTJtLCNX5h0AMLNemvbihfqBv3zjZpHDACKM7ntI3RMFgFSYcJ3B3P0sf6kzGOxM+AFwXAK7kuNurz2pcWTt7deuna/t4LQdvbbD23b8/wPY0UTO99dD5gAAAABJRU5ErkJggg=="
  286. },
  287. {
  288. name: "115网盘",
  289. regex: /115\.com/,
  290. url: "http://115.com/?tab=offline&mode=wangpan",
  291. offFunc: function(delLink){
  292. var rsc = setInterval(function(){
  293. if(document.readyState === 'complete'){
  294. clearInterval(rsc);
  295. setTimeout(function(){
  296. _unsafeWindow.Core.OFFL5Plug.OpenLink();
  297. setTimeout(function(){
  298. $('#js_offline_new_add').val(curlink);
  299. delLink();
  300. document.querySelector('[data-btn=start]').click();
  301. }, 1);
  302. }, 500);
  303. }
  304. }, 300);
  305. },
  306. bgColor: "21458a",
  307. bgImg:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAASFBMVEUhRYr///+XqcjV3OmJnMFTb6QoS45PbKLu8fbZ4OvBy95xiLRifKxbdqlXcqYxU5P3+Prh5u/O1uXH0eK6xduks89/lLtGZJ4ysMfhAAAAVUlEQVQY04WPSQ6AMAwD6ySkdKHs8P+fckyDhPBtRoojhyG4GP6FEjPvxhGZiKKJPM7uoAHYSif0Lgdw+tppQfOGIF4ILsea3CetvMa+UaRq+Mh7/gPkxAHFh9WDUQAAAABJRU5ErkJggg=="
  308. }
  309. ];
  310.  
  311. // showDiskIcons:显示离线面板并根据服务进行处理
  312. window.showDiskIcons = function(url, top, left){
  313. parentDiv.empty();
  314. services.forEach(function(service){
  315. var btn = $("<a></a>").addClass("whx-a").attr("title", service.name).attr("target", "_blank");
  316. btn.css({
  317. "background-color": "#" + service.bgColor,
  318. "background-image": service.bgImg ? 'url("' + service.bgImg + '")' : '',
  319. "display": "block",
  320. "margin": "5px 0"
  321. });
  322. btn.on("click", function(e){
  323. e.preventDefault();
  324. e.stopPropagation();
  325. // 如果当前域名匹配服务的 regex,则直接调用 offFunc
  326. if(service.regex.test(location.hostname)){
  327. if(service.offFunc && typeof service.offFunc === 'function'){
  328. service.offFunc(function(){
  329. parentDiv.hide();
  330. });
  331. }
  332. } else {
  333. // 不在目标离线页面,则存储磁链并打开目标页面
  334. storage.setItem(service.name + ":eoUrl", curlink);
  335. GM_openInTab(service.url, true);
  336. parentDiv.hide();
  337. }
  338. });
  339. parentDiv.append(btn);
  340. });
  341. parentDiv.css({top: top + 30, left: left});
  342. parentDiv.show();
  343. $(document).on("click.offlinePanel", function(e){
  344. if(!$(e.target).closest("#offlinePanel").length){
  345. parentDiv.hide();
  346. $(document).off("click.offlinePanel");
  347. }
  348. });
  349. };
  350.  
  351. // 如果当前页面属于某离线服务(例如百度或115),则自动读取存储中的链接并执行 offFunc
  352. services.forEach(function(service){
  353. if(service.regex.test(location.hostname)){
  354. storage.getItem(service.name + ":eoUrl", function(v){
  355. if(v){
  356. window.curlink = v;
  357. if(service.offFunc && typeof service.offFunc === 'function'){
  358. service.offFunc(function(){
  359. storage.delItem(service.name + ":eoUrl");
  360. });
  361. }
  362. }
  363. });
  364. }
  365. });
  366.  
  367. })();

QingJ © 2025

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