PTH Collector

Download multiple torrents by some criteria on PTH

当前为 2018-10-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name PTH Collector
  3. // @version 1.7
  4. // @description Download multiple torrents by some criteria on PTH
  5. // @author Chameleon
  6. // @include http*://redacted.ch/*
  7. // @grant none
  8. // @require https://greasyfork.org/scripts/19855-jszip/code/jszip.js?version=126859
  9. // @namespace https://greasyfork.org/users/87476
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. var wH=window.location.href;
  16. if(wH.indexOf('artist.php?id=') != -1)
  17. {
  18. addToX(compileArtist);
  19. }
  20. else if(wH.indexOf('threadid=3543') != -1)
  21. showSettings();
  22. else if(wH.indexOf('collages.php?id=') != -1)
  23. addToX(compileCollage);
  24. else if(wH.indexOf('bookmarks.php?type=torrents') != -1)
  25. addToX(compileCollage.bind('Bookmarks'));
  26. //else if(wH.indexOf('torrents.php') != -1 && wH.indexOf('?id=') == -1)
  27. //addToSearch();
  28. })();
  29.  
  30. function addToSearch()
  31. {
  32. var sidebar=document.createElement('div');
  33. sidebar.setAttribute('class', 'sidebar');
  34. sidebar.setAttribute('style', 'float: initial; margin: auto;');
  35. /*var left=(document.body.clientWidth/2)+425;
  36. sidebar.setAttribute('style', 'position: absolute; left: '+left+'px;');
  37. var before=document.getElementsByClassName('header')[0].nextElementSibling;
  38. before.parentNode.insertBefore(sidebar, before);*/
  39. document.getElementsByClassName('thin')[0].appendChild(sidebar);
  40. addToX(compileCollage.bind('Search'));
  41. }
  42.  
  43. function showSettings()
  44. {
  45. var div=document.getElementById('collectorSettings');
  46. if(!div)
  47. {
  48. var before = document.getElementsByClassName('forum_post')[0];
  49. div = document.createElement('div');
  50. div.setAttribute('id', 'collectorSettings');
  51. before.parentNode.insertBefore(div, before);
  52. div.setAttribute('style', 'width: 100%; text-align: center; padding-bottom: 10px;');
  53. div.setAttribute('class', 'box');
  54. }
  55. div.innerHTML = '<h2>Collector Settings</h2><br />';
  56. var settings = getSettings();
  57.  
  58. var a=document.createElement('a');
  59. a.href='javascript:void(0);';
  60. a.innerHTML = 'Sequential torrent download: '+(settings.sequential ? 'On':'Off');
  61. a.addEventListener('click', changeLink.bind(undefined, a, div), false);
  62. div.appendChild(a);
  63. div.appendChild(document.createElement('br'));
  64.  
  65. var a=document.createElement('a');
  66. a.href='javascript:void(0);';
  67. a.innerHTML = 'Include summary txt in .zip: '+(settings.summary ? 'On':'Off');
  68. a.addEventListener('click', changeLink.bind(undefined, a, div), false);
  69. div.appendChild(a);
  70. div.appendChild(document.createElement('br'));
  71. }
  72.  
  73. function changeLink(a, div)
  74. {
  75. if(a.innerHTML.indexOf('On') != -1)
  76. a.innerHTML = a.innerHTML.replace(/On/, 'Off');
  77. else
  78. a.innerHTML = a.innerHTML.replace(/Off/, 'On');
  79.  
  80. changeSettings(div);
  81. }
  82.  
  83. function changeSettings(div)
  84. {
  85. var settings = getSettings();
  86. var as=div.getElementsByTagName('a');
  87.  
  88. if(as[0].innerHTML.indexOf('On') != -1)
  89. settings.sequential=true;
  90. else
  91. settings.sequential=false;
  92.  
  93. if(as[1].innerHTML.indexOf('On') != -1)
  94. settings.summary=true;
  95. else
  96. settings.summary=false;
  97.  
  98. setSettings(settings);
  99. showSettings();
  100. }
  101.  
  102. function setSettings(settings)
  103. {
  104. window.localStorage.collectorOperationSettings = JSON.stringify(settings);
  105. }
  106.  
  107. function getSettings()
  108. {
  109. var settings = window.localStorage.collectorOperationSettings;
  110. if(!settings)
  111. {
  112. settings = {sequential:false};
  113. }
  114. else
  115. {
  116. settings = JSON.parse(settings);
  117. }
  118. return settings;
  119. }
  120.  
  121. function addToX(compileFunc)
  122. {
  123. var style=document.createElement('style');
  124. style.innerHTML = '.collectorAdded { background-color: #151 !important; } ';
  125. style.innerHTML+= '.collectorAddedSuboptimal { background-color: #551 !important; } ';
  126. style.innerHTML+= '.collectorMissing { background: rgba(255, 0, 0, 0.2) !important;} ';
  127. style.innerHTML+= '.collectorSuboptimal { background: rgba(255, 255, 0, 0.2) !important;}';
  128. document.head.appendChild(style);
  129.  
  130. var settings=getPersistence();
  131.  
  132. var sidebar=document.getElementsByClassName('sidebar')[0];
  133. var box=document.createElement('div');
  134. box.setAttribute('class', 'box');
  135. sidebar.appendChild(box);
  136. //sidebar.insertBefore(box, sidebar.firstElementChild);
  137. var head=document.createElement('div');
  138. box.appendChild(head);
  139. head.setAttribute('class', 'head');
  140. head.innerHTML = '<strong>Collector</strong>';
  141. var list=document.createElement('ul');
  142. box.appendChild(list);
  143. list.setAttribute('class', 'nobullet');
  144.  
  145. var labelStyle='';
  146. var inputStyle='';
  147.  
  148. var li=document.createElement('li');
  149. list.appendChild(li);
  150. var label=document.createElement('span');
  151. label.setAttribute('style', labelStyle);
  152. label.innerHTML = 'Format [?]: ';
  153. var options = ["Any", "FLAC", "MP3", "AAC", "AC3", "DTS"];
  154. li.addEventListener('mouseover', mouseOverLabel.bind(undefined, options), false);
  155. li.addEventListener('mouseout', mouseOutLabel.bind(undefined, options), false);
  156. li.appendChild(label);
  157. var format=document.createElement('input');
  158. format.setAttribute('style', inputStyle);
  159. li.appendChild(format);
  160. format.value = settings.format.join(', ');
  161. format.placeholder="Format";
  162.  
  163. var li=document.createElement('li');
  164. list.appendChild(li);
  165. var label=document.createElement('span');
  166. label.setAttribute('style', labelStyle);
  167. label.innerHTML = 'Bitrate [?]: ';
  168. var options = ["Any", "192", "APS (VBR)", "V2 (VBR)", "V1 (VBR)", "256", "APX", "V0 (VBR)", "320", "Lossless", "24bit Lossless", "Other"];
  169. li.addEventListener('mouseover', mouseOverLabel.bind(undefined, options), false);
  170. li.addEventListener('mouseout', mouseOutLabel.bind(undefined, options), false);
  171. li.appendChild(label);
  172. var bitrate=document.createElement('input');
  173. bitrate.setAttribute('style', inputStyle);
  174. li.appendChild(bitrate);
  175. bitrate.value = settings.bitrate.join(', ');
  176. bitrate.placeholder="Bitrate";
  177.  
  178. var li=document.createElement('li');
  179. list.appendChild(li);
  180. var label=document.createElement('span');
  181. label.setAttribute('style', labelStyle);
  182. label.innerHTML = 'Media [?]: ';
  183. var options = ["Any", "CD", "DVD", "Vinyl", "Soundboard", "SACD", "DAT", "Cassette", "WEB", "Blu-Ray"];
  184. li.addEventListener('mouseover', mouseOverLabel.bind(undefined, options), false);
  185. li.addEventListener('mouseout', mouseOutLabel.bind(undefined, options), false);
  186. li.appendChild(label);
  187. var media=document.createElement('input');
  188. media.setAttribute('style', inputStyle);
  189. li.appendChild(media);
  190. media.value = settings.media.join(', ');
  191. media.placeholder="Media";
  192.  
  193. var li=document.createElement('li');
  194. list.appendChild(li);
  195. var label=document.createElement('span');
  196. label.setAttribute('style', labelStyle);
  197. label.innerHTML = 'Type: ';
  198. li.appendChild(label);
  199. var type=document.createElement('input');
  200. type.placeholder = 'Release Type';
  201. type.value = settings.types.join(', ');
  202. type.setAttribute('style', inputStyle);
  203. li.appendChild(type);
  204.  
  205. var li=document.createElement('li');
  206. list.appendChild(li);
  207. var label=document.createElement('span');
  208. label.setAttribute('style', labelStyle);
  209. label.innerHTML = 'Minimum number of seeders: ';
  210. li.appendChild(label);
  211. var minSeedCount=document.createElement('input');
  212. minSeedCount.type='number';
  213. minSeedCount.value = settings.minSeedCount;
  214. minSeedCount.setAttribute('style', inputStyle);
  215. li.appendChild(minSeedCount);
  216.  
  217. var messageDiv=document.createElement('div');
  218. messageDiv.setAttribute('style', 'text-align: center;');
  219.  
  220. format.addEventListener('keyup', compileFunc.bind(undefined, {format:format, bitrate:bitrate, media:media, type:type, minSeedCount:minSeedCount}, messageDiv), false);
  221. bitrate.addEventListener('keyup', compileFunc.bind(undefined, {format:format, bitrate:bitrate, media:media, type:type, minSeedCount:minSeedCount}, messageDiv), false);
  222. media.addEventListener('keyup', compileFunc.bind(undefined, {format:format, bitrate:bitrate, media:media, type:type, minSeedCount:minSeedCount}, messageDiv), false);
  223. type.addEventListener('keyup', compileFunc.bind(undefined, {format:format, bitrate:bitrate, media:media, type:type, minSeedCount:minSeedCount}, messageDiv), false);
  224. minSeedCount.addEventListener('keyup', compileFunc.bind(undefined, {format:format, bitrate:bitrate, media:media, type:type, minSeedCount:minSeedCount}, messageDiv), false);
  225. minSeedCount.addEventListener('change', compileFunc.bind(undefined, {format:format, bitrate:bitrate, media:media, type:type, minSeedCount:minSeedCount}, messageDiv), false);
  226. minSeedCount.addEventListener('click', compileFunc.bind(undefined, {format:format, bitrate:bitrate, media:media, type:type, minSeedCount:minSeedCount}, messageDiv), false);
  227.  
  228. var div=document.createElement('div');
  229. div.setAttribute('style', 'text-align: center;');
  230. box.appendChild(div);
  231. var a=document.createElement('a');
  232. div.appendChild(a);
  233. a.href='javascript:void(0);';
  234. a.innerHTML = 'Collect';
  235. a.addEventListener('click', save.bind(undefined, messageDiv), false);
  236.  
  237. div.appendChild(document.createTextNode(' | '));
  238. var a=document.createElement('a');
  239. div.appendChild(a);
  240. a.href='javascript:void(0);';
  241. a.innerHTML = 'Preview';
  242. a.setAttribute('id', 'collectorPreviewLink');
  243. a.addEventListener('click', compileFunc.bind(undefined, {format:format, bitrate:bitrate, media:media, type:type, minSeedCount:minSeedCount}, messageDiv, true), false);
  244.  
  245.  
  246. div.appendChild(document.createTextNode(' | '));
  247. var a=document.createElement('a');
  248. div.appendChild(a);
  249. a.href='javascript:void(0);';
  250. a.innerHTML = 'List';
  251. a.addEventListener('click', listC.bind(undefined, messageDiv), false);
  252.  
  253. var div=document.createElement('div');
  254. div.setAttribute('style', 'text-align: center; white-space:nowrap; text-overflow:ellipsis; overflow:hidden;');
  255. box.appendChild(div);
  256. div.id='collectorList';
  257.  
  258. box.appendChild(messageDiv);
  259. }
  260.  
  261. function listC(messageDiv)
  262. {
  263. var div=document.getElementById('collectorList');
  264. div.innerHTML='';
  265.  
  266. var torrentList=messageDiv.getAttribute('torrentList');
  267. if(!torrentList)
  268. messageDiv.innerHTML = "You need to preview first";
  269. torrentList=JSON.parse(torrentList);
  270. for(var i=0; i<torrentList.length; i++)
  271. {
  272. div.innerHTML+='<br /><a href="'+torrentList[i].dl+'" title="'+torrentList[i].name+'">'+torrentList[i].name+'</a>';
  273. }
  274. }
  275.  
  276. function mouseOverLabel(options, event)
  277. {
  278. var div=document.createElement('div');
  279. document.body.appendChild(div);
  280. div.setAttribute('class', 'labelPopups');
  281. div.setAttribute('style', 'position: fixed; left: '+event.clientX+'px; top: '+event.clientY+'px; border-radius: 10px; padding: 10px; background: rgba(0,0,0,0.8); color: white;');
  282. for(var i=0; i<options.length; i++)
  283. {
  284. div.innerHTML+=options[i]+'<br />';
  285. }
  286. }
  287.  
  288. function mouseOutLabel()
  289. {
  290. var l=document.getElementsByClassName('labelPopups');
  291. for(var i=0; i<l.length; i++)
  292. {
  293. l[i].parentNode.removeChild(l[i]);
  294. }
  295. }
  296.  
  297. function compileCollage(filters, messageDiv, hilight)
  298. {
  299. setPersistence(filters);
  300. var pers=getPersistence();
  301.  
  302. var format = pers.format;
  303. var bitrate = pers.bitrate;
  304. var media = pers.media;
  305. var minSeedCount = pers.minSeedCount;
  306.  
  307. var collage=document.getElementsByTagName('h2')[0].textContent;
  308. if(this == "Bookmarks")
  309. collage="Bookmarks";
  310.  
  311. var title = "Collection Collage - "+collage+".zip";//+" - "+format+"_"+bitrate+"_"+media+".zip";
  312. messageDiv.setAttribute('zipName', title);
  313.  
  314. messageDiv.innerHTML = 'Collecting torrents';
  315. var torrents=[];
  316.  
  317. var missed=[];
  318. var suboptimal=[];
  319. var albumCount=0;
  320.  
  321. if(hilight)
  322. {
  323. var tRows = document.getElementsByClassName('torrent_row');
  324. for(var i=0; i<tRows.length; i++)
  325. {
  326. var t=tRows[i];
  327. t.setAttribute('class', t.getAttribute('class').replace(' collectorAddedSuboptimal', ''));
  328. t.setAttribute('class', t.getAttribute('class').replace(' collectorAdded', ''));
  329. if(t.getAttribute('collectorPreviewing') != "true")
  330. {
  331. t.addEventListener('click', addAnywayFunc.bind(undefined, t), false);
  332. t.setAttribute('collectorPreviewing', "true");
  333. }
  334. }
  335. var groups=document.getElementsByClassName('group');
  336. for(var i=0; i<groups.length; i++)
  337. {
  338. groups[i].setAttribute('class', groups[i].getAttribute('class').replace(' collectorMissing', ''));
  339. groups[i].setAttribute('class', groups[i].getAttribute('class').replace(' collectorSuboptimal', ''));
  340. }
  341. }
  342.  
  343. var totalSize=0;
  344.  
  345. var groups=document.getElementsByClassName('group');
  346. for(var i=0; i<groups.length; i++)
  347. {
  348. var g=groups[i];
  349. var album=g.getElementsByTagName('strong');
  350. if(album.length === 0)
  351. album=g.getElementsByClassName('group_info')[0].getElementsByTagName('a');
  352. else
  353. album = album[0].getElementsByTagName('a');
  354. var artist=album[0].innerHTML;
  355. album = album[album.length-1].innerHTML;
  356. g.setAttribute('artist', artist);
  357. g.setAttribute('album', album);
  358. }
  359.  
  360. var output=doGroups(groups, torrents, hilight, albumCount, suboptimal, missed);
  361.  
  362. torrents=output.torrents;
  363. totalSize+=output.totalSize;
  364. albumCount=output.albumCount;
  365. suboptimal=output.suboptimal;
  366. missed=output.missed;
  367.  
  368.  
  369. messageDiv.innerHTML = '';
  370.  
  371. var summaryText=(title.replace(/.zip$/, ''))+"\n\nDate: "+Date()+"\n\nTorrent groups analyzed: "+albumCount;
  372. if(missed.length > 0)
  373. summaryText+="\nTorrent groups filtered: "+missed.length+"\nTorrents downloaded: "+(albumCount-missed.length);
  374. if(suboptimal.length > 0)
  375. summaryText+="\nSuboptimal torrents: "+suboptimal.length;
  376. summaryText+="\n\nFormat filter: "+format.join(', ')+'\nBitrate filter: '+bitrate.join(', ')+'\nMedia filter: '+media.join(', ');
  377. summaryText+="\n\nTotal size of torrents (ratio hit): "+prettySize(totalSize);
  378. if(missed.length > 0)
  379. {
  380. summaryText+="\n\nAlbums unavailable within your criteria (consider making a request for your desired format):";
  381. for(var i=0; i<missed.length; i++)
  382. {
  383. var m=missed[i];
  384. summaryText+="\n/torrents.php?id="+m.groupid+" - "+m.artist+" - "+m.album;
  385. }
  386. }
  387. if(suboptimal.length > 0)
  388. {
  389. summaryText+="\n\nAlbums suboptimal within your criteria (consider making a request for your optimal format):";
  390. for(var i=0; i<suboptimal.length; i++)
  391. {
  392. var m=suboptimal[i];
  393. summaryText+="\n/torrents.php?id="+m.groupid+" - "+m.artist+" - "+m.album;
  394. }
  395. }
  396.  
  397. messageDiv.setAttribute('summaryText', summaryText);
  398.  
  399. if(missed.length > 0)
  400. {
  401. messageDiv.innerHTML = "Missing "+missed.length+" of "+albumCount+" groups";
  402. }
  403. else
  404. {
  405. messageDiv.innerHTML = 'Added torrents from all '+albumCount+' groups';
  406. }
  407. if(suboptimal.length > 0)
  408. {
  409. messageDiv.innerHTML+= '<br />'+suboptimal.length+' of '+(albumCount-missed.length)+' selected are suboptimal';
  410. }
  411. messageDiv.innerHTML+="<br />Total size: "+prettySize(totalSize);
  412. messageDiv.setAttribute('torrentList', JSON.stringify(torrents));
  413. }
  414.  
  415. function getPersistence()
  416. {
  417. var settings = window.localStorage.collectorSettings;
  418. if(!settings)
  419. {
  420. settings = {format: [], bitrate: [], media: [], types: [], minSeedCount: 0};
  421. }
  422. else
  423. {
  424. settings = JSON.parse(settings);
  425. }
  426. if(typeof(settings.format) != "object")
  427. settings = {format: [], bitrate: [], media: [], types: [], minSeedCount: 0};
  428. return settings;
  429. }
  430.  
  431. function setPersistence(filters)
  432. {
  433. var settings = {
  434. format: filters.format.value.split(', '),
  435. bitrate: filters.bitrate.value.split(', '),
  436. media: filters.media.value.split(', '),
  437. types: filters.type.value.split(', '),
  438. minSeedCount: parseInt(filters.minSeedCount.value),
  439. };
  440. if(isNaN(settings.minSeedCount))
  441. settings.minSeedCount=0;
  442. window.localStorage.collectorSettings = JSON.stringify(settings);
  443. }
  444.  
  445. function compileArtist(filters, messageDiv, hilight)
  446. {
  447. setPersistence(filters);
  448. var pers=getPersistence();
  449.  
  450. var format = pers.format;
  451. var bitrate = pers.bitrate;
  452. var media = pers.media;
  453. var types = pers.types;
  454.  
  455. var artist=document.getElementsByTagName('h2')[0].textContent;
  456. var title = "Collection Artist - "+artist+".zip";//+" - "+format+"_"+bitrate+"_"+media+".zip";
  457. messageDiv.setAttribute('zipName', title);
  458.  
  459. messageDiv.innerHTML = 'Collecting torrents';
  460. var torrents=[];
  461.  
  462. var missed=[];
  463. var suboptimal=[];
  464. var albumCount=0;
  465.  
  466. if(hilight)
  467. {
  468. var tRows = document.getElementsByClassName('torrent_row');
  469. for(var i=0; i<tRows.length; i++)
  470. {
  471. var t=tRows[i];
  472. t.setAttribute('class', t.getAttribute('class').replace(' collectorAddedSuboptimal', ''));
  473. t.setAttribute('class', t.getAttribute('class').replace(' collectorAdded', ''));
  474. if(t.getAttribute('collectorPreviewing') != "true")
  475. {
  476. t.addEventListener('click', addAnywayFunc.bind(undefined, t), false);
  477. t.setAttribute('collectorPreviewing', "true");
  478. }
  479. }
  480. var groups=document.getElementsByClassName('group');
  481. for(var i=0; i<groups.length; i++)
  482. {
  483. groups[i].setAttribute('class', groups[i].getAttribute('class').replace(' collectorMissing', ''));
  484. groups[i].setAttribute('class', groups[i].getAttribute('class').replace(' collectorSuboptimal', ''));
  485. }
  486. }
  487. for(var i=0; i<groups.length; i++)
  488. {
  489. var g=groups[i];
  490. var album=g.getElementsByClassName('group_info')[0].getElementsByTagName('strong')[0].getElementsByTagName('a');
  491. album = album[album.length-1].innerHTML;
  492. g.setAttribute('artist', artist);
  493. g.setAttribute('album', album);
  494. }
  495.  
  496. var totalSize=0;
  497.  
  498. var tables = document.getElementsByClassName('release_table');
  499. for(var i=0; i<tables.length; i++)
  500. {
  501. var t=tables[i];
  502. var releaseType=t.getElementsByTagName('tr')[0].getElementsByTagName('strong')[0].innerHTML;
  503.  
  504. var inTypes=false;
  505. for(var m=0; m<types.length; m++)
  506. {
  507. if(types[m] == releaseType)
  508. {
  509. inTypes=true;
  510. break;
  511. }
  512. }
  513. if(!inTypes && !(types[0] == '' && types.length == 1))
  514. continue;
  515.  
  516. var groups=t.getElementsByClassName('group');
  517.  
  518. var output=doGroups(groups, torrents, hilight, albumCount, suboptimal, missed);
  519.  
  520. torrents=output.torrents;
  521. totalSize+=output.totalSize;
  522. albumCount=output.albumCount;
  523. suboptimal=output.suboptimal;
  524. missed=output.missed;
  525. }
  526.  
  527. messageDiv.innerHTML = '';
  528.  
  529. var summaryText=(title.replace(/.zip$/, ''))+"\n\nDate: "+Date()+"\n\nTorrent groups analyzed: "+albumCount;
  530. if(missed.length > 0)
  531. summaryText+="\nTorrent groups filtered: "+missed.length+"\nTorrents downloaded: "+(albumCount-missed.length);
  532. if(suboptimal.length > 0)
  533. summaryText+="\nSuboptimal torrents: "+suboptimal.length;
  534. summaryText+="\n\nFormat filter: "+format.join(', ')+'\nBitrate filter: '+bitrate.join(', ')+'\nMedia filter: '+media.join(', ')+'\nRelease type filter: '+types.join(', ');
  535. summaryText+="\n\nTotal size of torrents (ratio hit): "+prettySize(totalSize);
  536. if(missed.length > 0)
  537. {
  538. summaryText+="\n\nAlbums unavailable within your criteria (consider making a request for your desired format):";
  539. for(var i=0; i<missed.length; i++)
  540. {
  541. var m=missed[i];
  542. summaryText+="\n/torrents.php?id="+m.groupid+" - "+m.artist+" - "+m.album;
  543. }
  544. }
  545. if(suboptimal.length > 0)
  546. {
  547. summaryText+="\n\nAlbums suboptimal within your criteria (consider making a request for your optimal format):";
  548. for(var i=0; i<suboptimal.length; i++)
  549. {
  550. var m=suboptimal[i];
  551. summaryText+="\n/torrents.php?id="+m.groupid+" - "+m.artist+" - "+m.album;
  552. }
  553. }
  554.  
  555. messageDiv.setAttribute('summaryText', summaryText);
  556.  
  557. if(missed.length > 0)
  558. {
  559. messageDiv.innerHTML = "Missing "+missed.length+" of "+albumCount+" groups";
  560. }
  561. else
  562. {
  563. messageDiv.innerHTML = 'Added torrents from all '+albumCount+' groups';
  564. }
  565. if(suboptimal.length > 0)
  566. {
  567. messageDiv.innerHTML+= '<br />'+suboptimal.length+' of '+(albumCount-missed.length)+' selected are suboptimal';
  568. }
  569. messageDiv.innerHTML+="<br />Total size: "+prettySize(totalSize);
  570. messageDiv.setAttribute('torrentList', JSON.stringify(torrents));
  571. }
  572.  
  573. function doGroups(groups, torrents, hilight, albumCount, suboptimal, missed)
  574. {
  575. var searchPage=false;
  576. if(window.location.href.indexOf('torrents.php') != -1 && window.location.href.indexOf('?id=') == -1)
  577. searchPage=true;
  578. var totalSize=0;
  579. for(var j=0; j<groups.length; j++)
  580. {
  581. var g=groups[j];
  582. var groupId=g.getElementsByTagName('div')[0].getAttribute('id').split('_')[1];
  583. var artist=g.getAttribute('artist');
  584. var album=g.getAttribute('album');
  585. var editions=document.getElementsByClassName('groupid_'+groupId+' edition');
  586. var added=0;
  587. var allEditions=[];
  588. for(var k=0; k<editions.length; k++)
  589. {
  590. var editionMeta=editions[k].textContent.split(' / ');
  591. var editionMedia = editionMeta[editionMeta.length-1].trim();
  592.  
  593. var torrentRows = document.getElementsByClassName('torrent_row groupid_'+groupId+' edition_'+(k+1));
  594. if(searchPage)
  595. {
  596. torrentRows = document.getElementsByClassName('groupid_'+groupId+' edition_'+(k+1));
  597. }
  598. for(var l=0; l<torrentRows.length; l++)
  599. {
  600. var e=torrentRows[l];
  601. e.setAttribute('media', editionMedia);
  602. allEditions.push(e);
  603. }
  604. }
  605. var best=getBest(allEditions);
  606. var addIndexes=[];
  607. var score=best.score;
  608. for(var k=0; k<allEditions.length; k++)
  609. {
  610. var e=allEditions[k];
  611. var addAnyway = e.getAttribute('addAnyway');
  612. if(addAnyway == "true")
  613. {
  614. var score1=getBest([e]).score;
  615. addIndexes.push({index:k, score:score1});
  616. if(score1 < score)
  617. score=score1;
  618. }
  619. if(addIndexes.length === 0 && best.index != -1 && allEditions[best.index].getAttribute('addAnyway') != "false")
  620. addIndexes.push(best);
  621. }
  622. var secondCount=0;
  623. for(var l=0; l<addIndexes.length; l++)
  624. {
  625. var e=allEditions[addIndexes[l].index];
  626.  
  627. var as=e.getElementsByTagName('a');
  628. var dl=as[0].href;
  629. var linkCount=1;
  630. while(dl.indexOf('authkey') == -1)
  631. {
  632. dl=as[linkCount].href;
  633. linkCount++;
  634. }
  635. var meta=as[as.length-1].innerHTML.split(' / ');
  636. var tdIndex=1;
  637. if(searchPage)
  638. tdIndex=3;
  639. var size=unPretty(e.getElementsByTagName('td')[tdIndex].textContent);
  640. var editionMedia=e.getAttribute('media');
  641. totalSize+=size;
  642.  
  643. var addAnyway = e.getAttribute('addAnyway');
  644. if(addAnyway == "false")
  645. continue;
  646.  
  647. var torrentId=as[as.length-1].href.split('&torrentid=')[1];
  648. var torrentName=artist+' - '+album+' - '+meta[0]+"_"+meta[1]+"_"+editionMedia+" - "+torrentId+".torrent";
  649.  
  650. torrents.push({dl:dl, name:torrentName});
  651. if(hilight)
  652. {
  653. if(score === 0)
  654. e.setAttribute('class', e.getAttribute('class')+' collectorAdded');
  655. else if(addIndexes.length > 0)
  656. e.setAttribute('class', e.getAttribute('class')+' collectorAddedSuboptimal');
  657. }
  658. secondCount++;
  659. }
  660. if(score === 0)
  661. added=1;
  662. else if(addIndexes.length > 0)
  663. added=2;
  664. if(secondCount === 0)
  665. added=0;
  666. albumCount++;
  667. if(added === 0)
  668. {
  669. if(hilight)
  670. g.setAttribute('class', g.getAttribute('class')+' collectorMissing');
  671. missed.push({groupid:groupId, artist:artist, album:album});
  672. }
  673. else if(added == 2)
  674. {
  675. if(hilight)
  676. g.setAttribute('class', g.getAttribute('class')+' collectorSuboptimal');
  677. suboptimal.push({groupid:groupId, artist:artist, album:album});
  678. }
  679. }
  680.  
  681. return {totalSize:totalSize, torrents:torrents, albumCount:albumCount, suboptimal:suboptimal, missed:missed};
  682. }
  683.  
  684. function unPretty(size)
  685. {
  686. var s=parseFloat(size);
  687. if(size.indexOf('KB') != -1)
  688. s = s*Math.pow(2, 10);
  689. else if(size.indexOf('MB') != -1)
  690. s = s*Math.pow(2, 20);
  691. else if(size.indexOf('GB') != -1)
  692. s = s*Math.pow(2, 30);
  693. else if(size.indexOf('TB') != -1)
  694. s = s*Math.pow(2, 40);
  695. else if(size.indexOf('PB') != -1)
  696. s = s*Math.pow(2, 50);
  697.  
  698. return Math.round(s);
  699. }
  700.  
  701. function prettySize(size)
  702. {
  703. var newSize=size;
  704. var i=0;
  705. while(newSize > 1)
  706. {
  707. i++;
  708. newSize = size/Math.pow(2, i*10);
  709. }
  710. i--;
  711. if(i<0)
  712. i=0;
  713. newSize=size/Math.pow(2, (i)*10);
  714.  
  715. var suffixes=["B", "KB", "MB", "GB", "TB", "PB"];
  716.  
  717. newSize = Math.round(newSize*100)/100;
  718. newSize = newSize+' '+suffixes[i];
  719. return newSize;
  720. }
  721.  
  722. function getBest(rows)
  723. {
  724. var pers=getPersistence();
  725.  
  726. var best={index:-1, score:100000};
  727.  
  728. for(var i=0; i<rows.length; i++)
  729. {
  730. var e=rows[i];
  731. var editionMedia=e.getAttribute('media');
  732. if(e.getAttribute('addAnyway') == "false")
  733. continue;
  734.  
  735. var seedCount=parseInt(e.getElementsByTagName('td')[3].textContent);
  736. if(seedCount < pers.minSeedCount)
  737. continue;
  738.  
  739. var meta=e.getElementsByTagName('a');
  740. meta=meta[meta.length-1].innerHTML.split(' / ');
  741.  
  742. if(meta[0] == pers.format[0] && meta[1] == pers.bitrate[0] && editionMedia == pers.media[0])
  743. {
  744. best.index=i;
  745. best.score=0;
  746. break;
  747. }
  748.  
  749. if(pers.format.length === 0)
  750. pers.format.push("Any");
  751. if(pers.bitrate.length === 0)
  752. pers.format.push("Any");
  753. if(pers.media.length === 0)
  754. pers.format.push("Any");
  755.  
  756.  
  757. for(var j=0; j<pers.format.length; j++)
  758. {
  759. var f=pers.format[j];
  760. if(f==='')
  761. f='Any';
  762. if(f=="Any" || meta[0]==f)
  763. {
  764. for(var k=0; k<pers.bitrate.length; k++)
  765. {
  766. var b=pers.bitrate[k];
  767. if(b==='')
  768. b='Any';
  769. if(b=="Any" || meta[1]==b)
  770. {
  771. for(var l=0; l<pers.media.length; l++)
  772. {
  773. var m=pers.media[l];
  774. if(m==='')
  775. m='Any';
  776. if(m=="Any" || editionMedia==m)
  777. {
  778. var score = (j*100)+(k*10)+l;
  779. if(score < best.score)
  780. {
  781. best.index=i;
  782. best.score=score;
  783. }
  784. }
  785. }
  786. }
  787. }
  788. }
  789. }
  790. }
  791. return best;
  792. }
  793.  
  794. function addAnywayFunc(tr, event)
  795. {
  796. if(!event.ctrlKey && !event.metaKey)
  797. return;
  798.  
  799. event.preventDefault();
  800.  
  801. var addAnyway = tr.getAttribute("addAnyway");
  802. var adding = tr.getAttribute('class').indexOf('collectorAdded') != -1;
  803. if(adding)
  804. {
  805. tr.setAttribute("addAnyway", false);
  806. document.getElementById('collectorPreviewLink').click();
  807. return;
  808. }
  809. else
  810. {
  811. tr.setAttribute("addAnyway", true);
  812. document.getElementById('collectorPreviewLink').click();
  813. return;
  814. }
  815. }
  816.  
  817. function save(messageDiv)
  818. {
  819. var torrentList=messageDiv.getAttribute('torrentList');
  820. if(!torrentList)
  821. messageDiv.innerHTML = "You need to preview first";
  822. torrentList=JSON.parse(torrentList);
  823. var opSettings = getSettings();
  824. if(opSettings.sequential)
  825. {
  826. messageDiv.setAttribute('stopSequential', "false");
  827. sequentialGet(torrentList, 0, messageDiv);
  828. }
  829. else
  830. {
  831. var zip=new JSZip();
  832.  
  833. var settings=getSettings();
  834. if(settings.summary)
  835. {
  836. var name=messageDiv.getAttribute('zipName').replace(/zip$/, "txt");
  837. var text=messageDiv.getAttribute('summaryText');
  838. zip.file(name.replace(/\//g, '_'), text);
  839. }
  840.  
  841. getTorrent(torrentList, 0, zip, messageDiv);
  842. }
  843. }
  844.  
  845. function sequentialGet(list, index, messageDiv)
  846. {
  847. if(messageDiv.getAttribute('stopSequential') == "true")
  848. {
  849. messageDiv.innerHTML = 'Stopped';
  850. return;
  851. }
  852. if(index >= list.length)
  853. {
  854. messageDiv.innerHTML = 'Finished';
  855. return;
  856. }
  857.  
  858. messageDiv.innerHTML = "Downloading torrent "+(index+1)+" of "+list.length+"<br />";
  859. var a=document.createElement('a');
  860. messageDiv.appendChild(a);
  861. a.innerHTML='Stop';
  862. a.href='javascript:void(0);';
  863. a.addEventListener('click', stopSequential.bind(undefined, messageDiv), false);
  864.  
  865. var a=document.createElement('a');
  866. a.href=list[index].dl;
  867. a.download=list[index].name;
  868. document.body.appendChild(a);
  869. a.click();
  870.  
  871. window.setTimeout(sequentialGet.bind(undefined, list, index+1, messageDiv), 1000);
  872. }
  873.  
  874. function stopSequential(messageDiv)
  875. {
  876. messageDiv.setAttribute('stopSequential', "true");
  877. }
  878.  
  879. function getTorrent(list, index, zip, messageDiv)
  880. {
  881. if(index >= list.length)
  882. {
  883. gotTorrents(zip, messageDiv);
  884. return;
  885. }
  886. messageDiv.innerHTML = "Getting torrent "+(index+1)+" of "+list.length+"<br />"+list[index].name;
  887. var xhr = new XMLHttpRequest();
  888. xhr.open('GET', list[index].dl);
  889. xhr.responseType = "arraybuffer";
  890. xhr.onreadystatechange = xhr_func.bind(undefined, messageDiv, xhr, gotTorrent.bind(undefined, list, index, zip, messageDiv), getTorrent.bind(undefined, list, index, zip, messageDiv), true);
  891. xhr.send();
  892. }
  893.  
  894. function gotTorrent(list, index, zip, messageDiv, response)
  895. {
  896. zip.file(list[index].name.replace(/\//g, '_'), response);
  897. window.setTimeout(getTorrent.bind(undefined, list, index+1, zip, messageDiv), 1000);
  898. }
  899.  
  900. function gotTorrents(zip, messageDiv)
  901. {
  902. messageDiv.innerHTML = 'Generating zip file of torrents';
  903. zip.generateAsync({type:"blob"}).then(saveLink.bind(undefined, messageDiv));
  904. }
  905.  
  906. function saveLink(messageDiv, blob)
  907. {
  908. messageDiv.innerHTML = '';
  909. var a=document.createElement('a');
  910. messageDiv.appendChild(a);
  911. var name=messageDiv.getAttribute('zipName');
  912. a.innerHTML = name;
  913. a.href = URL.createObjectURL(blob);
  914. a.download = name;
  915. }
  916.  
  917. function xhr_func(messageDiv, xhr, func, repeatFunc, binary)
  918. {
  919. if(xhr.readyState == 4)
  920. {
  921. if(xhr.status == 200)
  922. {
  923. if(binary)
  924. {
  925. var byteArray = new Uint8Array(xhr.response);
  926. func(byteArray);
  927. }
  928. else
  929. {
  930. func(xhr.responseText);
  931. }
  932. }
  933. else
  934. {
  935. messageDiv.innerHTML = 'Error: '+xhr.status+'<br />retrying in 1 second';
  936. window.setTimeout(repeatFunc, 1000);
  937. }
  938. }
  939. }