XuanFengEx

QQ旋风网页版离线下载增强

  1. // ==UserScript==
  2. // @name XuanFengEx
  3. // @namespace https://github.com/rhyzx/xuanfeng-userscript
  4. // @version 0.8.0
  5. // @description QQ旋风网页版离线下载增强
  6. // @match http://lixian.qq.com/main.html*
  7. // @copyright 2016+, rhyzx
  8. // ==/UserScript==
  9.  
  10.  
  11. /**
  12. * export downloads
  13. */
  14. injectScript(function () {
  15. // ======
  16.  
  17. var $ = window.jQuery // v1.6.1
  18. , msg = window.XF.widget.msgbox
  19.  
  20. // export / rewrite
  21. $('#task_dl_local em').text('导出下载')
  22. EventHandler.task_batch2local = function (e) {
  23. if ($(e).hasClass('disabled_btn')) return
  24. msg.show('获取下载地址中...', 0, 5000)
  25.  
  26. requestDownloadLinks(function (dls) {
  27. msg.hide()
  28. g_pop_export.setDownloads(dls)
  29. g_pop_export.show()
  30. })
  31. }
  32.  
  33.  
  34.  
  35. // get selected tasks' download link/cookie/filename
  36. // callback(dowloads)
  37. function requestDownloadLinks(callback) {
  38. var count = 0
  39. , downloads = []
  40.  
  41. // TODO? pre-check task status by
  42. // $.getJSON('/handler/lixian/get_lixian_items.php')
  43. $.Deferred().resolve(g_task_op.last_task_info)
  44. .done(function (res) {
  45. $.each(res, function (i, task) {
  46. // check
  47. if (
  48. !$('#task_sel_' +task.mid).is(':checked')|| // user selected
  49. task.file_size !== task.comp_size || // download finished
  50. task.dl_status !== TASK_STATUS['ST_UL_OK']
  51. ) return
  52.  
  53.  
  54. count++
  55. $.post('/handler/lixian/get_http_url.php', {
  56. hash : task.hash
  57. , filename: task.file_name
  58. //, g_tk : getACSRFToken(cookie.get('skey', 'qq.com'))
  59. //, browser : 'other'
  60. }, null, 'json')
  61. .done(function (res) {
  62. count--
  63. if (res && res.ret === 0) {
  64. // break speed limit
  65. // thanks @4023 https://userscripts.org/users/381599
  66. var url = res.data.com_url
  67. .replace('xflx.store.cd.qq.com:443', 'xfcd.ctfs.ftn.qq.com')
  68. .replace('xflx.sz.ftn.qq.com:80', 'sz.disk.ftn.qq.com')
  69. .replace('xflx.cd.ftn.qq.com:80', 'cd.ctfs.ftn.qq.com')
  70. .replace('xflxsrc.store.qq.com:443', 'xfxa.ctfs.ftn.qq.com')
  71.  
  72. downloads.push({
  73. url : url
  74. , cookie : res.data.com_cookie
  75. , filename : task.file_name
  76. })
  77. }
  78. })
  79. .fail(function () {
  80. msg.show('获取失败', 2, 2000)
  81. })
  82. .always(function () {
  83. if (count === 0) {
  84. // sort according to filename
  85. downloads.sort(function (a, b) {
  86. return a.filename.localeCompare(b.filename)
  87. })
  88. callback(downloads)
  89. }
  90. })
  91.  
  92. })
  93. })
  94. .fail(function () {
  95. msg.show('获取列表的接口坏了嘛?! 请联系脚本作者', 2, 2000)
  96. })
  97. }
  98. window.requestDownloadLinks = requestDownloadLinks // export to global
  99.  
  100. /// =====
  101. })
  102.  
  103.  
  104. /**
  105. * aria rpc
  106. */
  107. injectScript(function recall() {
  108. // ======
  109.  
  110. var $ = window.jQuery
  111. , msg = window.XF.widget.msgbox
  112.  
  113.  
  114. // button
  115. var $export = $('#task_dl_local')
  116. var $rpc = $export.clone()
  117. .removeAttr('onclick')
  118. .attr('id', 'task_dl_rpc')
  119. .find('em').text('RPC').end()
  120. .insertAfter($export)
  121.  
  122. // diable/enable botton
  123. $(document).click(function () {
  124. $export.hasClass('disabled_btn')
  125. ? $rpc.addClass('disabled_btn')
  126. : $rpc.removeClass('disabled_btn')
  127. })
  128.  
  129.  
  130. $rpc.click(function (evt) {
  131. if ($rpc.hasClass('disabled_btn')) return
  132.  
  133. var config = {
  134. url : localStorage.getItem('rpc-url')
  135. , token : localStorage.getItem('rpc-token')
  136. }
  137. if (config.url) {
  138. msg.show('获取下载地址中...', 0, 5000)
  139. requestDownloadLinks(function (dls) {
  140. msg.show('rpc请求中...', 0, 5000)
  141.  
  142. rpc(dls, config)
  143. .done(function (res) {
  144. msg.show('成功', 1, 2000)
  145. })
  146. .fail(function ($xhr, status, error) {
  147. msg.show('rpc请求失败,请检查设置,Message: ' +error, 2, 2000)
  148. g_pop_rpc.showConfig(config)
  149. })
  150. })
  151. } else {
  152. msg.show('rpc未设置', 3, 2000)
  153. g_pop_rpc.showConfig() // default url
  154. }
  155. })
  156.  
  157.  
  158. function rpc(dls, config) {
  159. var data = []
  160. $.each(dls, function (k, dl) {
  161. var ret = {
  162. jsonrpc : '2.0'
  163. , id : 'down_' +k
  164. , method : 'aria2.addUri'
  165. , params : [
  166. [dl.url]
  167. , {
  168. out : dl.filename
  169. , header : 'Cookie: FTN5K=' +dl.cookie
  170. , continue: 'true'
  171. , split : '10'
  172. , 'max-connection-per-server' : '10'
  173. }
  174. ]
  175. }
  176. if (config.token) {
  177. ret.params.unshift('token:' +config.token)
  178. }
  179. data.push(ret)
  180. })
  181.  
  182. // return Deferred Obj
  183. return $.post(config.url, JSON.stringify(data))
  184. // filter error
  185. .pipe(function (res, status, $xhr) {
  186. if (res[0].error) {
  187. return $.Deferred().reject($xhr, 'error', res[0].error.message)
  188. }
  189. })
  190. }
  191.  
  192. /// =====
  193. })
  194.  
  195.  
  196. /**
  197. * auto login
  198. */
  199. injectScript(function recall() {
  200. // ======
  201.  
  202. // function from http://imgcache.qq.com/ptlogin/ver/10021/js/comm.js
  203. var hexchar2bin=function(str){var arr=[];for(var i=0;i<str.length;i=i+2){arr.push("\\x"+str.substr(i,2))}arr=arr.join("");eval("var temp = '"+arr+"'");return temp}
  204. var md5=function(){var r=1;var n="";var t=8;var a=32;function u(r){return e(r)}function e(r){return g(v(A(r),r.length*t))}function v(r,n){r[n>>5]|=128<<n%32;r[(n+64>>>9<<4)+14]=n;var t=1732584193;var u=-271733879;var e=-1732584194;var v=271733878;for(var i=0;i<r.length;i+=16){var s=t;var A=u;var g=e;var b=v;t=f(t,u,e,v,r[i+0],7,-680876936);v=f(v,t,u,e,r[i+1],12,-389564586);e=f(e,v,t,u,r[i+2],17,606105819);u=f(u,e,v,t,r[i+3],22,-1044525330);t=f(t,u,e,v,r[i+4],7,-176418897);v=f(v,t,u,e,r[i+5],12,1200080426);e=f(e,v,t,u,r[i+6],17,-1473231341);u=f(u,e,v,t,r[i+7],22,-45705983);t=f(t,u,e,v,r[i+8],7,1770035416);v=f(v,t,u,e,r[i+9],12,-1958414417);e=f(e,v,t,u,r[i+10],17,-42063);u=f(u,e,v,t,r[i+11],22,-1990404162);t=f(t,u,e,v,r[i+12],7,1804603682);v=f(v,t,u,e,r[i+13],12,-40341101);e=f(e,v,t,u,r[i+14],17,-1502002290);u=f(u,e,v,t,r[i+15],22,1236535329);t=o(t,u,e,v,r[i+1],5,-165796510);v=o(v,t,u,e,r[i+6],9,-1069501632);e=o(e,v,t,u,r[i+11],14,643717713);u=o(u,e,v,t,r[i+0],20,-373897302);t=o(t,u,e,v,r[i+5],5,-701558691);v=o(v,t,u,e,r[i+10],9,38016083);e=o(e,v,t,u,r[i+15],14,-660478335);u=o(u,e,v,t,r[i+4],20,-405537848);t=o(t,u,e,v,r[i+9],5,568446438);v=o(v,t,u,e,r[i+14],9,-1019803690);e=o(e,v,t,u,r[i+3],14,-187363961);u=o(u,e,v,t,r[i+8],20,1163531501);t=o(t,u,e,v,r[i+13],5,-1444681467);v=o(v,t,u,e,r[i+2],9,-51403784);e=o(e,v,t,u,r[i+7],14,1735328473);u=o(u,e,v,t,r[i+12],20,-1926607734);t=c(t,u,e,v,r[i+5],4,-378558);v=c(v,t,u,e,r[i+8],11,-2022574463);e=c(e,v,t,u,r[i+11],16,1839030562);u=c(u,e,v,t,r[i+14],23,-35309556);t=c(t,u,e,v,r[i+1],4,-1530992060);v=c(v,t,u,e,r[i+4],11,1272893353);e=c(e,v,t,u,r[i+7],16,-155497632);u=c(u,e,v,t,r[i+10],23,-1094730640);t=c(t,u,e,v,r[i+13],4,681279174);v=c(v,t,u,e,r[i+0],11,-358537222);e=c(e,v,t,u,r[i+3],16,-722521979);u=c(u,e,v,t,r[i+6],23,76029189);t=c(t,u,e,v,r[i+9],4,-640364487);v=c(v,t,u,e,r[i+12],11,-421815835);e=c(e,v,t,u,r[i+15],16,530742520);u=c(u,e,v,t,r[i+2],23,-995338651);t=h(t,u,e,v,r[i+0],6,-198630844);v=h(v,t,u,e,r[i+7],10,1126891415);e=h(e,v,t,u,r[i+14],15,-1416354905);u=h(u,e,v,t,r[i+5],21,-57434055);t=h(t,u,e,v,r[i+12],6,1700485571);v=h(v,t,u,e,r[i+3],10,-1894986606);e=h(e,v,t,u,r[i+10],15,-1051523);u=h(u,e,v,t,r[i+1],21,-2054922799);t=h(t,u,e,v,r[i+8],6,1873313359);v=h(v,t,u,e,r[i+15],10,-30611744);e=h(e,v,t,u,r[i+6],15,-1560198380);u=h(u,e,v,t,r[i+13],21,1309151649);t=h(t,u,e,v,r[i+4],6,-145523070);v=h(v,t,u,e,r[i+11],10,-1120210379);e=h(e,v,t,u,r[i+2],15,718787259);u=h(u,e,v,t,r[i+9],21,-343485551);t=l(t,s);u=l(u,A);e=l(e,g);v=l(v,b)}if(a==16){return Array(u,e)}else{return Array(t,u,e,v)}}function i(r,n,t,a,u,e){return l(s(l(l(n,r),l(a,e)),u),t)}function f(r,n,t,a,u,e,v){return i(n&t|~n&a,r,n,u,e,v)}function o(r,n,t,a,u,e,v){return i(n&a|t&~a,r,n,u,e,v)}function c(r,n,t,a,u,e,v){return i(n^t^a,r,n,u,e,v)}function h(r,n,t,a,u,e,v){return i(t^(n|~a),r,n,u,e,v)}function l(r,n){var t=(r&65535)+(n&65535);var a=(r>>16)+(n>>16)+(t>>16);return a<<16|t&65535}function s(r,n){return r<<n|r>>>32-n}function A(r){var n=Array();var a=(1<<t)-1;for(var u=0;u<r.length*t;u+=t){n[u>>5]|=(r.charCodeAt(u/t)&a)<<u%32}return n}function g(n){var t=r?"0123456789ABCDEF":"0123456789abcdef";var a="";for(var u=0;u<n.length*4;u++){a+=t.charAt(n[u>>2]>>u%4*8+4&15)+t.charAt(n[u>>2]>>u%4*8&15)}return a}return u}();
  205.  
  206. var $ = window.jQuery
  207. , msg = window.XF.widget.msgbox
  208. , cookie = window.QZFL.cookie
  209.  
  210. // rewrite
  211. QQXF.COMMON.backToLogin = function (time) {
  212. msg.hide()
  213. if (time === 13) return logout() // user click logout
  214.  
  215. var uin = localStorage.getItem('uin')
  216. , passhex = localStorage.getItem('passhex')
  217.  
  218. // autologin
  219. if (uin && passhex) {
  220. msg.show('自动登录中...', 0, 5000, true)
  221. checkVC(uin, function (code, vcode, vc) {
  222. if (code == '0') { // no captcha
  223. login(uin, passhex, vcode, vc)
  224. } else { // captcha
  225. g_pop_login.showVC(function (vcode) {
  226. login(uin, passhex, vcode, vc)
  227. }, uin)
  228. }
  229. })
  230. } else {
  231. // self login
  232. g_pop_login.showLogin(function (uin, pass, vcode, vc, save) {
  233. var passhex = hexchar2bin( md5(pass) )
  234.  
  235. localStorage.setItem('uin', uin)
  236. if (save) { // save pass
  237. localStorage.setItem('passhex', passhex)
  238. }
  239.  
  240. login(uin, passhex, vcode, vc)
  241. }, uin)
  242. }
  243. }
  244.  
  245. // vc
  246. var vcallback
  247. function checkVC(uin, callback) {
  248. vcallback = callback
  249. $.getScript('http://check.ptlogin2.qq.com/check?uin=' +uin)
  250. }
  251. window.checkVC = checkVC // export
  252. // check vc callback
  253. //ptui_checkVC('0','!JTF','\x00\x00\x00\x00\x20\x56\x38\xb0');
  254. window.ptui_checkVC = function (code, vcode, vc) {
  255. vcallback.apply(null, arguments)
  256. }
  257.  
  258. // login main
  259. function login (uin, passhex, vcode, vc) {
  260. $.getScript(['http://ptlogin2.qq.com/login'
  261. , '?u=' +uin
  262. , '&p=' +md5( md5(passhex+vc) +vcode.toUpperCase() )
  263. , '&verifycode=' +vcode
  264.  
  265. // useles but necessary for request
  266. , '&u1=http%3A%2F%2Fqq.com&aid=1&h=1&from_ui=1&g=1'
  267. ].join(''))
  268. }
  269.  
  270. // login callback
  271. // code? ? url ? info usr
  272. //ptuiCB('4','3','','0','登录失败,请重试。*', '100000');
  273. window.ptuiCB = function (code, x, url, x2, tip, usr) {
  274. if (code == '0') {
  275. msg.show(tip, 1, 5000)
  276. } else {
  277. msg.show(tip, 2, 5000)
  278. localStorage.removeItem('passhex')
  279. }
  280.  
  281. setTimeout(function () {
  282. window.location.reload()
  283. }, 800)
  284. }
  285.  
  286.  
  287. // logout main
  288. function logout() {
  289. cookie.del('uin', 'qq.com')
  290. cookie.del('skey', 'qq.com')
  291. localStorage.removeItem('uin')
  292. localStorage.removeItem('passhex')
  293. msg.show('已退出', 3, 2000)
  294. window.location.reload()
  295. }
  296. /// =====
  297. })
  298.  
  299.  
  300. /**
  301. * magnet
  302. */
  303. injectScript(function () {
  304. // ======
  305. var $ = window.jQuery
  306. , msg = window.XF.widget.msgbox
  307.  
  308.  
  309. // orignal code by binux
  310. // https://gist.github.com/binux/4585941
  311. $('#input_tips').text('请输入HTTP/eD2k/magnet链接').each(function () {
  312. var $tips = $(this)
  313. // rewrite
  314. var _info = EventHandler.set_hide_info
  315.  
  316. , input = $('#dl_url_id').get(0)
  317.  
  318. var isMagnet = /^magnet:\?/i
  319. EventHandler.set_hide_info = function () {
  320. var url = input.value//.replace(/,/g, '_')
  321.  
  322. if ( isMagnet.test(url) ) {
  323. addMagnetTask(url)
  324.  
  325. // clean up
  326. input.value = ''
  327. $tips.blur()
  328. } else {
  329. _info.apply(EventHandler, arguments)
  330. }
  331.  
  332. }
  333. })
  334.  
  335.  
  336.  
  337. // mock bt upload function
  338. // extract show bt files select function
  339. var showFileList = (function () {
  340. var AjaxUpload = window.AjaxUpload
  341. var showFileList
  342. window.AjaxUpload = function ($e, options) {
  343. showFileList = options.onComplete
  344. }
  345. window.initTorrent() // call
  346. window.AjaxUpload = AjaxUpload // revert
  347.  
  348. return showFileList
  349. })()
  350.  
  351.  
  352. function addMagnetTask(url) {
  353. window.g_pop_task.hide()
  354. msg.show('解析magnet链接中...', 0, 20000, true)
  355.  
  356. $.ajax({
  357. // callback name is hard coded
  358. url : 'http://pew.rhyzx.im/magnet?callback=?'
  359. , data : { u : url }
  360. , cache : true
  361. , dataType: 'jsonp'
  362. }).done(function (res) {
  363. showFileList(null, JSON.stringify({
  364. ret : 0
  365. , name: res.name
  366. , hash: res.infoHash.toLowerCase()
  367. , files : res.files.map(function (item, i) {
  368. return {
  369. file_index : item.index
  370. , file_name : item.name
  371. , file_size : item.length_f
  372. , file_size_ori : item.length
  373. }
  374. })
  375. }))
  376. }).fail(function ($xhr) {
  377. msg.show('解析magnet链接失败:' + $xhr.responseText, 2, 2000)
  378. })
  379. }
  380.  
  381. /// =====
  382. })
  383.  
  384.  
  385. /**
  386. * fold bt
  387. * TODO update bt info when task update
  388. */
  389. injectScript(function () {
  390. // ======
  391.  
  392. var $ = window.jQuery
  393. , format = new CTaskParaFormat
  394.  
  395. // fix bt fold
  396. var _showList = CTaskOp.prototype.showListFromCache
  397. CTaskOp.prototype.showListFromCache = function (firstGet) {
  398. _showList.call(this, true) // always firstGet
  399. }
  400.  
  401. // rewrite
  402. // add url to new task
  403. var _getInfo = CTaskOp.prototype.getTaskTemplateInfo
  404. CTaskOp.prototype.getTaskTemplateInfo = function (task) {
  405. var info = _getInfo.apply(this, arguments)
  406. if (!task.task_type && !task.file_url) {
  407. info.task_org_url = task.bt_id
  408. }
  409. return info
  410. }
  411.  
  412. // rewrite
  413. var _show = QQVIP.template.show
  414. QQVIP.template.show = function (options) {
  415. var taskList = options.JSON, newList = []
  416.  
  417. var bt // last bt task
  418. , key = 0
  419. for (var i=0, task; task=taskList[i++];) {
  420. // show full name
  421. task.task_short_file_name = task.task_file_name
  422.  
  423. // bt task url pattern: hash_index
  424. // eg. task_org_url: "DB7B0F2264494DAFCD20CACB410399CC65230819_0"
  425. var hash = (task.task_org_url || '').split('_')
  426. if (hash.length > 1) { // is bt
  427. if (!bt || bt.hash !== hash[0]) { // new bt
  428. bt = {
  429. hash : hash[0]
  430. , count : 0
  431. , cloudplayer_status : 'player_hide'
  432. //, cloudplayer_url: '###'
  433. , eyun_status : 'eyun_hide'
  434. //, hash: '181674167CD5C63034A212F2BD120BE8A7D8E5E9'
  435. //, not_empty: ''
  436. , org_file_size : 0
  437. //, player_status: 'player_ok'
  438. //, player_url: 'id=181674167CD5C63034A212F2BD120BE8A7D8E5E9&uin=542521520'
  439. //, task_dl_local_class: ''
  440. , task_dl_speed : 'BT任务'
  441. , task_done_percent : '0%'
  442. //, task_done_percent_class: 'green'
  443. , task_file_name : '[BT]' +task.task_file_name
  444. , task_file_size : '0'
  445. , task_file_type : 'icon_bt'
  446. , task_id : 'bt_' +key++ // key for select
  447. , task_left_days : task.task_left_days
  448. //, task_org_url: '8DAB9FC87D97F44B3C613C4F75D09094E3291DB6_6'
  449. //, task_org_url_class: 'elem_hide'
  450. , task_row_status : 'bt_row'
  451. //, task_share_class: ''
  452. , task_short_file_name : '[BT]' +task.task_file_name
  453. , task_status : 'icon_bt_unfold'
  454. }
  455. newList.push(bt)
  456. }
  457.  
  458. // add class for toggle display
  459. task.task_row_status = (task.task_row_status || '') +' bt_task_row ' + bt.task_id
  460.  
  461. // update bt summary info
  462. bt.count++
  463. bt.org_file_size += task.org_file_size
  464. bt.task_file_size = format.formatFilesize(bt.org_file_size)
  465. var percent = parseInt(bt.task_done_percent)/bt.count * (bt.count- 1)
  466. + parseInt(task.task_done_percent)/bt.count
  467.  
  468. bt.task_done_percent = percent.toFixed(2) +'%'
  469.  
  470.  
  471. bt.task_done_percent_class = bt.task_done_percent === '100%' ? 'green' : ''
  472.  
  473. }
  474.  
  475.  
  476. newList.push(task)
  477. }
  478.  
  479. options.JSON = newList
  480. _show.call(QQVIP.template, options)
  481. }
  482.  
  483. // rewrite
  484. // toggle bt tasks display
  485. var isBt = /^bt_/, $curr = $()
  486. EventHandler.task_op_display = function (obj, taskid) {
  487. var $e = $(obj)
  488.  
  489. // bt row, toggle it's task list
  490. if (taskid.match(isBt)) {
  491. var $items = $('#task_info_body > .' +taskid)
  492.  
  493. var show = !!$e.data('show')
  494. $e.data('show', !show)
  495. show ? $items.hide() : $items.show()
  496.  
  497. // normal task, show info
  498. // default hanlder will clear DOM class
  499. // so show info by self code
  500. } else {
  501. EventHandler.get_http_url(taskid) // show normal download link
  502. $curr.removeClass('bg_curr')
  503. $curr = $e.parent().parent()
  504.  
  505. // only show visible task's info
  506. if ($curr.is(':visible')) $curr.addClass('bg_curr')
  507. }
  508. }
  509.  
  510. // select all in bt
  511. $(document).delegate('.bt_row .seltbox input', 'click', function () {
  512. var $items = $('#task_info_body > .' +this.id.slice(9)) // task_sel_bt_0
  513. $items.find('.seltbox input').attr('checked', this.checked)
  514. EventHandler.set_top_button() // enable/disable export btn
  515. })
  516.  
  517.  
  518. /// =====
  519. })
  520.  
  521.  
  522. /**
  523. * TODO add multi task
  524. */
  525. injectScript(function () {
  526. // ======
  527. var $ = window.jQuery
  528. /// =====
  529. })
  530.  
  531.  
  532.  
  533. /**
  534. * others
  535. */
  536. injectScript(function () {
  537. // ======
  538. var $ = window.jQuery
  539.  
  540. // break normal download restrict
  541. EventHandler.httpDownload = function () {
  542. // big size download will be blocked by default
  543. // just clear this code
  544. }
  545.  
  546. /// =====
  547. })
  548.  
  549.  
  550.  
  551.  
  552.  
  553. /**
  554. * download dialogBox
  555. */
  556. injectScript(function () {
  557. // ======
  558.  
  559. var $ = window.jQuery
  560. , xfDialog= window.xfDialog
  561.  
  562. var $export = $((function () {/*
  563. <div id="ex_pop_export_dl" class="com_win">
  564. <div class="com_win_head_wrap"> <h1><em>导出下载</em> <span class="close_win" title="关闭"><a href="javascript:;"></a></span></h1></div>
  565. <div class="com_win_cont_wrap">
  566. <div class="com_win_cont">
  567. <div class="pop">
  568. <p class="ex_file">
  569. <a class="icon_file ex_file_aria" href="javascript:;" target="_blank"
  570. title="$ aria2c -i aria2.down.txt"
  571. download="aria2.down.txt"
  572. >存为aria2文件</a>
  573. <a class="icon_file ex_file_idm" href="javascript:;" target="_blank"
  574. title="IDM"
  575. download="idm.ef2"
  576. >存为IDM文件</a>
  577. <a class="icon_file ex_file_orbit" href="javascript:;" target="_blank"
  578. title="orbit"
  579. download="orbit.olt"
  580. >存为Orbit文件</a>
  581. </p>
  582. <div class="ex_code">
  583. <textarea readonly wrap="off"></textarea>
  584. </div>
  585. </div>
  586. </div>
  587. </div>
  588. <div class="com_win_foot_wrap"><div class="com_win_foot"></div></div>
  589. </div>
  590. */}).toString().slice(16, -4)).appendTo('#popup_area')
  591.  
  592.  
  593. var $file = $export.find('.ex_file_aria')
  594. , $code = $export.find('.ex_code textarea:first')
  595.  
  596. , $idm = $export.find('.ex_file_idm')
  597. , $orbit= $export.find('.ex_file_orbit')
  598.  
  599. // setup dialog function
  600. var pop = window.g_pop_export = new xfDialog('ex_pop_export_dl')
  601.  
  602.  
  603. pop.setDownloads = function (dls) {
  604. var file = '', code = '', idm = '', orbit = ''
  605.  
  606. for (var i=0, dl; dl=dls[i++];) {
  607. file += [
  608. dl.url
  609. , ' header=Cookie: FTN5K=' +dl.cookie
  610. , ' out=' +dl.filename
  611. , ' continue=true'
  612. , ' max-connection-per-server=10'
  613. , ' split=10'
  614. , '\n'
  615. ].join('\n')
  616.  
  617. code += [
  618. 'aria2c -c -s10 -x10 -o '
  619. , dl.filename
  620. , ' --header '
  621. , 'Cookie: FTN5K=' +dl.cookie
  622. , ' '
  623. , dl.url
  624. , '\n'
  625. ].join('\'')
  626.  
  627. idm += [
  628. '<'
  629. , dl.url //+dl.filename?
  630. , 'cookie: FTN5K=' +dl.cookie
  631. , '>'
  632. , ''
  633. ].join('\r\n')
  634.  
  635. orbit += dl.url
  636. +'|' +dl.filename.replace(/\|/g, '_')
  637. +'||FTN5K=' +dl.cookie
  638. +'\r\n'
  639. }
  640.  
  641. $file.attr('href', 'data:text/plain;charset=utf-8,' +encodeURIComponent(file))
  642. $code.val(code)
  643.  
  644. $idm.attr('href', 'data:text/plain;charset=utf-8,' +encodeURIComponent(idm))
  645. $orbit.attr('href', 'data:text/plain;charset=utf-8,' +encodeURIComponent(orbit))
  646. }
  647.  
  648. /// =====
  649. })
  650.  
  651.  
  652. /**
  653. * rpc config dialogBox
  654. */
  655. injectScript(function () {
  656. // ======
  657.  
  658. var $ = window.jQuery
  659. , xfDialog= window.xfDialog
  660. , msg = window.XF.widget.msgbox
  661.  
  662. var $rpc = $((function () {/*
  663. <div id="ex_rpc_config" class="com_win">
  664. <div class="com_win_head_wrap"> <h1><em>Aria RPC设置</em> <span class="close_win" title="关闭"><a href="###"></a></span></h1></div>
  665. <div class="com_win_cont_wrap">
  666. <div class="com_win_cont">
  667. <div class="pop">
  668. <div class="con">
  669. <form action="#">
  670. <div class="">
  671. <p class="p1"><label>地址:</label><input name="url" type="text"></p>
  672. <p class="p2"><label>Secret Token:</label><input name="token" type="text"></p>
  673. </div>
  674. <p class="discr">
  675. <a href="javascript:;" class="com_opt_btn ok"><span><em>确定</em></span></a>
  676. </p>
  677. </form>
  678. <p style="margin-top:20px"><code>&gt; aria2c --enable-rpc=true --rpc-allow-origin-all=true --rpc-secret=token</code></p>
  679. </div>
  680. </div>
  681. </div>
  682. </div>
  683. <div class="com_win_foot_wrap"><div class="com_win_foot"></div></div>
  684. </div>
  685. */}).toString().slice(16, -4)).appendTo('#popup_area')
  686.  
  687. var pop = window.g_pop_rpc = new xfDialog('ex_rpc_config')
  688.  
  689. var elements = $rpc.find('form:first').get(0).elements
  690. , url = elements.url
  691. , token = elements.token
  692.  
  693.  
  694. pop.showConfig = function (config) {
  695. config = config || {}
  696. url.value = config.url || 'http://localhost:6800/jsonrpc'
  697. token.value = config.token || ''
  698. this.show()
  699. }
  700.  
  701. $rpc.find('.ok:first').click(function () {
  702. pop.hide()
  703. localStorage.setItem('rpc-url', url.value)
  704. localStorage.setItem('rpc-token', token.value)
  705. })
  706.  
  707. /// =====
  708. })
  709.  
  710.  
  711. /**
  712. * login dialogBox
  713. */
  714. injectScript(function () {
  715. // ======
  716.  
  717. var $ = window.jQuery
  718. , xfDialog= window.xfDialog
  719. , msg = window.XF.widget.msgbox
  720.  
  721. var $login = $((function () {/*
  722. <div id="login_win" class="com_win">
  723. <div class="com_win_head_wrap"> <h1><em>登录</em> <span class="close_win" title="关闭"><a href="###"></a></span></h1></div>
  724. <div class="com_win_cont_wrap">
  725. <div class="com_win_cont">
  726. <div class="pop">
  727. <div class="con">
  728. <form action="#">
  729. <div class="ex_login_area">
  730. <p class="p1"><label>QQ帐号:</label><input name="uin" type="text"></p>
  731. <p class="p2"><label>QQ密码:</label><input name="pass" type="password"></p>
  732. </div>
  733. <div class="ex_vc_area" style="display:none">
  734. <p class="p2" style="">
  735. <label>验证码:</label>
  736. <input class="ex_vcode" name="vcode" type="text" />
  737. <img class="ex_vimg" width="130" height="53">
  738. </p>
  739. </div>
  740. <p class="discr">
  741. <a href="javascript:;" class="ex_login_btn com_opt_btn"><span><em>登录</em></span></a>
  742. <span class="ex_login_area">
  743. <input class="ex_check_box" name="save" type="checkbox">
  744. <span>自动登录</span>
  745. </span>
  746. </p>
  747. </form>
  748. </div>
  749. </div>
  750. </div>
  751. </div>
  752. <div class="com_win_foot_wrap"><div class="com_win_foot"></div></div>
  753. </div>
  754. */}).toString().slice(16, -4)).appendTo('#popup_area')
  755.  
  756. var pop = window.g_pop_login = new xfDialog('login_win')
  757.  
  758. var elements = $login.find('form:first').get(0).elements
  759.  
  760. var $vcArea = $login.find('.ex_vc_area')
  761. , $loginArea = $login.find('.ex_login_area')
  762.  
  763. var $vimg = $login.find('.ex_vimg').click(function () {
  764. // refresh captcha pic
  765. this.src = 'http://captcha.qq.com/getimage?uin='
  766. +this.getAttribute('data-uin')
  767. +'&' +Date.now()
  768. })
  769.  
  770.  
  771. var action, vc
  772. $login.find('.ex_login_btn').click(function () {
  773. pop.hide()
  774. msg.show('登录中...', 0, 5000, true)
  775. action()
  776. })
  777.  
  778. // only show vc dialog
  779. pop.showVC = function (callback, uin) {
  780. action = function () {
  781. callback(elements.vcode.value)
  782. }
  783. $loginArea.hide()
  784. $vcArea.show()
  785. $vimg.attr('data-uin', uin).click()
  786. pop.show()
  787. }
  788.  
  789.  
  790. // show login dialog
  791. pop.showLogin = function (callback, uin) {
  792. action = function () {
  793. callback(elements.uin.value, elements.pass.value, elements.vcode.value, vc, elements.save.checked)
  794. }
  795. pop.show()
  796.  
  797. // set uin and checkVC
  798. if (uin) $(elements.uin).val(uin).change()
  799. }
  800.  
  801.  
  802. // check vc when qq changed
  803. $(elements.uin).change(function () {
  804. var uin = this.value
  805. if (uin.length > 4) {
  806. msg.show('检测帐号中...', 0, 5000)
  807. checkVC(uin, function (code, vcode, _vc) {
  808. msg.hide()
  809. vc = _vc
  810.  
  811. if (code == '0') { // no captcha
  812. $vcArea.hide()
  813. elements.vcode.value = vcode
  814. } else { // need captcha
  815. $vcArea.show()
  816. $vimg.attr('data-uin', uin).click() // show pic
  817. }
  818. })
  819. }
  820. })
  821.  
  822. /// =====
  823. })
  824.  
  825.  
  826. /**
  827. * overwrite CSS
  828. */
  829. injectStyle((function () {/*
  830. .top,
  831. .search_box,
  832. #share_opt,
  833. #down_box {
  834. display: none !important;
  835. }
  836. #cont_wrap, #tbl_tpl_id, .box, .filename em {
  837. width: auto !important;
  838. }
  839.  
  840. .main {
  841. width: auto;
  842. margin-left: 50px;
  843. margin-right: 50px;
  844. }
  845. .tablebox .tit_h th {
  846. background-repeat: repeat;
  847. }
  848.  
  849.  
  850. #ex_pop_export_dl {
  851. position: absolute;
  852. top: 200px;
  853. left: 50%;
  854. width: 640px;
  855. margin-left: -320px;
  856. text-align: left;
  857. color: #2d5b7c;
  858. z-index: 102;
  859. background: #FFF;
  860. overflow: hidden;
  861. }
  862. .ex_file {
  863. margin: 8px;
  864. }
  865. .ex_file a {
  866. display: inline-block;
  867. margin-right: 14px;
  868. outline: none;
  869. }
  870. .ex_code {
  871. margin: 0 8px;
  872. border: 1px solid #C7E2F1;
  873. border-raduis: 4px;
  874. }
  875. .ex_code textarea {
  876. width: 100%;
  877. height: 180px;
  878. font: 12px/1.5 monospace;
  879. border: none;
  880. }
  881. #login_win input {
  882. padding: 0 5px;
  883. width: 220px;
  884. background: #FFF;
  885. }
  886. #login_win .ex_vcode {
  887. display: inline-block;
  888. width: 80px;
  889. }
  890. #login_win .ex_check_box {
  891. width: 16px;
  892. }
  893. .ex_login_btn {
  894. float: none;
  895. }
  896. .ex_vimg {
  897. vertical-align: middle;
  898. }
  899.  
  900. .bt_row {
  901. background: #f6fef8;
  902. }
  903. .bt_task_row {
  904. display: none;
  905. }
  906. .bt_task_row td:first-child ,
  907. .bt_row td:first-child {
  908. border-left: 3px solid #9fe5b1;
  909. }
  910. .bt_task_row .seltbox input {
  911. margin-left: 20px;
  912. }
  913. .icon_bt {
  914. padding-left: 20px;
  915. height: 16px;
  916. line-height: 16px;
  917. font-style: normal;
  918. background-repeat: no-repeat;
  919. background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGrSURBVDjLxZO7ihRBFIa/6u0ZW7GHBUV0UQQTZzd3QdhMQxOfwMRXEANBMNQX0MzAzFAwEzHwARbNFDdwEd31Mj3X7a6uOr9BtzNjYjKBJ6nicP7v3KqcJFaxhBVtZUAK8OHlld2st7Xl3DJPVONP+zEUV4HqL5UDYHr5xvuQAjgl/Qs7TzvOOVAjxjlC+ePSwe6DfbVegLVuT4r14eTr6zvA8xSAoBLzx6pvj4l+DZIezuVkG9fY2H7YRQIMZIBwycmzH1/s3F8AapfIPNF3kQk7+kw9PWBy+IZOdg5Ug3mkAATy/t0usovzGeCUWTjCz0B+Sj0ekfdvkZ3abBv+U4GaCtJ1iEm6ANQJ6fEzrG/engcKw/wXQvEKxSEKQxRGKE7Izt+DSiwBJMUSm71rguMYhQKrBygOIRStf4TiFFRBvbRGKiQLWP29yRSHKBTtfdBmHs0BUpgvtgF4yRFR+NUKi0XZcYjCeCG2smkzLAHkbRBmP0/Uk26O5YnUActBp1GsAI+S5nRJJJal5K1aAMrq0d6Tm9uI6zjyf75dAe6tx/SsWeD//o2/Ab6IH3/h25pOAAAAAElFTkSuQmCC)
  920. }
  921.  
  922. .bg_curr {
  923. pointer: normal !important;
  924. background: #d2eeff !important;
  925. }
  926. .bg_curr .p2 {
  927. display: block !important;
  928. }
  929. #ex_rpc_config {
  930. width: 460px;
  931. margin-left: -230px;
  932. }
  933. */}).toString().slice(16, -4)) // extract css in function
  934.  
  935.  
  936.  
  937.  
  938.  
  939. // execute code in the content page scope
  940. function injectScript(source) {
  941. var script = document.createElement('script')
  942. script.setAttribute('type', 'text/javascript')
  943. script.textContent = ';(' + source.toString() + ')()'
  944.  
  945. document.body.appendChild(script)
  946. document.body.removeChild(script)
  947. }
  948.  
  949. // insert css
  950. function injectStyle(css) {
  951. var script = document.createElement('style')
  952. script.setAttribute('type', 'text/css')
  953. script.textContent = css
  954. document.head.appendChild(script)
  955. }