// ==UserScript== // ==UserScript== // @name 115优化大师 // @author zxf10608 // @version 3.4 // @icon https://115.com/favicon.ico // @namespace https://greasyfork.org/zh-CN/scripts/408466 // @description 115网盘升级登录,延长登录有效期、一键离线下载、调用Dplayer或Potplayer播放视频、文件快捷下载等。 // @require https://cdn.bootcss.com/jquery/3.5.1/jquery.min.js // @require https://greasyfork.org/scripts/398240-gm-config-zh-cn/code/GM_config_zh-CN.js // @require https://greasyfork.org/scripts/412267-base64-v1-0/code/base64_v10.js // @require https://openuserjs.org/src/libs/zxf10608/fec115.js // @require https://openuserjs.org/src/libs/zxf10608/js-xxhash.js // @require https://openuserjs.org/src/libs/zxf10608/elliptic.js // @require https://cdn.jsdelivr.net/npm/toastr@2.1.4/toastr.min.js // @resource toastrCss https://cdn.jsdelivr.net/npm/toastr@2.1.4/build/toastr.min.css // @require https://cdn.bootcdn.net/ajax/libs/crc-32/1.2.0/crc32.min.js // @require https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.16.0/js/md5.min.js // @require https://cdn.bootcdn.net/ajax/libs/aes-js/3.1.2/index.min.js // @require https://cdn.bootcdn.net/ajax/libs/jsSHA/2.4.2/sha1.js // @require https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.js // @resource dplayerCss https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.css // @require https://cdn.jsdelivr.net/npm/hls.js@0.14.15/dist/hls.min.js // @require https://cdn.jsdelivr.net/npm/lz4@0.6.4/build/lz4.min.js // @require https://cdn.jsdelivr.net/npm/js-md4@0.3.2/src/md4.min.js // @require https://cdn.jsdelivr.net/npm/compare-versions@3.6.0/index.js // @include * // @exclude http*://*.baidu.com/* // @exclude http*://*.jb51.* // @exclude http*://*.iqiyi.com/* // @exclude http*://*.qq.com/* // @exclude http*://v.youku.com/* // @exclude http*://*.bilibili.com/ // @exclude http*://*.pptv.com/* // @exclude http*://*.fun.tv/* // @exclude http*://*.sohu.com/* // @exclude http*://*.le.com/* // @exclude http*://*.tudou.com/* // @exclude http*://www.bilibili.com/* // @exclude http*://music.163.com/* // @exclude http*://github.com/* // @exclude http*://www.sojson.com/* // @grant GM_log // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant GM_openInTab // @grant GM_setClipboard // @grant GM_getResourceText // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @connect 115.com // @grant unsafeWindow // @grant window.open // @grant window.close // @run-at document-start // @compatible chrome // @license GPL License // @downloadURL none // ==/UserScript== (function() { 'use strict'; var newVersion = 'v3.4'; if ( typeof GM_config == 'undefined') { alert('115优化大师:\n网络异常,相关库文件加载失败,脚本无法使用,请刷新网页重新加载!'); return; } else { console.log('115优化大师:相关库文件加载成功!'); }; function config(){ var windowCss = '#Cfg .config_var {margin-left: 10%;margin-right: 10%;} #Cfg input[type="checkbox"] {margin: 3px 3px 3px 0px;} #Cfg input[type="text"] {width: 53px;} #Cfg {background-color: lightblue;} #Cfg .reset_holder {float: left; position: relative; bottom: -1em;} #Cfg .saveclose_buttons {margin: .7em;} #Cfg .section_desc {font-size: 10pt;}'; GM_registerMenuCommand('设置', opencfg); function opencfg(){ GM_config.open(); }; GM_config.init( { id: 'Cfg', title: GM_config.create('a', { href: 'https://greasyfork.org/zh-CN/scripts/408466', target: '_blank', textContent: '115优化大师', title: '作者:zxf10608 版本:'+newVersion+' 点击访问主页' }), isTabs: true, skin: 'tab', css: windowCss, frameStyle: { height: '430px', width: '425px', zIndex:'2147483648', }, fields: { account_Login: { section: ['登录管理', '升级登录,延长登录有效期'], label: '升级帐号登录', labelPos: 'right', type: 'checkbox', default: true, }, hide_qrcodeLogin: { label: '隐藏二维码登录', labelPos: 'right', type: 'checkbox', default: false, }, hide_officeLogin: { label: '隐藏115组织登录', labelPos: 'right', type: 'checkbox', default: false, }, login_Alidity: { label: '登录有效期', labelPos: 'left', type: 'select', options: ['1天', '7天', '30天'], default: '7天', }, show_Alidity: { label: '显示登录有效截止时间', labelPos: 'right', type: 'checkbox', default: false, }, reminder: { label: '温馨提示', labelPos: 'right', type: 'button', click: function() { alert('1、升级账号登录,方可设置登录有效期。\n2、常用帐号登录,建议关闭“两步验证”,效果更佳。'); } }, offline_Down: { section: ['离线升级', '升级离线下载功能'], label: '启用一键离线下载', labelPos: 'right', type: 'checkbox', default: true, }, offline_result: { label: '任务添加后显示离线结果', labelPos: 'right', type: 'checkbox', default: true, }, open_List: { label: '离线后自动打开任务列表', labelPos: 'right', type: 'checkbox', default: false, }, open_search: { label: '离线成功后开启视频搜索', labelPos: 'right', type: 'checkbox', default: true, line: 'start', }, search_result: { label: '显示视频搜索结果', labelPos: 'right', type: 'checkbox', default: true, }, open_Popup: { label: '搜到视频自动播放', labelPos: 'right', type: 'checkbox', default: false, line: 'end', }, fuzzy_find: { label: '启用下载地址模糊匹配', labelPos: 'right', type: 'checkbox', default: false, }, reminder2: { label: '温馨提示', labelPos: 'right', type: 'button', click: function() { alert('1、显示离线下载结果有10s延时,用于服务器响应时间。\n2、为避免通知弹窗过多,最多只显示3个视频搜索结果,更多请自行到115查看。\n3、“开启下载地址模糊匹配”后,能根据哈希值或纯文本模糊匹配磁力链接和迅雷专用链,如在磁力搜索引擎、资源网等有奇效,但在某些网页有一定几率误识别,请谨慎开启。'); } }, player: { section: ['播放优化', '调用第三方播放器,优化播放体验'], label: '默认播放器', labelPos: 'left', type: 'select', options: ['Dplayer', 'Potplayer', '官方HTML5'], default: 'Dplayer', }, play_Quality: { label: '默认播放清晰度', labelPos: 'left', type: 'select', 'options': ['最高', '次高', '最低'], default: '次高', }, play_Number: { label: '保存播放进度', labelPos: 'left', type: 'select', 'options': ['0条', '20条', '50条'], default: '20条', }, skip_titles: { label: '跳过片头秒数', type: 'unsigned int', default: '0', }, skip_credits: { label: '跳过片尾秒数', type: 'unsigned int', default: '0', }, Tab_ing: { label: '播放器跟随页面变化', labelPos: 'right', type: 'checkbox', default: false, }, reminder3: { label: '温馨提示', labelPos: 'right', type: 'button', click: function() { alert('1、除第一、第二项外,其他仅在启用Dplayer时有效。\n2、保存播放进度设为0条,可关闭记忆播放或清空播放进度。\n3、播放界面右键可显示更多菜单,谨慎使用“删除”操作。\n4、播放器跟随页面变化,即页面后台则暂停,页面前台则播放,支持Dplayer和官方HTML5。\n5、关于播放器调用说明:\n 单击文件名:默认播放器;\n 双击除文件名外:官方HTML5;\n 单击“Dp播放”:Dplayer;\n 单击“Pot播放”:Potplayer;\n 非115页面:默认播放器。'); } }, hide_sidebar: { section: ['更多设置', '优化浏览体验'], label: '隐藏网盘侧边栏', labelPos: 'right', type: 'checkbox', default: false, }, show_Star: { label: '网盘顶部增加星标按钮', labelPos: 'right', type: 'checkbox', default: true, }, show_Update: { label: '更新后弹出更新日志', labelPos: 'right', type: 'checkbox', default: true, }, file_Down: { label: '启用文件快捷下载', labelPos: 'right', type: 'checkbox', default: true, line: 'start', }, show_sha: { label: '下载后显示文件校验码', labelPos: 'right', type: 'checkbox', default: false, line: 'end', }, toastr: { label: '通知弹出位置', labelPos: 'left', type: 'select', 'options': ['左上', '右上', '中上','全铺'], default: '右上', }, }, events: { save: function() { GM_config.close(); } }, }); }; config(); function login(day){ var Buffer, LZ4, LoginEncrypt_, browserInterface, bytesToHex, bytesToString, cloneInto, dictToForm, dictToQuery, ec115_compress_decode, ec115_decode, ec115_decode_aes, ec115_encode_data, ec115_encode_token, ec115_init, elliptic, g_ver, get_key, md4, md4_init, preLoginEncrypt, ref, sig_calc, sig_init, stringToBytes; g_ver = '8.3.0.25'; Buffer = require('buffer').Buffer; LZ4 = require('lz4'); elliptic = window.elliptic; md4 = window.md4; stringToBytes = function(s) { var i, l, ref, ret; ret = []; for (i = l = 0, ref = s.length; (0 <= ref ? l < ref : l > ref); i = 0 <= ref ? ++l : --l) { ret.push(s.charCodeAt(i)); } return ret; }; bytesToString = function(b) { var i, l, len1, ret; ret = ''; for (l = 0, len1 = b.length; l < len1; l++) { i = b[l]; ret += String.fromCharCode(i); } return ret; }; bytesToHex = function(b) { var l, len1, ret, t; ret = ''; for (l = 0, len1 = b.length; l < len1; l++) { t = b[l]; ret += (t >> 4).toString(16); ret += (t & 0xf).toString(16); } return ret; }; ec115_init = function() { var Q, c, key, keys, pub; c = new elliptic.ec('p224'); keys = c.genKeyPair(); pub = [0x1d].concat(keys.getPublic(true, true)); Q = c.keyFromPublic('0457A29257CD2320E5D6D143322FA4BB8A3CF9D3CC623EF5EDAC62B7678A89C91A83BA800D6129F522D034C895DD2465243ADDC250953BEEBA'.toLowerCase(), 'hex'); key = (keys.derive(Q.getPublic())).toArray(); return {pub, key}; }; ec115_encode_token = function(pub, tm, cnt) { var i, l, m, o, q, r20, r21, tmp, tmp2; r20 = Math.floor(Math.random() * 256); r21 = Math.floor(Math.random() * 256); tmp = Buffer.alloc(48); for (i = l = 0; l < 15; i = ++l) { tmp[i] = pub[i] ^ r20; } tmp[15] = r20; tmp.writeInt32LE(115, 16); tmp.writeInt32LE(tm, 20); for (i = m = 16; m < 24; i = ++m) { tmp[i] ^= r20; } for (i = o = 24; o < 39; i = ++o) { tmp[i] = pub[i - 9] ^ r21; } tmp[39] = r21; tmp.writeInt32LE(cnt, 40); for (i = q = 40; q < 44; i = ++q) { tmp[i] ^= r21; } tmp2 = Buffer.concat([Buffer.from('^j>WD3Kr?J2gLFjD4W2y@'), tmp.slice(0, 44)]); tmp.writeInt32LE(CRC32.buf(tmp2), 44); return tmp.toString('base64'); }; ec115_encode_data = function(data, key) { var aesEcb, i, j, k, key1, key2, l, n, part, rets, tmp; key1 = key.slice(0, 16); key2 = key.slice(-16); aesEcb = new aesjs.ModeOfOperation.ecb(key1); tmp = stringToBytes(data); n = tmp.length; j = 0; rets = []; while (n > 0) { part = Buffer.alloc(16); for (i = l = 0; l < 16; i = ++l) { k = n <= 0 ? 0 : tmp[i + j]; part[i] = key2[i] ^ k; --n; } key2 = aesEcb.encrypt(part); rets.push(Buffer.from(key2)); j += 16; } return Buffer.concat(rets); }; ec115_decode_aes = function(data, key) { var aesCbc, i, iv, key1, ret; key1 = key.slice(0, 16); iv = key.slice(-16); aesCbc = new aesjs.ModeOfOperation.cbc(key1, iv); ret = aesCbc.decrypt(data); i = ret.length; while (i > 0 && ret[i - 1] === 0) { --i; } return Buffer.from(ret.buffer, ret.byteOffset, i); }; ec115_compress_decode = function(data) { var len, p, r, rets, tmp; p = 0; rets = []; while (p < data.length) { len = data.readInt16LE(p) + 2; if (p + len > data.length) { return null; } tmp = Buffer.alloc(0x2000); r = LZ4.decodeBlock(data.slice(p + 2, p + len), tmp); if (r < 0) { return null; } rets.push(tmp.slice(0, r)); p += len; } return Buffer.concat(rets); }; get_key = function(data_buf) { var i, l, p, ret, t; p = 0; ret = Buffer.alloc(40); for (i = l = 0; l < 40; i = ++l) { t = data_buf.readInt32LE(p); p = t + 1; ret[i] = data_buf[t]; } return ret; }; md4_init = function(pSig) { var ret; ret = md4.create(); ret.h0 = pSig.readInt32LE(4); ret.h1 = pSig.readInt32LE(8); ret.h2 = pSig.readInt32LE(12); ret.h3 = pSig.readInt32LE(16); ret.first = false; return ret; }; sig_init = function(body) { var data_buf, data_buf_p, dhash, md4h, ori_data_p, pSig, sz; ori_data_p = Module._malloc(body.length); Module.HEAPU8.set(body, ori_data_p); data_buf_p = Module._malloc(body.length); sz = Module.ccall('calc_out', 'number', ['number', 'number', 'number'], [ori_data_p, body.length, data_buf_p]); Module._free(ori_data_p); data_buf = Buffer.from(Module.buffer, data_buf_p, sz); pSig = get_key(data_buf); md4h = md4_init(pSig); md4h.update(data_buf); dhash = md4h.digest(); return {data_buf, data_buf_p, pSig, dhash}; }; sig_calc = function({data_buf, data_buf_p, pSig, dhash}, src) { var h1, h1_p, h2, h2b, i, l, md4h, out_data, out_data_p, pad, ret, sz, xxh; xxh = XXH.h64(); xxh.init(pSig.readUInt32LE(8)); xxh.update(src); h2 = xxh.digest().toString(16); pad = '0000000000000000'; h2b = Buffer.from(pad.slice(0, 16 - h2.length) + h2, 'hex').swap64(); md4h = md4_init(pSig); md4h.update(dhash); md4h.update(src); md4h.update(h2b); md4h.update(pSig); h1 = new Uint8Array(md4h.buffer()); h1_p = Module._malloc(16); Module.HEAPU8.set(h1, h1_p); out_data_p = Module._malloc(0x10000); sz = Module.ccall('encode', 'number', ['number', 'number', 'number', 'number', 'number', 'number', 'number'], [data_buf_p, data_buf.length / 2, h1_p, 16, out_data_p, 8, 10]); Module._free(data_buf_p); Module._free(h1_p); out_data = new Uint8Array(Module.buffer, out_data_p, sz); md4h = md4_init(pSig); md4h.update(out_data); ret = md4h.digest(); Module._free(out_data_p); ret.push(pSig[0]); for (i = l = 36; l < 40; i = ++l) { ret.push(pSig[i]); } return bytesToHex(ret); }; ec115_decode = function(data, key) { var dec, unzip; dec = data[data.length - 12 + 5]; unzip = data[data.length - 12 + 4]; data = data.slice(0, -12); if (dec === 1) { data = ec115_decode_aes(data, key); } if ((data != null) && unzip === 1) { data = ec115_compress_decode(data); } return data; }; dictToQuery = function(dict) { var k, tmp, v; tmp = []; for (k in dict) { v = dict[k]; tmp.push(`${encodeURIComponent(k)}=${encodeURIComponent(v)}`); } return tmp.join('&'); }; dictToForm = function(dict) { var k, tmp, v; tmp = []; for (k in dict) { v = dict[k]; tmp.push(`${k}=${v}`); } return tmp.join('&'); }; LoginEncrypt_ = function({account, passwd, environment, goto, login_type}, g, {pub, key}, sig) { var data, fake, tm, tmus, token; tmus = (new Date()).getTime(); tm = Math.floor(tmus / 1000); fake = md5(account); token = ec115_encode_token(pub, tm, 1); data = ec115_encode_data(dictToForm({ GUID: fake.slice(0, 20), account: account, device: 'GhostXP', device_id: fake.slice(2, 14).toUpperCase(), device_type: 'windows', disk_serial: fake.slice(0, 8).toUpperCase(), dk: '', environment: environment, goto: goto, login_source: '115chrome', network: '5', passwd: passwd, sign: md5(`${account}${tm}`), system_info: ` ${fake[1]}${fake[0]}${fake[3]}${fake[2]}${fake[5]}${fake[4]}${fake[7]}${fake[6]}`.toUpperCase(), time: tm, login_type: login_type, signew: 1, sign115: sig_calc(sig, md5(`${account}${tm}`)) }), key); return GM_xmlhttpRequest({ method: 'POST', url: `http://passport.115.com/?ct=encrypt&ac=login&k_ec=${token}`, data: GM_info.scriptHandler === 'Violentmonkey' && compareVersions.compare(GM_info.version, 'v2.12.2', '<') ? new Blob([data.buffer], { type: 'application/octet-binary' }) : data.toString('latin1'), binary: true, responseType: 'arraybuffer', headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' }, onerror: function(response) { return GM_log(`response.status = ${response.status}, response.statusText = ${response.statusText}`); }, onload: function(response) { var date, datestr, json; if (response.status === 200) { data = Buffer.from(response.response); data = ec115_decode(data, key); if (data != null) { json = JSON.parse(data.toString('latin1')); if (json.state && (json.data != null)) { date = new Date(); date.setTime(date.getTime() + parseInt(day) * 24 * 3600 * 1000); datestr = date.toUTCString(); var time = date.Format("yyyy年MM月dd日 HH:mm:ss"); GM_setValue('login_Last',time); document.cookie = `UID=${json.data.cookie.UID}; expires=${datestr}; path=/; domain=115.com`; document.cookie = `CID=${json.data.cookie.CID}; expires=${datestr}; path=/; domain=115.com`; document.cookie = `SEID=${json.data.cookie.SEID}; expires=${datestr}; path=/; domain=115.com`; document.cookie = `OOFL=${json.data.user_id}; expires=${datestr}; path=/; domain=115.com`; delete json.data; } return unsafeWindow[g](JSON.stringify(json)); } else { return GM_log('data is null'); } } else { return GM_log(`response.status = ${response.status}`); } } }); }; preLoginEncrypt = function(n, g) { var key, pub, tm, tmus, token; tmus = (new Date()).getTime(); tm = Math.floor(tmus / 1000); ({pub, key} = ec115_init()); token = ec115_encode_token(pub, tm, 0); return GM_xmlhttpRequest({ method: 'GET', url: `https://passportapi.115.com/app/2.0/web/${g_ver}/login/sign?k_ec=${token}`, responseType: 'arraybuffer', anonymous: true, onerror: function(response) { return GM_log(`response.status = ${response.status}, response.statusText = ${response.statusText}`); }, onload: function(response) { var body, data, error, json, sig; if (response.status === 200) { data = Buffer.from(response.response); data = ec115_decode(data, key); if (data != null) { json = JSON.parse(data.toString('latin1')); if (json.state) { body = Buffer.from(json.sign, 'base64'); try { sig = sig_init(body); return LoginEncrypt_(JSON.parse(n), g, {pub, key}, sig); } catch (error1) { error = error1; return GM_log(`${error.message}\n${error.stack}`); } } else { return GM_log(JSON.stringify(json)); } } else { return GM_log('data is null'); } } else { return GM_log(`response.status = ${response.status}`); } } }); }; browserInterface = (ref = unsafeWindow.browserInterface) != null ? ref : {}; browserInterface.LoginEncrypt = function(n, g) { var error; try { return preLoginEncrypt(n, g); } catch (error1) { error = error1; return GM_log(`${error.message}\n${error.stack}`); } }; browserInterface.GetBrowserVersion = function() { return new String(g_ver); }; browserInterface.ChromeGetIncognitoState = function() { return false; }; if (typeof cloneInto !== 'function') { cloneInto = function(x) { return x; }; } unsafeWindow.browserInterface = cloneInto(browserInterface, unsafeWindow, { cloneFunctions: true }); }; var G = GM_config; var localHref = window.location.href; var sign_url = 'http://115.com/?ct=offline&ac=space'; var add_url = 'http://115.com/web/lixian/?ct=lixian&ac=add_task_url'; var lists_url = 'http://115.com/web/lixian/?ct=lixian&ac=task_lists'; function notice(){ GM_addStyle(GM_getResourceText('toastrCss')); if(G.get('toastr')=='全铺'|| localHref.indexOf('https://captchaapi.115.com') != -1) { GM_addStyle('.toast{font-size:15px!important;} .toast-title{font-size:16px!important;text-align:center}'); }else{ GM_addStyle('.toast{font-size:15px!important;width:350px!important;} .toast-title{font-size:16px!important;text-align:center}'); }; var place = {'左上':'toast-top-left','右上':'toast-top-right','中上':'toast-top-center'}[G.get('toastr')] || 'toast-top-full-width'; toastr.options = { "closeButton": true, "debug": false, "progressBar": true, "timeOut": 8000, "extendedTimeOut": 8000, "positionClass": place, "allowHtml": true, "newestOnTop" : false, }; }; notice(); function AjaxCall(href,callback) { GM_xmlhttpRequest({ method: "GET", url: href, onload: function(data,status) { if(data.readyState==4 && data.status==200){ var htmlTxt = data.responseText; callback(null,htmlTxt); }; }, onerror: function (error) { callback(error); }, ontimeout: function (error) { callback(error); }, }); }; function download(pid,sha){ var href = 'https://webapi.115.com/files/download?pickcode='+pid; AjaxCall(href,function(error,htmlTxt) { var json = JSON.parse(htmlTxt); if(json.state) { var link = json.file_url.replace(/\\/g,''); GM_openInTab(link); if (G.get('show_sha')){ setTimeout(function(){ prompt('文件下载中,校验码(SHA1)为:',sha); }, 1000); }; console.log('下载地址:\n'+link); console.log('校验码:\n'+sha); } else { toastr.warning(json.msg,'下载失败!'); }; }); }; function palyData(video,className){ if ((G.get('player') =='官方HTML5' && className == '115play') || className == 'dblclick'){ var link = 'https://115.com/?ct=play&pickcode='+video.pid+'&hls=1'; GM_openInTab(link,false); return; }; var herfLink = 'https://115.com/api/video/m3u8/'+video.pid+'.m3u8'; AjaxCall(herfLink,function(error,htmlTxt) { if (typeof htmlTxt == 'undefined') { transcoding(video.sha,function(result,num,time) { if (result){ var txt = `等待转码排名:第${num}名,耗时:约${time},请稍后再试。`; }else{ var txt = '未获取到转码进度,请稍后再试。'; }; var h1 = `
查看转码进度详情`; toastr.warning(txt+h1, '播放失败,视频未转码!',{timeOut:10000}); }); return; }; var dataList = htmlTxt.split('\n'); var m3u8 = []; var temp = '"YH"|原画|"BD"|4K|"UD"|蓝光|"HD"|超清|"SD"|高清|"3G"|标清'; var txt = temp.split('|'); for (var i=0; i<6; i++){ dataList.forEach(function (e,j,arr) { if (e.indexOf(txt[i*2])!= -1) { m3u8.push({name: txt[i*2+1], url: arr[j+1].replace(/\r/g,''), type:'hls'}); }; }); }; if (m3u8.length ==1 || G.get('play_Quality') =='最高'){ var num = 0; }else if(m3u8.length >1 && G.get('play_Quality') =='次高'){ var num = 1; }else{ var num = m3u8.length - 1; }; video['quality'] = num; if ((G.get('player') == 'Potplayer' && className == '115play') || className == 'Pot'){ window.location.href = 'potplayer://'+m3u8[num].url; return; }; GM_setValue('videoInfo',video); GM_setValue('m3u8List',m3u8); GM_openInTab('http://115.com/web/lixian/',false); }); }; function transcoding(sha,callback){ var href = 'http://transcode.115.com/api/1.0/web/1.0/trans_code/check_transcode_job?sha1='+sha+'&priority=100'; console.log('转码进度地址:'+href); AjaxCall(href,function(error,htmlTxt) { var json = JSON.parse(htmlTxt); if(json.status != 127) { var num = json.count; var time = tranTime(json.time).replace(/分.*/,'分'); callback(true,num,time); return; }else{ callback(false,null); console.log('查询转码进度失败'); } }); }; function change(number){ var size = ""; if(number < 1024 * 1024 * 1024){ size = (number/(1024 * 1024)).toFixed(2) + "MB"; }else{ size = (number/(1024 * 1024 * 1024)).toFixed(2) + "GB"; }; var sizeStr = size + ""; var index = sizeStr.indexOf("."); var dou = sizeStr.substr(index + 1 ,2) if(dou == "00"){ return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2) }; return size; }; function tranTime(num){ var showTime = ''; if (num > 3600) {showTime += ' '+parseInt(num/3600)+' 小时'; num = num%3600;} if (num > 60) {showTime += ' '+parseInt(num/60)+' 分'; num = num%60;} return showTime += ' '+parseInt(num)+' 秒'; }; function enterPiP(videoEl){ if(document.pictureInPictureEnabled && !videoEl.disablePictureInPicture) { if (!document.pictureInPictureElement) { videoEl.requestPictureInPicture(); }else{ document.exitPictureInPicture(); }; }else{ alert('浏览器不支持或已关闭画中画功能!'); }; }; function clickOne(el){ if (el.attr('clicked') == 1){ console.log('5s内不可点击该按钮'); return false; }else{ el.attr('clicked',1); el.css('opacity','0.2'); setTimeout(function(){ el.attr('clicked',0); el.css('opacity','0.7'); }, 5000); return true; }; }; function verify(){ var time = new Date().getTime(); var w=335; var h=500; var t = (window.screen.availHeight-h)/2; var l = (window.screen.availWidth-w)/2; var url = 'https://captchaapi.115.com/?ac=security_code&type=web&cb=Close911_'+time; var a = confirm('立即打开验证账号弹窗?\n(浏览器需允许弹出式窗口)'); if (a){ window.open(url,'请验证账号','height='+h+',width='+w+',top='+t+',left='+l+',toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,status=no'); }; }; function getRightUrl(url){ var newUrl = url; if(/^magnet/.test(url)){ var hash=url.split('&')[0].substring(20) || url.substring(20); if(hash.length==32){ hash=base32To16(hash); }; newUrl='magnet:?xt=urn:btih:' + hash; }else if(/^thunder/.test(url)){ var key = url.replace('thunder://',''); var temp = decode64(key); newUrl = temp.slice(2,-2); }else if(/^\/\//.test(url)){ newUrl=location.protocol + url; }else if(/^\/(?!\/)/.test(url)){ newUrl=location.protocol+'//'+location.host + url; }; return newUrl; }; function base32To16(str){ if(str.length % 8 !== 0 || /[0189]/.test(str)){ return str; }; str = str.toUpperCase(); var bin = "", returnStr = "", i; for(i = 0;i < str.length;i++){ var charCode=str.charCodeAt(i); if(charCode<65)charCode-=24; else charCode-=65; charCode='0000'+charCode.toString(2); charCode=charCode.substr(charCode.length-5); bin+=charCode; }; for(i = 0;i < bin.length;i+=4){ returnStr += parseInt(bin.substring(i,i+4),2).toString(16); }; return returnStr; }; function getAttribute(e){ var data = [] ; $.each(e.attributes, function() { if(this.specified && this.value.length>30) { data.push(this.value); }; }); if($(e).text().length>25) data.push($(e).text()); return data; }; Date.prototype.Format = function (fmt) { var o = { "M+": this.getMonth() + 1, "d+": this.getDate(), "H+": this.getHours(), "m+": this.getMinutes(), "s+": this.getSeconds(), "q+": Math.floor((this.getMonth() + 3) / 3), "S": this.getMilliseconds() }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt; }; $(document).ready(function(){ if(localHref.indexOf('https://115.com/') != -1) { if (G.get('account_Login')){ if ( typeof (require) == 'undefined') { alert('115优化大师:帐号登录库文件加载失败,该功能无法使用,请刷新网页重新加载!'); return false; }; var day = G.get('login_Alidity').replace('天',''); login(day); }; if (typeof (unsafeWindow.USER_ID) != 'undefined') { GM_setValue('115ID', unsafeWindow.USER_ID); console.log('115账号已登录,账号ID获取成功!'); } else { if (G.get('hide_officeLogin')){ $('.ltab-office').hide(); }; if (G.get('hide_qrcodeLogin')){ $('.login-scene,.login-footer span:eq(0),.login-footer i:eq(0)').hide(); $('[lg_rel="login"]').show(); } else if ($('[lgb-nav="download"]').length > 0) { $('[lgb-nav="download"]').attr('lgb-nav','login'); }; console.log('115账号未登录,账号ID获取失败!'); }; var $El = $('#js_top_panel_box [menu="upload"]').addClass('btn-line'); if (G.get('show_Star')){ $El.after('星标'); }; $('body').append(` `); if (G.get('hide_sidebar')){ $('.sub-core').hide(); setTimeout(function(){ $('.main-core').css({'left':'16px','top':'16px'}); },50); }; if (G.get('file_Down')){ var herfd = 'li[rel="item"][file_type="1"]:not([down_button="1"])'; $('body').on('mouseenter',herfd,function(){ var $El = $(this).attr('down_button',1); $El.find('.file-opr [menu="download_one"]').hide(); $El.find('.file-opr').prepend('快捷下载'); return false; }); }; var herfv = 'li[rel="item"][file_type="1"][file_mode="9"]:not([paly_button="1"])'; $('body').on('mouseenter',herfv,function(){ var $El = $(this).attr('paly_button',1); var c = {'Dplayer':'Dp','Potplayer':'Pot','官方HTML5':'115play'}[G.get('player')]; $El.find('.name').addClass(c).removeAttr('menu'); var txt0 = ['Pot','Dp']; var txt1 = ['使用Potplayer播放视频','使用Dplayer播放视频']; var txt2 = ['Pot播放','Dp播放']; for (var i=0; i<2; i++){ $El.find('.file-opr').prepend(''+txt2[i]+''); }; $El.not('.name').dblclick(function(){ var className = 'dblclick'; var pid1 = $El.attr('pick_code'); var video = {'pid':pid1}; palyData(video,className); return false; }); }); }; if(localHref.indexOf('https://captchaapi.115.com') != -1) { window.focus(); toastr.info('验证成功本页面将自动关闭.'); $('#js_ver_code_box').find('[rel="verify"]').click(function () { setTimeout(function(){ if($('[rel="error_box"]').attr('style').indexOf('none') != -1){ window.opener=null; window.open('','_self'); window.close(); }; }, 500); return false; }); }; if(localHref.indexOf('https://115.com/?ct=play') != -1) { $('.bar-side ul').prepend(`
  • 画中画
    开启画中画
  • `); }; var oldVer = GM_getValue('version') || ''; if (G.get('show_Update') && oldVer != newVersion){ var txt=`115优化大师 ${newVersion} 更新日志:\n更新日期:2020年10月18日 \n1、新增“更新后弹出更新日志”选项,默认开启;\n2、优化模糊匹配规则,提高下载地址识别率;\n3、Dplayer的“开启画中画”选项,移至播放器右下角;\n4、优化播放进度保存规则,剩余播放时间少于120秒的将被自动删除。`; setTimeout(function(){ alert(txt); },2000); GM_setValue('version',newVersion); }; }); if(localHref.indexOf('https://115.com/?cid=0&offset=0&mode=wangpan') != -1){ window.onload=function(){ if (G.get('show_Alidity') && G.get('account_Login')){ var loginTime= GM_getValue('login_Last'); if (typeof unsafeWindow.USER_ID != 'undefined') { if (typeof loginTime != 'undefined') { toastr.success(loginTime, '登录有效期为',{timeOut:5000}); }else{ toastr.warning('其他方式登录,未知有效期!', '登录有效期为',{timeOut:5000}); }; }; }; }; }; if (localHref.match(/http:\/\/115\.com\/web\/lixian\/$/) != null ) { var m3u8 = GM_getValue('m3u8List'); var video = GM_getValue('videoInfo'); var titleTxt = video.name; var pickID = video.pid; var folderID = video.fid1; var videoID = video.fid2; var size = video.size; var sha = video.sha; var z = video.quality; var jsonList = GM_getValue('palyList') || {}; var curTime = jsonList[pickID]; if (curTime){ delete jsonList[pickID]; }; var skipTime = G.get('skip_titles'); var skipTime2 = G.get('skip_credits'); $('pre').remove(); $('head').html(`${titleTxt} ${size}`); GM_addStyle(`html,body,div{margin:0;padding:0;border:0;outline:0;background:transparent}`); GM_addStyle(GM_getResourceText('dplayerCss')); $('body').append('
    '); function playVideo(m3u8) { var dp = new DPlayer({ container: $('#Dplayer')[0], screenshot: true, volume: 1, video: { quality: m3u8, defaultQuality: z, }, contextmenu: [ { text: '下载视频', click: function(t) { download(pickID,sha); } }, { text: '删除视频', click: function(t) { dp.pause(); var a = confirm('确认删除 '+titleTxt+' 视频文件?'); if (a){ offline.del(videoID) }; } }, { text: '查看文件夹', click: function(t) { GM_openInTab(`https://115.com/?cid=${folderID}&offset=0&mode=wangpan`,false); } }, { text: '删除文件夹', click: function(t) { if (folderID==0){ alert('网盘根目录,不可删除!'); return ; }; var a = confirm('确认删除 '+titleTxt+' 视频所属文件夹?'); if (a){ offline.del(folderID); }; } }, { text: '设置星标', click: function(t) { var n=1; offline.setStar(videoID,n); } }, { text: '取消星标', click: function(t) { var n=0; offline.setStar(videoID,n); } }, ], }); unsafeWindow.dp = dp; $('#Dplayer').click(); $('.dplayer-menu').css('width','98px'); $('.dplayer-setting-loop,.dplayer-mobile-play,.dplayer-menu-item:gt(-3)').hide(); if(m3u8.length >1){ $('.dplayer-quality button').css('color','Lime'); }; $('.dplayer-quality').after(`
    `); dp.on('loadstart', function () { dp.notice('视频加载中,请稍侯。', 1000); }); var a = 0; dp.on('loadeddata', function () { dp.notice('视频加载完成。', 1000); a++; if( a==1){ setTimeout(function(){ if (curTime && curTime > skipTime){ dp.seek(curTime); dp.notice('已跳转到上次观看进度'+tranTime(curTime), 2500); }else if(skipTime>0){ dp.seek(skipTime); dp.notice('已跳过片头'+skipTime+'秒', 2500); }; if(m3u8.length >1){ setTimeout(function(){ dp.notice('本视频支持切换清晰度', 2500); }, 3000); }; if (document.hidden && G.get('Tab_ing')){ return; }; dp.play(); }, 1000); }; }); dp.on('timeupdate', function () { if ((dp.video.duration - dp.video.currentTime > 120) && dp.video.currentTime > 30) { jsonList[pickID] = dp.video.currentTime; var setNum = G.get('play_Number').replace('条',''); var saveNum = Object.keys(jsonList).length; if (saveNum > parseInt(setNum)){ var palyOld = JSON.stringify(jsonList).split('"')[1]; delete jsonList[palyOld]; }; }else{ delete jsonList[pickID]; }; GM_setValue('palyList',jsonList); if(0< skipTime2 && (dp.video.duration - dp.video.currentTime) <= skipTime2){ dp.pause(); dp.notice('已跳过片尾'+skipTime2+'秒', 2500); setTimeout(function(){ alert('视频已播放结束!'); }, 2000); }; }); dp.on('error', function () { alert('视频加载失败!'); return }); dp.on('ended', function () { alert('视频已播放结束!'); }); }; playVideo(m3u8); }; var offline = function(){ return { getSign:function () { return new Promise(function(resolve, reject){ var time = Date.now(); GM_xmlhttpRequest({ method: 'GET', url: sign_url, onload: function(response) { if (response.responseText.indexOf('html')!= -1) { toastr.error('请先登录115网盘账号!','离线任务添加失败。'); setTimeout(function(){ var a = confirm('立即打开115网盘登录页面?'); if (a){ GM_openInTab('https://115.com/?mode=login',false); }; }, 3000); return; }; var json = JSON.parse(response.responseText); resolve(json); }, onerror: function(error) { reject(error); }, }); }); }, param2:function (data,e) { if (typeof e != 'undefined'){ return e; }; var res = ''; for(var key in data){ var value = data[key]; res += '&' + encodeURIComponent( key ) + "=" + encodeURIComponent( value ); }; return res.slice(1); }, getData:function (url,herf,e){ var UserID = GM_getValue('115ID') || ''; return offline.getSign().then(function(json){ return new Promise(function(resolve, reject){ var data = { uid: UserID, sign: json.sign, time: json.time, url: url }; GM_xmlhttpRequest({ method: 'POST', data: offline.param2(data,e), url: herf, headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Accept": "application/json, text/javascript, */*; q=0.01", Origin: "http://115.com", "X-Requested-With": "XMLHttpRequest" }, onload: function(response) { var json = JSON.parse(response.responseText); resolve(json); }, onerror: function(error) { reject(error); }, }); }); }); }, del:function (key) { var url = ''; var del_url ='https://webapi.115.com/rb/delete'; var fidInfo = 'fid='+key; offline.getData(url,del_url,fidInfo).then(function(json){ if(json.state) { var a = confirm('删除成功,可从回收站还原。是否立即关闭本页面?'); if (a){ window.opener=null; window.open('','_self'); window.close(); }; } else { alert('删除失败:'+json.error); }; }); }, setStar:function (fid,n){ var url = ''; var star_url ='https://webapi.115.com/files/star'; var e = `file_id=${fid}&star=${n}`; var txt = {'1':'设置','0':'取消'}[n]; offline.getData(url,star_url,e).then(function(json){ json.state ? alert(txt+'星标成功!') : alert(txt+'星标失败:'+json.error); }); }, search:function (name,fid1,callback){ var title = new Array(); title[0] = name.replace(/(\.|-|_)?(f?hd|sd|720p|1080p|full|mp4|avi|mkv|wmv|rmvb|rm|flv|f4v)/gi,' '); title[1] = title[0].replace(/\.|-|_|@/g,' '); title[2] = 'mp4 avi mkv wmv rmvb rm flv f4v'; var a = 0; function add2(){ if(a == 3){ console.log('该文件夹无视频文件。'); callback(false); return; }; var searchLink = 'https://webapi.115.com/files/search?cid='+fid1+'&search_value='+encodeURIComponent(title[a])+'&type=4'; AjaxCall(searchLink,function(error,htmlTxt) { if (typeof htmlTxt == 'undefined'){ a++; add2(); }else{ var json = JSON.parse(htmlTxt); if(a == 2 && json.folder.name == '云下载'){ callback(false); return; }; if(json.count > 0) { var num= json.data.length; for(var i=0; i打开任务列表`; if(document.hidden){ GM_setValue('noTimeOut',true); toastr.options.timeOut = 0; console.log('已切换到后台,暂停通知超时'); }else{ GM_setValue('noTimeOut',false); toastr.options.timeOut = 12000; }; var c = 1; var retry = false; var txt2 = '5秒后自动重试,请稍等。'; function add(retry,txt2){ if(c == 4){ console.log('离线结果查询异常。离线任务数量过多,请清空后再试。'); toastr.warning('离线任务数量过多,请清空后再试。', '离线结果查询异常!'); return; }; var lists_url2 = lists_url+'&page='+c; console.log('离线任务数据地址:'+lists_url2); offline.getData(url,lists_url2).then(function(json){ console.log('离线任务列表第'+c+'页:'); console.log(json); if(json.state){ for (var k=0; k= 99){ var name = dataEl.name; var fid1 = dataEl.file_id || '0'; if (show_result && !retry) { var txt = `文件(夹)名:${dataEl.name},大小:${change(dataEl.size)}。`; toastr.success(txt+a_list, '离线下载已完成',{timeOut:5000}); }; if (G.get('open_search')) { offline.search(name,fid1,function(search_result,video,j,num) { if (search_result) { if (G.get('search_result')) { var videoTxt = JSON.stringify(video); var txt = `文件名:${video.name},大小:${video.size},时长:${tranTime(video.time)}。`; var h1 = `
    播放`; var h2 = `  下载`; var h3 = `  删除`; var h4 = `  查看`; toastr.success(txt+h1+h2+h3+h4,`发现第 ${j} 个视频(共 ${num} 个)`); }; if (G.get('open_Popup') && j==1){ setTimeout(function(){ var className = '115play'; palyData(video,className); }, 500); }; }else{ if( dataEl.move == 2 || dataEl.move == 0 || dataEl.status == 0){ var txt = '离线数据取回网盘中。'; }else{ var txt = '未发现任何视频文件。'; }; var h1 = `
    打开文件列表`; toastr.warning(txt+txt2+h1, '视频搜索无结果!'); if (!retry){ setTimeout(function(){ retry = true; txt2=''; toastr.clear(); console.log('重试搜索结果:'); add(retry,txt2); }, 5000); }; }; }); }; }else if(show_result) { var txt = `文件(夹)名:${dataEl.name},下载进度为:${down_result}%。`; toastr.warning(txt+a_list, '离线下载中...'); console.log(`文件(夹)名:${dataEl.name},下载进度为:${down_result}%`); }; }else if(show_result) { var txt = '未知原因,请到115查看。'; toastr.error(txt+a_list,'离线下载失败',{timeOut:8000}); return; }; break; }else if(k == (json.tasks.length-1)) { console.log('第'+c+'页查询失败,无匹配数据'); if(c == json.page_count) { console.log('离线链接对比异常,已搜索所有离线列表页面,无返回结果。'); toastr.warning('搜索参数错误。', '离线结果查询异常!',{timeOut:5000}); return; }; c++ add(); }; }; }else{ toastr.error('查询离线结果失败。','服务器错误!'); return; }; }); }; add(retry,txt2); }, addButton:function(){ var href = '[href^="magnet:"],[href^="ed2k:"],[href^="thunder:"],[href^="ftp:"],[href$=".torrent"],[href$=".rar"],[href$=".7z"],[href$=".zip"],[href$=".mp4"],[href$=".rmvb"],[href$=".mkv"],[href$=".avi"]'; $(href).each(function(){ var url = $(this).attr('href'); var $El = $(this).parent().filter('li,td,th,:header').find('[Searched]'); if ($(this).is('[Searched]') || $El.length>1 || ($El.length=1 && url.indexOf($El.attr('Searched')) != -1)){ return; }; if (url.match(/^(magnet|thunder|ftp|ed2k):/) != null){ $(this).attr('Searched',url.split(':')[0]); }else if(url.match(/torrent$/) != null){ $(this).attr('Searched','torrent'); }else{ $(this).attr('Searched','other'); }; var link = getRightUrl(url); $(this).css('display','inline-block'); $(this).after(''); }); }, addLink:function(){ $('a:not(.zcopy)').each(function(){ var reg0 =/^(magnet|thunder|ftp|ed2k):/; var reg1 =/(\/|&|-|\.|\?|=|:|#)(\w{40}|\w{32})(?!\w)/; var reg2 =/_|[a-z]{40}|[a-z]{32}/gi; var reg3 =/(\w{40}|\w{32})(?!\w)/i; if ($(this).next().addBack().is('[Searched],[href*="motelppp.com"],[href*="bvmqkla.de"]') || $(this).find('img').length>0 || $(this).parent().filter('li,td,th').find('[Searched]').length>0){ return; }; var url = getAttribute(this); if(url.length>0){ for(var i=0;i'); return; }; }; }; }); }, }; }(); $(document).ready(function(){ $(document).on('visibilitychange',function (e){ var isHidden = e.target.hidden; if (localHref.match(/115\.com\S*(lixian|play)/) != null && G.get('Tab_ing') && !document.pictureInPictureElement){ var video = $('#js-video')[0] || dp ; isHidden ? video.pause() : video.play(); return; }; var noTimeOut=GM_getValue('noTimeOut') || ''; if (isHidden){ }else if(noTimeOut){ GM_setValue('noTimeOut',''); setTimeout(function(){ toastr.clear(); }, 12000); }else{ }; }); $('body').on('click mouseenter mouseleave','.openPiP',function(e){ if(e.type == 'click'){ enterPiP($('video')[0]); }else if(e.type == 'mouseenter'){ $(this).css('opacity', 1); }else if(e.type == 'mouseleave'){ $(this).css('opacity', 0.7); }; return false; }); $('body').on('click','.transcode',function () { var pid = $(this).attr('data'); var link = 'https://115.com/?ct=play&pickcode='+pid+'&hls=1'; GM_openInTab(link,false); return false; }); $('body').on('click','.115play,.Dp,.Pot',function(){ if (!clickOne($(this))) return; var className = $(this).attr('class').replace(/name\s?/g,''); if ($(this).is('[data]')){ var video = JSON.parse($(this).attr('data')); }else{ var $El = $(this).parents('li'); var video = {}; video['name'] = $El.attr('title').replace(/\s*/g, ''); video['pid'] = $El.attr('pick_code'); video['fid1'] = $El.attr('cid'); video['fid2'] = $El.attr('file_id'); video['size'] = change($El.attr('file_size')); video['sha'] = $El.attr('sha1'); }; palyData(video,className); return false; }); $('body').on('click','.115down',function(){ if (!clickOne($(this))) return; if ($(this).is('[data]')){ var video = JSON.parse($(this).attr('data')); var pid = video.pid; var sha = video.sha; }else{ var $El = $(this).parents('li'); var pid = $El.attr('pick_code'); var sha = $El.attr('sha1'); }; download(pid,sha); return false; }); $('body').on('click','.115del',function(){ if (!clickOne($(this))) return; var video = JSON.parse($(this).attr('data')); var title = video.name; var folderID = video.fid1; var videoID = video.fid2; if (folderID == 0){ alert('网盘根目录,不可删除!'); return ; }; var a = confirm('确认删除 '+title+' 视频所属文件夹?'); if (a){ offline.del(folderID); }; return false; }); $('body').on('click','.openList:not([click="1"]),.openFolder:not([click="1"])',function(){ $(this).attr('click', '1'); if($(this).is('.openList')){ var txt='tab=offline'; }else{ var fID=$(this).attr('data'); var txt='cid='+fID+'&offset=0'; }; GM_openInTab('https://115.com/?'+txt+'&mode=wangpan',false); return false; }); $('body').on('contextmenu','.115offline',function(){ GM_setClipboard($(this).data('href')); toastr.success('下载地址复制成功!'); return false; }); $('body').on('click','.115offline',function(){ if (!clickOne($(this))) return; var link = $(this).data('href'); offline.getData(link,add_url).then(function(json){ console.log('离线任务添加结果:'); console.log(json); if(json.state){ if (G.get('offline_result')) { var txt = '10秒后显示离线结果。'; }else{ var txt = link if (G.get('open_List')){ setTimeout(function(){ GM_openInTab('https://115.com/?tab=offline&mode=wangpan',false); }, 2000); }; }; toastr.info(txt,'离线任务添加成功。',{timeOut:10000}); setTimeout(function(){ offline.check(link) }, 10000); } else if (json.errcode == 10008){ toastr.warning('任务已存在,无需重复添加。','离线任务添加无效!',{timeOut:5000}); if (G.get('open_List')){ setTimeout(function(){ GM_openInTab('https://115.com/?tab=offline&mode=wangpan',false); }, 2000); }; offline.check(link); } else if (json.errcode == 911){ toastr.warning('账号异常,请验证账号。','离线下载失败!',{timeOut:5000}); setTimeout(function(){ verify(); }, 1000); } else { toastr.warning(json.error_msg,'离线任务添加失败!',{timeOut:12000}); }; console.log('离线链接:'+link+' 添加结果:'+json.state+' 原因:' +json.error_msg); }, function(error) { toastr.error('服务器繁忙,请稍后再试。','离线任务添加异常!'); console.log(error); }); return false; }); if (G.get('offline_Down') && localHref.indexOf('115.com') == -1){ if (localHref.match(/[0-9]mag\.net|yhg\w+\.\w+\/search/) != null) { var trigger; $('body').on('mouseenter mouseleave','td,.magnet-box,.search-item',function(e){ if(e.type == 'mouseenter'){ trigger = setTimeout(function(){ offline.addButton(); }, 200); }else if(e.type == 'mouseleave'){ clearTimeout(trigger); }; }); } else if(localHref.match(/pianku/) != null) { var time = setInterval(function(){ if (document.readyState == 'complete') { clearInterval(time); if(localHref.match(/\/bt\//) != null) { var key =$('script:eq(-2)').text().match(/'.{13}'/)[0]; $('body').append(` `); }else{ $('body').append(''); }; offline.addButton(); }; }, 1000); $('body').on('click','.torrent:not([Searched])',function(){ setTimeout(function(){ offline.addButton(); },50); }); } else { setTimeout(function(){ offline.addButton(); },100); if (G.get('fuzzy_find')){ setTimeout(function(){ offline.addLink(); },200); }; }; }; }); })();