Greasy Fork is available in English.

115优化大师

115网盘升级登录,延长登录有效期、一键离线下载、调用Dplayer或Potplayer播放视频、文件快捷下载等功能

您查看的为 2020-08-30 提交的版本。查看 最新版本

// ==UserScript==
// @name         115优化大师
// @author       zxf10608
// @version      2.6
// @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://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.bootcdn.net/ajax/libs/toastr.js/2.1.4/toastr.min.js
// @resource     toastrCss   https://cdn.bootcdn.net/ajax/libs/toastr.js/2.1.4/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.3/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*://www.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/*
// @grant        GM_log
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @grant        GM_openInTab
// @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
// ==/UserScript==

(function() {
	
    'use strict';
	if ( typeof GM_config == 'undefined') {//检查依赖的库文件   
			alert('115优化大师:相关库文件加载失败,脚本无法使用,请刷新网页重新加载!');
			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 版本:v2.6 点击访问主页'
					}),
			isTabs: true,
			skin: 'tab',
			css: windowCss,
			frameStyle: 
			{
				height: '420px',
				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',
				},
				reminder2:
				{
					label: '温馨提示',
					labelPos: 'right',
					type: 'button',
					click: function() {
					alert('1、显示离线下载结果有10s延时,用于服务器响应时间。\n2、为避免通知弹窗过多,最多只显示3个视频搜索结果,更多请自行到115查看。');
					}
				},
				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条', '15条', '30条'],
					default: '15条',
				},
				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、单击视频文件名调用指定播放器,双击除文件名外始终调用官方HTML5。\n2、除第一、第二项外,其他仅在启用Dplayer时有效。\n3、保存播放进度设为0条,可关闭记忆播放或清空播放进度。\n4、播放界面右键可显示更多功能菜单,谨慎使用“删除”操作。\n5、播放器跟随页面变化支持官方HTML5。');
					}
				},
				hide_sidebar:  
				{
					section: ['更多设置', '优化浏览体验'],
					label: '隐藏网盘侧边栏',
					labelPos: 'right',
					type: 'checkbox',
					default: false,
				},
				file_Down:
				{
					label: '启用文件快捷下载',
					labelPos: 'right',
					type: 'checkbox',
					default: true,
					line: 'start',
				},
				show_sha:
				{
					label: '下载后显示文件哈希值',
					labelPos: 'right',
					type: 'checkbox',
					default: false,
					line: 'end',
				},
								
			},
			
			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';
	
	GM_addStyle(GM_getResourceText("toastrCss"));
	toastr.options = { 
        "closeButton": true, 
        "debug": false, 
        "progressBar": true, 
        "timeOut": "5000", 
		"extendedTimeOut": "3000", 
		"allowHtml": true,
		"newestOnTop" : false, 
    };
	
	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){
		if (G.get('player') =='官方HTML5'){
			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}小时,请稍后再试。。`;
						var h1 = `<br><a target="_blank" class="transcode" data=${video.pid} href="javascript: void(0);" style="cursor:pointer;color:blue;" title="点击查看转码进度详情">查看转码进度</a>`;
						toastr.warning(txt+h1, '播放失败,视频未转码!',{timeOut:8000});
						return;
					}else{
					toastr.warning('服务器错误,查询转码进度失败。','播放失败,视频未转码!',{timeOut:8000});	
					};
				});
				
			}else{
				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/,''), 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;
				GM_setValue('videoInfo',video);
				
				if (G.get('player') =='Potplayer'){	
					window.location.href = 'potplayer://'+m3u8[num].url;
					return;
				};
				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 = (json.time/3600).toFixed(1);
				callback(true,num,time);
				console.log('转码进度 排队人数:'+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');
		
		};
	};
	
	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获取失败!');
						};
						
			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('<a href="javascript:;" class="115down" style="cursor:pointer;" title="快捷下载文件"><i class="icon-operate ifo-download"></i><span>快捷下载</span></a>');
					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);
				$El.find('.name').addClass('115play').removeAttr('menu');
				
				if (G.get('player') !='官方HTML5'){
					if (G.get('player') =='Dplayer'){
						var txt1 = 'Dp播放';
						var txt2 = '使用Dplayer在线播放';
					}else{
						var txt1 = 'Pot播放';
						var txt2 = '使用Potplayer本地播放';
					}; 
					$El.find('.file-opr').prepend('<a class="115play" href="javascript:;" title='+txt2+'><span>'+txt1+'</span></a>');
				};
				
				$El.not('.name').dblclick(function(){
					
					var pid = $El.attr('pick_code');
					var link = 'https://115.com/?ct=play&pickcode='+pid+'&hls=1';
					GM_openInTab(link,false);
					return false;
				});
			});	
			
		};
	
		if(localHref.indexOf('https://captchaapi.115.com') != -1) {
			window.focus();
			$('#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();
					};
					console.log('验证失败!');
				}, 500);
				return false;
			});
		};
		
		if(localHref.indexOf('https://115.com/?ct=play') != -1) {
			$('.bar-side ul').prepend('<li><a href="javascript:;" class="openPiP"><s>画中画</s><div class="tooltip">开启画中画</div></a></li>');
			GM_addStyle('.openPiP{float:left;width:40px;height:20px;margin:10px 5px;border-radius:3px;font-size:12px;text-align:center;background:#666;color:#fff;opacity:0.7;}');
		};
		
	});
	
	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') {
						toastr.success(loginTime, '登录有效期为');
					} else {
						toastr.warning('其他方式登录,未知有效期!', '登录有效期为');
					};
				};
		
			};
		
	};
	
	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(`<meta http-equiv="Content-Type" content="text/html; charset=GBK"><title>${titleTxt} ${size}</title>`);
		GM_addStyle(`html,body,div{margin:0;padding:0;border:0;outline:0;background:transparent}`);
		GM_addStyle(GM_getResourceText('dplayerCss'));
		
		$('body').append('<div id="Dplayer"></div>');
		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) {
							enterPiP(t.video)
						}
					}
				],
			});
			unsafeWindow.dp = dp;
			$('#Dplayer').click();
			
		    $('.dplayer-setting-loop,.dplayer-mobile-play,.dplayer-menu-item:gt(-3)').hide();
			$('.dplayer-menu').css('width','98px');
			dp.on('loadstart', function () {
				dp.notice('视频加载中,请稍等。', 1000);
			});
			
			var a = 0;
			dp.on('loadeddata', function () {
				dp.notice('视频加载完成,即将播放。', 1000);
				
				a = a+1;
				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 > 30) && 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(){
									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){
					console.log('文件删除结果:');
					console.log(json);
					if(json.state) {
						alert('删除成功,可从回收站还原。本页面将自动关闭!');
						setTimeout(function(){
							window.opener=null;
							window.open('','_self');
							window.close();
						}, 100);
					} else {
						alert('删除失败:'+json.error);
					};
				});
			},
			
			search:function (name,fid1,offlined,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 add(){
					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++;
							add();
						}else{
							var json = JSON.parse(htmlTxt);
							if(a == 2 && json.folder.name == '云下载'){
								console.log('不可用第三关键词搜索离线主目录。');
								callback(false);						
								return;
							};
							
							if(json.count > 0) {
								var num= json.data.length;
								for(var i=0; i<num; i++){
									var $dataEh = json.data[i];
									var video = {};
									video['name'] = $dataEh.n.replace(/\s*/g,'');
									video['pid'] = $dataEh.pc;
									video['fid1'] = $dataEh.cid;
									video['fid2'] = $dataEh.fid;
									video['size'] = change($dataEh.s);
									video['sha'] = $dataEh.sha;
									video['time'] =$dataEh.play_long;
									
									callback(true,video,i+1,num);
									console.log('第'+a+'次搜索结果'+i+':'+video.name+' '+video.size);
									if(i == 2){
										console.log('第'+a+'次搜索到3个视频,停止搜索。');
										
										return;
									};
								};
							}else{
								a++;
								add();
							};
						};
					});
				};
				add();
			},
			
			check:function (offlined,link) {
				var url = '';
				var show_result = G.get('offline_result');
				var a_list= `<br><a target="_blank" class="openList" href="javascript: void(0);" style="cursor:pointer;color:blue;" title="点击打开离线链接任务列表">打开任务列表</a>`;
				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;
				function add(){
					if(c == 4){
						console.log('离线结果查询异常。离线任务数量过多,请清空后再试。');
						toastr.warning('离线任务数量过多,请清空后再试。', '离线结果查询异常!',{timeOut:5000});						
						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<json.tasks.length; k++){
								var dataEl = json.tasks[k];
								if (dataEl.url == link || dataEl.url == decodeURIComponent(link)){
									if (dataEl.status != -1){
										if (dataEl.move == -1){
											toastr.warning('空间不足,请到115扩容', '离线下载异常!',{timeOut:5000});
											return;
										};
										var down_result = dataEl.percentDone.toFixed(0);
										if (down_result >= 99){
											var name = dataEl.name;
											var fid1 = dataEl.file_id;
											
											if (show_result) {
												var txt = `文件(夹)名:${dataEl.name},大小:${change(dataEl.size)}。`;
												toastr.success(txt+a_list, '离线下载已完成',{timeOut:5000});
											};
											
											if (G.get('open_search')) {
												offline.search(name,fid1,offlined,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 = `<br><a target="_blank" class="115play" data=${videoTXT} href="javascript: void(0);" style="cursor:pointer;color:blue;" title="点击播放该视频">立即播放</a>`;
															var h2 = `&nbsp;&nbsp;<a target="_blank" class="115down" data=${videoTXT} href="javascript: void(0);" style="cursor:pointer;color:blue;" title="点击下载该视频">立即下载</a>`;
															toastr.success(txt+h1+h2,`发现第${j}个视频(共${num}个)`);
														};
														
														if (G.get('open_Popup') && j==1){
															setTimeout(function(){
																palyData(video);
															}, 500);
														};
													}else{
														if( dataEl.move == 2 || dataEl.move == 0 || dataEl.status == 0){
															var txt = '离线数据取回网盘中,请稍后再试。';
														}else if(offlined){
															var txt = '视频可能已被删除,请删除该离线任务重试。';
														}else{
															var txt = '未发现任何视频文件。';
														};
														var h1 = `<br><a target="_blank" class="openFolder" data=${fid1} href="javascript: void(0);" style="cursor:pointer;color:blue;" title="点击打开所属文件夹列表">打开文件列表</a>`;
														toastr.warning(txt+h1, '视频搜索无结果!');
														console.log(name+' 无搜索结果!');	
													};
												});
											};
											
										}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();
			},
			
			addButton:function(){
				var supportHref = 'a[href^="magnet:"],[href^="ed2k:"],a[href^="thunder:"],[href^="ftp:"],[href$=".torrent"],[href$=".rar"],[href$=".7z"],[href$=".zip"],[href$=".mp4"],[href$=".rmvb"],[href$=".mkv"],[href$=".avi"],[href$=".iso"]';
				$(supportHref).each(function(){
					if ($(this).attr('offline_button') == 1){				
						return;	
					};
					$(this).attr('offline_button', 1);
					var link = $(this).attr('href');
					$(this).attr('style','display:inline-block;');
					$(this).after('<img src="https://115.com/favicon.ico" class="offline_logo" data-href='+link+' style="display:inline-block;cursor:pointer; margin-left:5px;border-radius:50%;border:0px;vertical-align:middle;outline:none!important;padding:0px!important;height:20px!important;width:20px!important;left:0px!important;top:0px!important;" title="使用115网盘离线下载">');
				});
			},
		};
	}();
	
	$(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  ;
				if (isHidden){
					video.pause();
				}else{
					video.play();
				};
				return;
			};
			
			if (isHidden){
			}else if(GM_getValue('noTimeOut')){
				GM_setValue('noTimeOut','');
				setTimeout(function(){ 
					toastr.clear();
				}, 10000);
			};
		});
		
		$('body').on('click mouseenter mouseleave','.openPiP',function(e){
			if(e.type == 'click'){
				var video = $('#js-video')[0];
				enterPiP(video);
			}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',function () {
			if (!clickOne($(this))) return;
			if ( typeof ($(this).attr('data')) != 'undefined'){ 
				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);
			return false;
		});
		
		$('body').on('click','.115down',function(){
			if (!clickOne($(this))) return;
			
			if ( typeof ($(this).attr('data')) != 'undefined'){ 
				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','.openList:not([click="1"])',function(){
			$(this).attr('click', '1');
			GM_openInTab('https://115.com/?tab=offline&mode=wangpan',false);
			return false;
		});
	
		$('body').on('click','.openFolder:not([click="1"])',function(){
			$(this).attr('click', '1');
			var fID=$(this).attr('data');
			GM_openInTab(`https://115.com/?cid=${fID}&offset=0&mode=wangpan`,false);
			return false;
		});
			
		$('body').on('click','.offline_logo',function(){
			if (!clickOne($(this))) return;
			var link = $(this).data('href');
			offline.getData(link,add_url).then(function(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, '离线任务添加成功。');
					setTimeout(function(){
						var offlined = false;
						offline.check(offlined,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);
					};
					var offlined = true;
					offline.check(offlined,link);
				
				} else if (json.errcode == 911){
					toastr.warning('账号异常,请验证账号。','离线下载失败!',{timeOut:5000});
					setTimeout(function(){
						verify();
					}, 3000);
					
				} else {
					toastr.warning(json.error_msg,'离线任务添加失败!');
				};
				console.log('离线链接:'+link+ ' 添加结果:' +json.state+ ' 原因:' +json.error_msg);
			}, function(error) {
				toastr.error('服务器繁忙,请稍后再试。','离线任务添加异常!');
				console.log(error);
			});
			return false;
		});
				
		if (G.get('offline_Down')){
				if (localHref.match(/[0-9]mag.net/) != null) {
					var trigger; 
					$('body').on('mouseenter mouseleave','td',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) {
					$('body').on('click','.torrent',function(){
						setTimeout(function(){
							offline.addButton();
						},50);
					});	
				} else {
					setTimeout(function(){
						offline.addButton();
					},100);
				};
		};
		
	});
	
})();