XuanFengEx

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

目前为 2014-06-14 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name XuanFengEx
  3. // @namespace https://github.com/rhyzx/xuanfeng-userscript
  4. // @version 0.7.3
  5. // @description QQ旋风网页版离线下载增强
  6. // @match http://lixian.qq.com/main.html*
  7. // @copyright 2013+, 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. requestDownloadLinks(function (dls) {
  26. msg.hide()
  27. g_pop_export.setDownloads(dls)
  28. g_pop_export.show()
  29. })
  30. }
  31.  
  32.  
  33.  
  34. // get selected tasks' download link/cookie/filename
  35. // callback(dowloads)
  36. function requestDownloadLinks(callback) {
  37. var count = 0
  38. , downloads = []
  39.  
  40. $.getJSON('/handler/lixian/get_lixian_status.php'/*, {mids : [ids]} NOUSE*/)
  41. .done(function (res) {
  42. $.each(res.data, function (i, task) {
  43. // check
  44. if (
  45. !$('#task_sel_' +task.mid).is(':checked')|| // user selected
  46. task.file_size !== task.comp_size || // download finished
  47. task.dl_status !== TASK_STATUS['ST_UL_OK']
  48. ) return
  49.  
  50. count++
  51. $.post('/handler/lixian/get_http_url.php', {
  52. hash : task.hash
  53. , filename: task.file_name
  54. //, g_tk : getACSRFToken(cookie.get('skey', 'qq.com'))
  55. //, browser : 'other'
  56. }, null, 'json')
  57. .done(function (res) {
  58. count--
  59. if (res && res.ret === 0) {
  60. // break speed limit
  61. // thanks @4023 https://userscripts.org/users/381599
  62. var url = res.data.com_url
  63. .replace('xflx.store.cd.qq.com:443', 'xfcd.ctfs.ftn.qq.com')
  64. .replace('xflx.sz.ftn.qq.com:80', 'sz.disk.ftn.qq.com')
  65. .replace('xflx.cd.ftn.qq.com:80', 'cd.ctfs.ftn.qq.com')
  66. .replace('xflxsrc.store.qq.com:443', 'xfxa.ctfs.ftn.qq.com')
  67.  
  68. downloads.push({
  69. url : url
  70. , cookie : res.data.com_cookie
  71. , filename : task.file_name
  72. })
  73. }
  74. })
  75. .fail(function () {
  76. msg.show('获取失败', 2, 2000)
  77. })
  78. .always(function () {
  79. if (count === 0) {
  80. // sort according to filename
  81. downloads.sort(function (a, b) {
  82. return a.filename.localeCompare(b.filename)
  83. })
  84. callback(downloads)
  85. }
  86. })
  87.  
  88. })
  89. })
  90. .fail(function () {
  91. msg.show('获取列表的接口坏了嘛?! 请联系脚本作者', 2, 2000)
  92. })
  93. }
  94. window.requestDownloadLinks = requestDownloadLinks // export to global
  95.  
  96. /// =====
  97. })
  98.  
  99.  
  100. /**
  101. * aria rpc
  102. */
  103. injectScript(function recall() {
  104. // ======
  105.  
  106. var $ = window.jQuery
  107. , msg = window.XF.widget.msgbox
  108.  
  109.  
  110. // button
  111. var $export = $('#task_dl_local')
  112. var $rpc = $export.clone()
  113. .removeAttr('onclick')
  114. .attr('id', 'task_dl_rpc')
  115. .find('em').text('RPC').end()
  116. .insertAfter($export)
  117.  
  118. // diable/enable botton
  119. $(document).click(function () {
  120. $export.hasClass('disabled_btn')
  121. ? $rpc.addClass('disabled_btn')
  122. : $rpc.removeClass('disabled_btn')
  123. })
  124.  
  125.  
  126. $rpc.click(function (evt) {
  127. if ($rpc.hasClass('disabled_btn')) return
  128.  
  129. var config = {
  130. url : localStorage.getItem('rpc-url')
  131. , user: localStorage.getItem('rpc-user')
  132. , pass: localStorage.getItem('rpc-pass')
  133. }
  134. if (config.url) {
  135. msg.show('获取下载地址中...', 0, 5000)
  136. requestDownloadLinks(function (dls) {
  137. msg.show('rpc请求中...', 0, 5000)
  138.  
  139. rpc(dls, config)
  140. .done(function () {
  141. msg.show('成功', 1, 2000)
  142. })
  143. .fail(function () {
  144. msg.show('rpc请求失败,请检查设置', 2, 2000)
  145. g_pop_rpc.showConfig(config)
  146. })
  147. })
  148. } else {
  149. msg.show('rpc未设置', 3, 2000)
  150. g_pop_rpc.showConfig() // default url
  151. }
  152. })
  153.  
  154.  
  155. function rpc(dls, config) {
  156. var data = []
  157. $.each(dls, function (k, dl) {
  158. data.push({
  159. jsonrpc : '2.0'
  160. , id : 'down_' +k
  161. , method : 'aria2.addUri'
  162. , params : [
  163. [dl.url]
  164. , {
  165. out : dl.filename
  166. , header : 'Cookie: FTN5K=' +dl.cookie
  167. , continue: 'true'
  168. , split : '10'
  169. , 'max-connection-per-server' : '10'
  170. }
  171. ]
  172. })
  173. })
  174.  
  175. // http authorization
  176. var beforeSend
  177. if (config.user) {
  178. if (typeof btoa !== 'function') return alert('你的浏览器不支持验证,请不要设置用户名和密码')
  179. beforeSend = function (xhr) {
  180. xhr.setRequestHeader(
  181. 'Authorization',
  182. 'Basic ' +btoa( config.user +':' +config.pass )
  183. )
  184. }
  185. }
  186.  
  187. // return Deferred Obj
  188. return $.ajax(config.url, {
  189. data : JSON.stringify(data)
  190. , type : 'POST'
  191. , cache : false
  192. , beforeSend : beforeSend
  193. })
  194. }
  195.  
  196. /// =====
  197. })
  198.  
  199.  
  200. /**
  201. * auto login
  202. */
  203. injectScript(function recall() {
  204. // ======
  205.  
  206. // function from http://imgcache.qq.com/ptlogin/ver/10021/js/comm.js
  207. 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}
  208. 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}();
  209.  
  210. var $ = window.jQuery
  211. , msg = window.XF.widget.msgbox
  212. , cookie = window.QZFL.cookie
  213.  
  214. // rewrite
  215. QQXF.COMMON.backToLogin = function (time) {
  216. msg.hide()
  217. if (time === 13) return logout() // user click logout
  218.  
  219. var uin = localStorage.getItem('uin')
  220. , passhex = localStorage.getItem('passhex')
  221.  
  222. // autologin
  223. if (uin && passhex) {
  224. msg.show('自动登录中...', 0, 5000, true)
  225. checkVC(uin, function (code, vcode, vc) {
  226. if (code == '0') { // no captcha
  227. login(uin, passhex, vcode, vc)
  228. } else { // captcha
  229. g_pop_login.showVC(function (vcode) {
  230. login(uin, passhex, vcode, vc)
  231. }, uin)
  232. }
  233. })
  234. } else {
  235. // self login
  236. g_pop_login.showLogin(function (uin, pass, vcode, vc, save) {
  237. var passhex = hexchar2bin( md5(pass) )
  238. localStorage.setItem('uin', uin)
  239. if (save) { // save pass
  240. localStorage.setItem('passhex', passhex)
  241. }
  242.  
  243. login(uin, passhex, vcode, vc)
  244. }, uin)
  245. }
  246. }
  247.  
  248. // vc
  249. var vcallback
  250. function checkVC(uin, callback) {
  251. vcallback = callback
  252. $.getScript('http://check.ptlogin2.qq.com/check?uin=' +uin)
  253. }
  254. window.checkVC = checkVC // export
  255. // check vc callback
  256. //ptui_checkVC('0','!JTF','\x00\x00\x00\x00\x20\x56\x38\xb0');
  257. window.ptui_checkVC = function (code, vcode, vc) {
  258. vcallback.apply(null, arguments)
  259. }
  260.  
  261. // login main
  262. function login (uin, passhex, vcode, vc) {
  263. $.getScript(['http://ptlogin2.qq.com/login'
  264. , '?u=' +uin
  265. , '&p=' +md5( md5(passhex+vc) +vcode.toUpperCase() )
  266. , '&verifycode=' +vcode
  267.  
  268. // useles but necessary for request
  269. , '&u1=http%3A%2F%2Fqq.com&aid=1&h=1&from_ui=1&g=1'
  270. ].join(''))
  271. }
  272.  
  273. // login callback
  274. // code? ? url ? info usr
  275. //ptuiCB('4','3','','0','登录失败,请重试。*', '100000');
  276. window.ptuiCB = function (code, x, url, x2, tip, usr) {
  277. if (code == '0') {
  278. msg.show(tip, 1, 5000)
  279. } else {
  280. msg.show(tip, 2, 5000)
  281. localStorage.removeItem('passhex')
  282. }
  283.  
  284. setTimeout(function () {
  285. window.location.reload()
  286. }, 800)
  287. }
  288.  
  289.  
  290. // logout main
  291. function logout() {
  292. cookie.del('uin', 'qq.com')
  293. cookie.del('skey', 'qq.com')
  294. localStorage.removeItem('uin')
  295. localStorage.removeItem('passhex')
  296. msg.show('已退出', 3, 2000)
  297. window.location.reload()
  298. }
  299. /// =====
  300. })
  301.  
  302.  
  303. /**
  304. * magnet
  305. */
  306. injectScript(function () {
  307. // ======
  308. var $ = window.jQuery
  309. , msg = window.XF.widget.msgbox
  310.  
  311.  
  312. // orignal code by binux
  313. // https://gist.github.com/binux/4585941
  314. $('#input_tips').text('请输入HTTP/eD2k/magnet链接').each(function () {
  315. var $tips = $(this)
  316. // rewrite
  317. var _info = EventHandler.set_hide_info
  318.  
  319. , input = $('#dl_url_id').get(0)
  320. var isMagnet = /^magnet:\?/i
  321. EventHandler.set_hide_info = function () {
  322. var url = input.value//.replace(/,/g, '_')
  323.  
  324. if ( isMagnet.test(url) ) {
  325. addMagnetTask(url)
  326.  
  327. // clean up
  328. input.value = ''
  329. $tips.blur()
  330. } else {
  331. _info.apply(EventHandler, arguments)
  332. }
  333.  
  334. }
  335. })
  336.  
  337.  
  338.  
  339. // mock bt upload function
  340. // extract show bt files select function
  341. var showFileList = (function () {
  342. var AjaxUpload = window.AjaxUpload
  343. var showFileList
  344. window.AjaxUpload = function ($e, options) {
  345. showFileList = options.onComplete
  346. }
  347. window.initTorrent() // call
  348. window.AjaxUpload = AjaxUpload // revert
  349.  
  350. return showFileList
  351. })()
  352.  
  353.  
  354. function addMagnetTask(url) {
  355. window.g_pop_task.hide()
  356. msg.show('解析magnet链接中...', 0, 20000, true)
  357.  
  358. $.ajax({
  359. // callback name is hard coded
  360. url : 'http://pew.rhyzx.im/magnet?callback=?'
  361. , data : { u : url }
  362. , cache : true
  363. , dataType: 'jsonp'
  364. }).done(function (res) {
  365. showFileList(null, JSON.stringify({
  366. ret : 0
  367. , name: res.name
  368. , hash: res.infoHash.toLowerCase()
  369. , files : res.files.map(function (item, i) {
  370. return {
  371. file_index : item.index
  372. , file_name : item.name
  373. , file_size : item.length_f
  374. , file_size_ori : item.length
  375. }
  376. })
  377. }))
  378. }).fail(function ($xhr) {
  379. msg.show('解析magnet链接失败:' + $xhr.responseText, 2, 2000)
  380. })
  381. }
  382.  
  383. /// =====
  384. })
  385.  
  386.  
  387. /**
  388. * fold bt
  389. * TODO update bt info when task update
  390. */
  391. injectScript(function () {
  392. // ======
  393.  
  394. var $ = window.jQuery
  395. , format = new CTaskParaFormat
  396.  
  397. // fix bt fold
  398. var _showList = CTaskOp.prototype.showListFromCache
  399. CTaskOp.prototype.showListFromCache = function (firstGet) {
  400. _showList.call(this, true) // always firstGet
  401. }
  402.  
  403. // rewrite
  404. // add url to new task
  405. var _getInfo = CTaskOp.prototype.getTaskTemplateInfo
  406. CTaskOp.prototype.getTaskTemplateInfo = function (task) {
  407. var info = _getInfo.apply(this, arguments)
  408. if (!task.task_type && !task.file_url) {
  409. info.task_org_url = task.bt_id
  410. }
  411. return info
  412. }
  413.  
  414. // rewrite
  415. var _show = QQVIP.template.show
  416. QQVIP.template.show = function (options) {
  417. var taskList = options.JSON, newList = []
  418.  
  419. var bt // last bt task
  420. , key = 0
  421. for (var i=0, task; task=taskList[i++];) {
  422. // show full name
  423. task.task_short_file_name = task.task_file_name
  424.  
  425. // bt task url pattern: hash_index
  426. // eg. task_org_url: "DB7B0F2264494DAFCD20CACB410399CC65230819_0"
  427. var hash = (task.task_org_url || '').split('_')
  428. if (hash.length > 1) { // is bt
  429. if (!bt || bt.hash !== hash[0]) { // new bt
  430. bt = {
  431. hash : hash[0]
  432. , count : 0
  433. , cloudplayer_status : 'player_hide'
  434. //, cloudplayer_url: '###'
  435. , eyun_status : 'eyun_hide'
  436. //, hash: '181674167CD5C63034A212F2BD120BE8A7D8E5E9'
  437. //, not_empty: ''
  438. , org_file_size : 0
  439. //, player_status: 'player_ok'
  440. //, player_url: 'id=181674167CD5C63034A212F2BD120BE8A7D8E5E9&uin=542521520'
  441. //, task_dl_local_class: ''
  442. , task_dl_speed : 'BT任务'
  443. , task_done_percent : '0%'
  444. //, task_done_percent_class: 'green'
  445. , task_file_name : '[BT]' +task.task_file_name
  446. , task_file_size : '0'
  447. , task_file_type : 'icon_bt'
  448. , task_id : 'bt_' +key++ // key for select
  449. , task_left_days : task.task_left_days
  450. //, task_org_url: '8DAB9FC87D97F44B3C613C4F75D09094E3291DB6_6'
  451. //, task_org_url_class: 'elem_hide'
  452. , task_row_status : 'bt_row'
  453. //, task_share_class: ''
  454. , task_short_file_name : '[BT]' +task.task_file_name
  455. , task_status : 'icon_bt_unfold'
  456. }
  457. newList.push(bt)
  458. }
  459.  
  460. // add class for toggle display
  461. task.task_row_status = (task.task_row_status || '') +' bt_task_row ' + bt.task_id
  462.  
  463. // update bt summary info
  464. bt.count++
  465. bt.org_file_size += task.org_file_size
  466. bt.task_file_size = format.formatFilesize(bt.org_file_size)
  467. var percent = parseInt(bt.task_done_percent)/bt.count * (bt.count- 1)
  468. + parseInt(task.task_done_percent)/bt.count
  469.  
  470. bt.task_done_percent = percent.toFixed(2) +'%'
  471.  
  472.  
  473. bt.task_done_percent_class = bt.task_done_percent === '100%' ? 'green' : ''
  474. }
  475.  
  476.  
  477. newList.push(task)
  478. }
  479.  
  480. options.JSON = newList
  481. _show.call(QQVIP.template, options)
  482. }
  483.  
  484. // rewrite
  485. // toggle bt tasks display
  486. var isBt = /^bt_/, $curr = $()
  487. EventHandler.task_op_display = function (obj, taskid) {
  488. var $e = $(obj)
  489.  
  490. // bt row, toggle it's task list
  491. if (taskid.match(isBt)) {
  492. var $items = $('#task_info_body > .' +taskid)
  493.  
  494. var show = !!$e.data('show')
  495. $e.data('show', !show)
  496. show ? $items.hide() : $items.show()
  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>用户:</label><input name="user" type="text"></p>
  673. <p class="p2"><label>密码:</label><input name="pass" type="password"></p>
  674. </div>
  675. <p class="discr">
  676. <a href="javascript:;" class="com_opt_btn ok"><span><em>确定</em></span></a>
  677. </p>
  678. </form>
  679. <p style="margin-top:20px"><code>&gt; aria2c --enable-rpc=true --rpc-allow-origin-all=true --rpc-user=test --rpc-passwd=123</code></p>
  680. </div>
  681. </div>
  682. </div>
  683. </div>
  684. <div class="com_win_foot_wrap"><div class="com_win_foot"></div></div>
  685. </div>
  686. */}).toString().slice(16, -4)).appendTo('#popup_area')
  687.  
  688. var pop = window.g_pop_rpc = new xfDialog('ex_rpc_config')
  689.  
  690. var elements = $rpc.find('form:first').get(0).elements
  691. , url = elements.url
  692. , user = elements.user
  693. , pass = elements.pass
  694.  
  695.  
  696. pop.showConfig = function (config) {
  697. config = config || {}
  698. url.value = config.url || 'http://localhost:6800/jsonrpc'
  699. user.value = config.user || ''
  700. pass.value = config.pass || ''
  701. this.show()
  702. }
  703.  
  704. $rpc.find('.ok:first').click(function () {
  705. pop.hide()
  706. localStorage.setItem('rpc-url', url.value)
  707. localStorage.setItem('rpc-user', user.value)
  708. localStorage.setItem('rpc-pass', pass.value)
  709. })
  710.  
  711. /// =====
  712. })
  713.  
  714.  
  715. /**
  716. * login dialogBox
  717. */
  718. injectScript(function () {
  719. // ======
  720.  
  721. var $ = window.jQuery
  722. , xfDialog= window.xfDialog
  723. , msg = window.XF.widget.msgbox
  724.  
  725. var $login = $((function () {/*
  726. <div id="login_win" class="com_win">
  727. <div class="com_win_head_wrap"> <h1><em>登录</em> <span class="close_win" title="关闭"><a href="###"></a></span></h1></div>
  728. <div class="com_win_cont_wrap">
  729. <div class="com_win_cont">
  730. <div class="pop">
  731. <div class="con">
  732. <form action="#">
  733. <div class="ex_login_area">
  734. <p class="p1"><label>QQ帐号:</label><input name="uin" type="text"></p>
  735. <p class="p2"><label>QQ密码:</label><input name="pass" type="password"></p>
  736. </div>
  737. <div class="ex_vc_area" style="display:none">
  738. <p class="p2" style="">
  739. <label>验证码:</label>
  740. <input class="ex_vcode" name="vcode" type="text" />
  741. <img class="ex_vimg" width="130" height="53">
  742. </p>
  743. </div>
  744. <p class="discr">
  745. <a href="javascript:;" class="ex_login_btn com_opt_btn"><span><em>登录</em></span></a>
  746. <span class="ex_login_area">
  747. <input class="ex_check_box" name="save" type="checkbox">
  748. <span>自动登录</span>
  749. </span>
  750. </p>
  751. </form>
  752. </div>
  753. </div>
  754. </div>
  755. </div>
  756. <div class="com_win_foot_wrap"><div class="com_win_foot"></div></div>
  757. </div>
  758. */}).toString().slice(16, -4)).appendTo('#popup_area')
  759.  
  760. var pop = window.g_pop_login = new xfDialog('login_win')
  761.  
  762. var elements = $login.find('form:first').get(0).elements
  763.  
  764. var $vcArea = $login.find('.ex_vc_area')
  765. , $loginArea = $login.find('.ex_login_area')
  766.  
  767. var $vimg = $login.find('.ex_vimg').click(function () {
  768. // refresh captcha pic
  769. this.src = 'http://captcha.qq.com/getimage?uin='
  770. +this.getAttribute('data-uin')
  771. +'&' +Date.now()
  772. })
  773.  
  774.  
  775. var action, vc
  776. $login.find('.ex_login_btn').click(function () {
  777. pop.hide()
  778. msg.show('登录中...', 0, 5000, true)
  779. action()
  780. })
  781.  
  782. // only show vc dialog
  783. pop.showVC = function (callback, uin) {
  784. action = function () {
  785. callback(elements.vcode.value)
  786. }
  787. $loginArea.hide()
  788. $vcArea.show()
  789. $vimg.attr('data-uin', uin).click()
  790. pop.show()
  791. }
  792.  
  793.  
  794. // show login dialog
  795. pop.showLogin = function (callback, uin) {
  796. action = function () {
  797. callback(elements.uin.value, elements.pass.value, elements.vcode.value, vc, elements.save.checked)
  798. }
  799. pop.show()
  800.  
  801. // set uin and checkVC
  802. if (uin) $(elements.uin).val(uin).change()
  803. }
  804.  
  805.  
  806. // check vc when qq changed
  807. $(elements.uin).change(function () {
  808. var uin = this.value
  809. if (uin.length > 4) {
  810. msg.show('检测帐号中...', 0, 5000)
  811. checkVC(uin, function (code, vcode, _vc) {
  812. msg.hide()
  813. vc = _vc
  814. if (code == '0') { // no captcha
  815. $vcArea.hide()
  816. elements.vcode.value = vcode
  817. } else { // need captcha
  818. $vcArea.show()
  819. $vimg.attr('data-uin', uin).click() // show pic
  820. }
  821. })
  822. }
  823. })
  824.  
  825. /// =====
  826. })
  827.  
  828.  
  829. /**
  830. * overwrite CSS
  831. */
  832. injectStyle((function () {/*
  833. .top,
  834. .search_box,
  835. #share_opt,
  836. #down_box {
  837. display: none !important;
  838. }
  839. #cont_wrap, #tbl_tpl_id, .box, .filename em {
  840. width: auto !important;
  841. }
  842.  
  843. .main {
  844. width: auto;
  845. margin-left: 50px;
  846. margin-right: 50px;
  847. }
  848. .tablebox .tit_h th {
  849. background-repeat: repeat;
  850. }
  851.  
  852.  
  853. #ex_pop_export_dl {
  854. position: absolute;
  855. top: 200px;
  856. left: 50%;
  857. width: 640px;
  858. margin-left: -320px;
  859. text-align: left;
  860. color: #2d5b7c;
  861. z-index: 102;
  862. background: #FFF;
  863. overflow: hidden;
  864. }
  865. .ex_file {
  866. margin: 8px;
  867. }
  868. .ex_file a {
  869. display: inline-block;
  870. margin-right: 14px;
  871. outline: none;
  872. }
  873. .ex_code {
  874. margin: 0 8px;
  875. border: 1px solid #C7E2F1;
  876. border-raduis: 4px;
  877. }
  878. .ex_code textarea {
  879. width: 100%;
  880. height: 180px;
  881. font: 12px/1.5 monospace;
  882. border: none;
  883. }
  884. #login_win input {
  885. padding: 0 5px;
  886. width: 220px;
  887. background: #FFF;
  888. }
  889. #login_win .ex_vcode {
  890. display: inline-block;
  891. width: 80px;
  892. }
  893. #login_win .ex_check_box {
  894. width: 16px;
  895. }
  896. .ex_login_btn {
  897. float: none;
  898. }
  899. .ex_vimg {
  900. vertical-align: middle;
  901. }
  902.  
  903. .bt_row {
  904. background: #f6fef8;
  905. }
  906. .bt_task_row {
  907. display: none;
  908. }
  909. .bt_task_row td:first-child ,
  910. .bt_row td:first-child {
  911. border-left: 3px solid #9fe5b1;
  912. }
  913. .bt_task_row .seltbox input {
  914. margin-left: 20px;
  915. }
  916. .icon_bt {
  917. padding-left: 20px;
  918. height: 16px;
  919. line-height: 16px;
  920. font-style: normal;
  921. background-repeat: no-repeat;
  922. 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)
  923. }
  924.  
  925. .bg_curr {
  926. pointer: normal !important;
  927. background: #d2eeff !important;
  928. }
  929. .bg_curr .p2 {
  930. display: block !important;
  931. }
  932. #ex_rpc_config {
  933. width: 460px;
  934. margin-left: -230px;
  935. }
  936. */}).toString().slice(16, -4)) // extract css in function
  937.  
  938.  
  939.  
  940.  
  941.  
  942. // execute code in the content page scope
  943. function injectScript(source) {
  944. var script = document.createElement('script')
  945. script.setAttribute('type', 'text/javascript')
  946. script.textContent = ';(' + source.toString() + ')()'
  947.  
  948. document.body.appendChild(script)
  949. document.body.removeChild(script)
  950. }
  951.  
  952. // insert css
  953. function injectStyle(css) {
  954. var script = document.createElement('style')
  955. script.setAttribute('type', 'text/css')
  956. script.textContent = css
  957. document.head.appendChild(script)
  958. }