PTH Collector

Download multiple torrents by some criteria on PTH

  1. // ==UserScript==
  2. // @name PTH Collector
  3. // @version 1.8
  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. var t=torrentList[i];
  273. var id=parseInt(t.dl.split('id=')[1]);
  274. var name=t.name.split('.torrent')[0];
  275. div.innerHTML+='<br /><a href="/torrents.php?torrentid='+id+'" title="'+name+'">'+name+'</a>';
  276. }
  277. }
  278.  
  279. function mouseOverLabel(options, event)
  280. {
  281. var div=document.createElement('div');
  282. document.body.appendChild(div);
  283. div.setAttribute('class', 'labelPopups');
  284. 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;');
  285. for(var i=0; i<options.length; i++)
  286. {
  287. div.innerHTML+=options[i]+'<br />';
  288. }
  289. }
  290.  
  291. function mouseOutLabel()
  292. {
  293. var l=document.getElementsByClassName('labelPopups');
  294. for(var i=0; i<l.length; i++)
  295. {
  296. l[i].parentNode.removeChild(l[i]);
  297. }
  298. }
  299.  
  300. function compileCollage(filters, messageDiv, hilight)
  301. {
  302. setPersistence(filters);
  303. var pers=getPersistence();
  304.  
  305. var format = pers.format;
  306. var bitrate = pers.bitrate;
  307. var media = pers.media;
  308. var minSeedCount = pers.minSeedCount;
  309.  
  310. var collage=document.getElementsByTagName('h2')[0].textContent;
  311. if(this == "Bookmarks")
  312. collage="Bookmarks";
  313.  
  314. var title = "Collection Collage - "+collage+".zip";//+" - "+format+"_"+bitrate+"_"+media+".zip";
  315. messageDiv.setAttribute('zipName', title);
  316.  
  317. messageDiv.innerHTML = 'Collecting torrents';
  318. var torrents=[];
  319.  
  320. var missed=[];
  321. var suboptimal=[];
  322. var albumCount=0;
  323.  
  324. if(hilight)
  325. {
  326. var tRows = document.getElementsByClassName('torrent_row');
  327. for(var i=0; i<tRows.length; i++)
  328. {
  329. var t=tRows[i];
  330. t.setAttribute('class', t.getAttribute('class').replace(' collectorAddedSuboptimal', ''));
  331. t.setAttribute('class', t.getAttribute('class').replace(' collectorAdded', ''));
  332. if(t.getAttribute('collectorPreviewing') != "true")
  333. {
  334. t.addEventListener('click', addAnywayFunc.bind(undefined, t), false);
  335. t.setAttribute('collectorPreviewing', "true");
  336. }
  337. }
  338. var groups=document.getElementsByClassName('group');
  339. for(var i=0; i<groups.length; i++)
  340. {
  341. groups[i].setAttribute('class', groups[i].getAttribute('class').replace(' collectorMissing', ''));
  342. groups[i].setAttribute('class', groups[i].getAttribute('class').replace(' collectorSuboptimal', ''));
  343. }
  344. }
  345.  
  346. var totalSize=0;
  347.  
  348. var groups=document.getElementsByClassName('group');
  349. for(var i=0; i<groups.length; i++)
  350. {
  351. var g=groups[i];
  352. var album=g.getElementsByTagName('strong');
  353. if(album.length === 0)
  354. album=g.getElementsByClassName('group_info')[0].getElementsByTagName('a');
  355. else
  356. album = album[0].getElementsByTagName('a');
  357. var artist=album[0].innerHTML;
  358. album = album[album.length-1].innerHTML;
  359. g.setAttribute('artist', artist);
  360. g.setAttribute('album', album);
  361. }
  362.  
  363. var output=doGroups(groups, torrents, hilight, albumCount, suboptimal, missed);
  364.  
  365. torrents=output.torrents;
  366. totalSize+=output.totalSize;
  367. albumCount=output.albumCount;
  368. suboptimal=output.suboptimal;
  369. missed=output.missed;
  370.  
  371.  
  372. messageDiv.innerHTML = '';
  373.  
  374. var summaryText=(title.replace(/.zip$/, ''))+"\n\nDate: "+Date()+"\n\nTorrent groups analyzed: "+albumCount;
  375. if(missed.length > 0)
  376. summaryText+="\nTorrent groups filtered: "+missed.length+"\nTorrents downloaded: "+(albumCount-missed.length);
  377. if(suboptimal.length > 0)
  378. summaryText+="\nSuboptimal torrents: "+suboptimal.length;
  379. summaryText+="\n\nFormat filter: "+format.join(', ')+'\nBitrate filter: '+bitrate.join(', ')+'\nMedia filter: '+media.join(', ');
  380. summaryText+="\n\nTotal size of torrents (ratio hit): "+prettySize(totalSize);
  381. if(missed.length > 0)
  382. {
  383. summaryText+="\n\nAlbums unavailable within your criteria (consider making a request for your desired format):";
  384. for(var i=0; i<missed.length; i++)
  385. {
  386. var m=missed[i];
  387. summaryText+="\n/torrents.php?id="+m.groupid+" - "+m.artist+" - "+m.album;
  388. }
  389. }
  390. if(suboptimal.length > 0)
  391. {
  392. summaryText+="\n\nAlbums suboptimal within your criteria (consider making a request for your optimal format):";
  393. for(var i=0; i<suboptimal.length; i++)
  394. {
  395. var m=suboptimal[i];
  396. summaryText+="\n/torrents.php?id="+m.groupid+" - "+m.artist+" - "+m.album;
  397. }
  398. }
  399.  
  400. messageDiv.setAttribute('summaryText', summaryText);
  401.  
  402. if(missed.length > 0)
  403. {
  404. messageDiv.innerHTML = "Missing "+missed.length+" of "+albumCount+" groups";
  405. }
  406. else
  407. {
  408. messageDiv.innerHTML = 'Added torrents from all '+albumCount+' groups';
  409. }
  410. if(suboptimal.length > 0)
  411. {
  412. messageDiv.innerHTML+= '<br />'+suboptimal.length+' of '+(albumCount-missed.length)+' selected are suboptimal';
  413. }
  414. messageDiv.innerHTML+="<br />Total size: "+prettySize(totalSize);
  415. messageDiv.setAttribute('torrentList', JSON.stringify(torrents));
  416. }
  417.  
  418. function getPersistence()
  419. {
  420. var settings = window.localStorage.collectorSettings;
  421. if(!settings)
  422. {
  423. settings = {format: [], bitrate: [], media: [], types: [], minSeedCount: 0};
  424. }
  425. else
  426. {
  427. settings = JSON.parse(settings);
  428. }
  429. if(typeof(settings.format) != "object")
  430. settings = {format: [], bitrate: [], media: [], types: [], minSeedCount: 0};
  431. return settings;
  432. }
  433.  
  434. function setPersistence(filters)
  435. {
  436. var settings = {
  437. format: filters.format.value.split(', '),
  438. bitrate: filters.bitrate.value.split(', '),
  439. media: filters.media.value.split(', '),
  440. types: filters.type.value.split(', '),
  441. minSeedCount: parseInt(filters.minSeedCount.value),
  442. };
  443. if(isNaN(settings.minSeedCount))
  444. settings.minSeedCount=0;
  445. window.localStorage.collectorSettings = JSON.stringify(settings);
  446. }
  447.  
  448. function compileArtist(filters, messageDiv, hilight)
  449. {
  450. setPersistence(filters);
  451. var pers=getPersistence();
  452.  
  453. var format = pers.format;
  454. var bitrate = pers.bitrate;
  455. var media = pers.media;
  456. var types = pers.types;
  457.  
  458. var artist=document.getElementsByTagName('h2')[0].textContent;
  459. var title = "Collection Artist - "+artist+".zip";//+" - "+format+"_"+bitrate+"_"+media+".zip";
  460. messageDiv.setAttribute('zipName', title);
  461.  
  462. messageDiv.innerHTML = 'Collecting torrents';
  463. var torrents=[];
  464.  
  465. var missed=[];
  466. var suboptimal=[];
  467. var albumCount=0;
  468.  
  469. if(hilight)
  470. {
  471. var tRows = document.getElementsByClassName('torrent_row');
  472. for(var i=0; i<tRows.length; i++)
  473. {
  474. var t=tRows[i];
  475. t.setAttribute('class', t.getAttribute('class').replace(' collectorAddedSuboptimal', ''));
  476. t.setAttribute('class', t.getAttribute('class').replace(' collectorAdded', ''));
  477. if(t.getAttribute('collectorPreviewing') != "true")
  478. {
  479. t.addEventListener('click', addAnywayFunc.bind(undefined, t), false);
  480. t.setAttribute('collectorPreviewing', "true");
  481. }
  482. }
  483. var groups=document.getElementsByClassName('group');
  484. for(var i=0; i<groups.length; i++)
  485. {
  486. groups[i].setAttribute('class', groups[i].getAttribute('class').replace(' collectorMissing', ''));
  487. groups[i].setAttribute('class', groups[i].getAttribute('class').replace(' collectorSuboptimal', ''));
  488. }
  489. }
  490. for(var i=0; i<groups.length; i++)
  491. {
  492. var g=groups[i];
  493. var album=g.getElementsByClassName('group_info')[0].getElementsByTagName('strong')[0].getElementsByTagName('a');
  494. album = album[album.length-1].innerHTML;
  495. g.setAttribute('artist', artist);
  496. g.setAttribute('album', album);
  497. }
  498.  
  499. var totalSize=0;
  500.  
  501. var tables = document.getElementsByClassName('release_table');
  502. for(var i=0; i<tables.length; i++)
  503. {
  504. var t=tables[i];
  505. var releaseType=t.getElementsByTagName('tr')[0].getElementsByTagName('strong')[0].innerHTML;
  506.  
  507. var inTypes=false;
  508. for(var m=0; m<types.length; m++)
  509. {
  510. if(types[m] == releaseType)
  511. {
  512. inTypes=true;
  513. break;
  514. }
  515. }
  516. if(!inTypes && !(types[0] == '' && types.length == 1))
  517. continue;
  518.  
  519. var groups=t.getElementsByClassName('group');
  520.  
  521. var output=doGroups(groups, torrents, hilight, albumCount, suboptimal, missed);
  522.  
  523. torrents=output.torrents;
  524. totalSize+=output.totalSize;
  525. albumCount=output.albumCount;
  526. suboptimal=output.suboptimal;
  527. missed=output.missed;
  528. }
  529.  
  530. messageDiv.innerHTML = '';
  531.  
  532. var summaryText=(title.replace(/.zip$/, ''))+"\n\nDate: "+Date()+"\n\nTorrent groups analyzed: "+albumCount;
  533. if(missed.length > 0)
  534. summaryText+="\nTorrent groups filtered: "+missed.length+"\nTorrents downloaded: "+(albumCount-missed.length);
  535. if(suboptimal.length > 0)
  536. summaryText+="\nSuboptimal torrents: "+suboptimal.length;
  537. summaryText+="\n\nFormat filter: "+format.join(', ')+'\nBitrate filter: '+bitrate.join(', ')+'\nMedia filter: '+media.join(', ')+'\nRelease type filter: '+types.join(', ');
  538. summaryText+="\n\nTotal size of torrents (ratio hit): "+prettySize(totalSize);
  539. if(missed.length > 0)
  540. {
  541. summaryText+="\n\nAlbums unavailable within your criteria (consider making a request for your desired format):";
  542. for(var i=0; i<missed.length; i++)
  543. {
  544. var m=missed[i];
  545. summaryText+="\n/torrents.php?id="+m.groupid+" - "+m.artist+" - "+m.album;
  546. }
  547. }
  548. if(suboptimal.length > 0)
  549. {
  550. summaryText+="\n\nAlbums suboptimal within your criteria (consider making a request for your optimal format):";
  551. for(var i=0; i<suboptimal.length; i++)
  552. {
  553. var m=suboptimal[i];
  554. summaryText+="\n/torrents.php?id="+m.groupid+" - "+m.artist+" - "+m.album;
  555. }
  556. }
  557.  
  558. messageDiv.setAttribute('summaryText', summaryText);
  559.  
  560. if(missed.length > 0)
  561. {
  562. messageDiv.innerHTML = "Missing "+missed.length+" of "+albumCount+" groups";
  563. }
  564. else
  565. {
  566. messageDiv.innerHTML = 'Added torrents from all '+albumCount+' groups';
  567. }
  568. if(suboptimal.length > 0)
  569. {
  570. messageDiv.innerHTML+= '<br />'+suboptimal.length+' of '+(albumCount-missed.length)+' selected are suboptimal';
  571. }
  572. messageDiv.innerHTML+="<br />Total size: "+prettySize(totalSize);
  573. messageDiv.setAttribute('torrentList', JSON.stringify(torrents));
  574. }
  575.  
  576. function doGroups(groups, torrents, hilight, albumCount, suboptimal, missed)
  577. {
  578. var searchPage=false;
  579. if(window.location.href.indexOf('torrents.php') != -1 && window.location.href.indexOf('?id=') == -1)
  580. searchPage=true;
  581. var totalSize=0;
  582. for(var j=0; j<groups.length; j++)
  583. {
  584. var g=groups[j];
  585. var groupId=g.getElementsByTagName('div')[0].getAttribute('id').split('_')[1];
  586. var artist=g.getAttribute('artist');
  587. var album=g.getAttribute('album');
  588. var editions=document.getElementsByClassName('groupid_'+groupId+' edition');
  589. var added=0;
  590. var allEditions=[];
  591. for(var k=0; k<editions.length; k++)
  592. {
  593. var editionMeta=editions[k].textContent.split(' / ');
  594. var editionMedia = editionMeta[editionMeta.length-1].trim();
  595.  
  596. var torrentRows = document.getElementsByClassName('torrent_row groupid_'+groupId+' edition_'+(k+1));
  597. if(searchPage)
  598. {
  599. torrentRows = document.getElementsByClassName('groupid_'+groupId+' edition_'+(k+1));
  600. }
  601. for(var l=0; l<torrentRows.length; l++)
  602. {
  603. var e=torrentRows[l];
  604. e.setAttribute('media', editionMedia);
  605. allEditions.push(e);
  606. }
  607. }
  608. var best=getBest(allEditions);
  609. var addIndexes=[];
  610. var score=best.score;
  611. for(var k=0; k<allEditions.length; k++)
  612. {
  613. var e=allEditions[k];
  614. var addAnyway = e.getAttribute('addAnyway');
  615. if(addAnyway == "true")
  616. {
  617. var score1=getBest([e]).score;
  618. addIndexes.push({index:k, score:score1});
  619. if(score1 < score)
  620. score=score1;
  621. }
  622. if(addIndexes.length === 0 && best.index != -1 && allEditions[best.index].getAttribute('addAnyway') != "false")
  623. addIndexes.push(best);
  624. }
  625. var secondCount=0;
  626. for(var l=0; l<addIndexes.length; l++)
  627. {
  628. var e=allEditions[addIndexes[l].index];
  629.  
  630. var as=e.getElementsByTagName('a');
  631. var dl=as[0].href;
  632. var linkCount=1;
  633. while(dl.indexOf('authkey') == -1)
  634. {
  635. dl=as[linkCount].href;
  636. linkCount++;
  637. }
  638. var meta=as[as.length-1].innerHTML.split(' / ');
  639. var tdIndex=1;
  640. if(searchPage)
  641. tdIndex=3;
  642. var size=unPretty(e.getElementsByTagName('td')[tdIndex].textContent);
  643. var editionMedia=e.getAttribute('media');
  644. totalSize+=size;
  645.  
  646. var addAnyway = e.getAttribute('addAnyway');
  647. if(addAnyway == "false")
  648. continue;
  649.  
  650. var torrentId=as[as.length-1].href.split('&torrentid=')[1];
  651. var torrentName=artist+' - '+album+' - '+meta[0]+"_"+meta[1]+"_"+editionMedia+" - "+torrentId+".torrent";
  652.  
  653. torrents.push({dl:dl, name:torrentName});
  654. if(hilight)
  655. {
  656. if(score === 0)
  657. e.setAttribute('class', e.getAttribute('class')+' collectorAdded');
  658. else if(addIndexes.length > 0)
  659. e.setAttribute('class', e.getAttribute('class')+' collectorAddedSuboptimal');
  660. }
  661. secondCount++;
  662. }
  663. if(score === 0)
  664. added=1;
  665. else if(addIndexes.length > 0)
  666. added=2;
  667. if(secondCount === 0)
  668. added=0;
  669. albumCount++;
  670. if(added === 0)
  671. {
  672. if(hilight)
  673. g.setAttribute('class', g.getAttribute('class')+' collectorMissing');
  674. missed.push({groupid:groupId, artist:artist, album:album});
  675. }
  676. else if(added == 2)
  677. {
  678. if(hilight)
  679. g.setAttribute('class', g.getAttribute('class')+' collectorSuboptimal');
  680. suboptimal.push({groupid:groupId, artist:artist, album:album});
  681. }
  682. }
  683.  
  684. return {totalSize:totalSize, torrents:torrents, albumCount:albumCount, suboptimal:suboptimal, missed:missed};
  685. }
  686.  
  687. function unPretty(size)
  688. {
  689. var s=parseFloat(size);
  690. if(size.indexOf('KB') != -1)
  691. s = s*Math.pow(2, 10);
  692. else if(size.indexOf('MB') != -1)
  693. s = s*Math.pow(2, 20);
  694. else if(size.indexOf('GB') != -1)
  695. s = s*Math.pow(2, 30);
  696. else if(size.indexOf('TB') != -1)
  697. s = s*Math.pow(2, 40);
  698. else if(size.indexOf('PB') != -1)
  699. s = s*Math.pow(2, 50);
  700.  
  701. return Math.round(s);
  702. }
  703.  
  704. function prettySize(size)
  705. {
  706. var newSize=size;
  707. var i=0;
  708. while(newSize > 1)
  709. {
  710. i++;
  711. newSize = size/Math.pow(2, i*10);
  712. }
  713. i--;
  714. if(i<0)
  715. i=0;
  716. newSize=size/Math.pow(2, (i)*10);
  717.  
  718. var suffixes=["B", "KB", "MB", "GB", "TB", "PB"];
  719.  
  720. newSize = Math.round(newSize*100)/100;
  721. newSize = newSize+' '+suffixes[i];
  722. return newSize;
  723. }
  724.  
  725. function getBest(rows)
  726. {
  727. var pers=getPersistence();
  728.  
  729. var best={index:-1, score:100000};
  730.  
  731. for(var i=0; i<rows.length; i++)
  732. {
  733. var e=rows[i];
  734. var editionMedia=e.getAttribute('media');
  735. if(e.getAttribute('addAnyway') == "false")
  736. continue;
  737.  
  738. var seedCount=parseInt(e.getElementsByTagName('td')[3].textContent);
  739. if(seedCount < pers.minSeedCount)
  740. continue;
  741.  
  742. var meta=e.getElementsByTagName('a');
  743. meta=meta[meta.length-1].innerHTML.split(' / ');
  744.  
  745. if(meta[0] == pers.format[0] && meta[1] == pers.bitrate[0] && editionMedia == pers.media[0])
  746. {
  747. best.index=i;
  748. best.score=0;
  749. break;
  750. }
  751.  
  752. if(pers.format.length === 0)
  753. pers.format.push("Any");
  754. if(pers.bitrate.length === 0)
  755. pers.format.push("Any");
  756. if(pers.media.length === 0)
  757. pers.format.push("Any");
  758.  
  759.  
  760. for(var j=0; j<pers.format.length; j++)
  761. {
  762. var f=pers.format[j];
  763. if(f==='')
  764. f='Any';
  765. if(f=="Any" || meta[0]==f)
  766. {
  767. for(var k=0; k<pers.bitrate.length; k++)
  768. {
  769. var b=pers.bitrate[k];
  770. if(b==='')
  771. b='Any';
  772. if(b=="Any" || meta[1]==b)
  773. {
  774. for(var l=0; l<pers.media.length; l++)
  775. {
  776. var m=pers.media[l];
  777. if(m==='')
  778. m='Any';
  779. if(m=="Any" || editionMedia==m)
  780. {
  781. var score = (j*100)+(k*10)+l;
  782. if(score < best.score)
  783. {
  784. best.index=i;
  785. best.score=score;
  786. }
  787. }
  788. }
  789. }
  790. }
  791. }
  792. }
  793. }
  794. return best;
  795. }
  796.  
  797. function addAnywayFunc(tr, event)
  798. {
  799. if(!event.ctrlKey && !event.metaKey)
  800. return;
  801.  
  802. event.preventDefault();
  803.  
  804. var addAnyway = tr.getAttribute("addAnyway");
  805. var adding = tr.getAttribute('class').indexOf('collectorAdded') != -1;
  806. if(adding)
  807. {
  808. tr.setAttribute("addAnyway", false);
  809. document.getElementById('collectorPreviewLink').click();
  810. return;
  811. }
  812. else
  813. {
  814. tr.setAttribute("addAnyway", true);
  815. document.getElementById('collectorPreviewLink').click();
  816. return;
  817. }
  818. }
  819.  
  820. function save(messageDiv)
  821. {
  822. var torrentList=messageDiv.getAttribute('torrentList');
  823. if(!torrentList)
  824. messageDiv.innerHTML = "You need to preview first";
  825. torrentList=JSON.parse(torrentList);
  826. var opSettings = getSettings();
  827. if(opSettings.sequential)
  828. {
  829. messageDiv.setAttribute('stopSequential', "false");
  830. sequentialGet(torrentList, 0, messageDiv);
  831. }
  832. else
  833. {
  834. var zip=new JSZip();
  835.  
  836. var settings=getSettings();
  837. if(settings.summary)
  838. {
  839. var name=messageDiv.getAttribute('zipName').replace(/zip$/, "txt");
  840. var text=messageDiv.getAttribute('summaryText');
  841. zip.file(name.replace(/\//g, '_'), text);
  842. }
  843.  
  844. getTorrent(torrentList, 0, zip, messageDiv);
  845. }
  846. }
  847.  
  848. function sequentialGet(list, index, messageDiv)
  849. {
  850. if(messageDiv.getAttribute('stopSequential') == "true")
  851. {
  852. messageDiv.innerHTML = 'Stopped';
  853. return;
  854. }
  855. if(index >= list.length)
  856. {
  857. messageDiv.innerHTML = 'Finished';
  858. return;
  859. }
  860.  
  861. messageDiv.innerHTML = "Downloading torrent "+(index+1)+" of "+list.length+"<br />";
  862. var a=document.createElement('a');
  863. messageDiv.appendChild(a);
  864. a.innerHTML='Stop';
  865. a.href='javascript:void(0);';
  866. a.addEventListener('click', stopSequential.bind(undefined, messageDiv), false);
  867.  
  868. var a=document.createElement('a');
  869. a.href=list[index].dl;
  870. a.download=list[index].name;
  871. document.body.appendChild(a);
  872. a.click();
  873.  
  874. window.setTimeout(sequentialGet.bind(undefined, list, index+1, messageDiv), 1000);
  875. }
  876.  
  877. function stopSequential(messageDiv)
  878. {
  879. messageDiv.setAttribute('stopSequential', "true");
  880. }
  881.  
  882. function getTorrent(list, index, zip, messageDiv)
  883. {
  884. if(index >= list.length)
  885. {
  886. gotTorrents(zip, messageDiv);
  887. return;
  888. }
  889. messageDiv.innerHTML = "Getting torrent "+(index+1)+" of "+list.length+"<br />"+list[index].name;
  890. var xhr = new XMLHttpRequest();
  891. xhr.open('GET', list[index].dl);
  892. xhr.responseType = "arraybuffer";
  893. xhr.onreadystatechange = xhr_func.bind(undefined, messageDiv, xhr, gotTorrent.bind(undefined, list, index, zip, messageDiv), getTorrent.bind(undefined, list, index, zip, messageDiv), true);
  894. xhr.send();
  895. }
  896.  
  897. function gotTorrent(list, index, zip, messageDiv, response)
  898. {
  899. zip.file(list[index].name.replace(/\//g, '_'), response);
  900. window.setTimeout(getTorrent.bind(undefined, list, index+1, zip, messageDiv), 1000);
  901. }
  902.  
  903. function gotTorrents(zip, messageDiv)
  904. {
  905. messageDiv.innerHTML = 'Generating zip file of torrents';
  906. zip.generateAsync({type:"blob"}).then(saveLink.bind(undefined, messageDiv));
  907. }
  908.  
  909. function saveLink(messageDiv, blob)
  910. {
  911. messageDiv.innerHTML = '';
  912. var a=document.createElement('a');
  913. messageDiv.appendChild(a);
  914. var name=messageDiv.getAttribute('zipName');
  915. a.innerHTML = name;
  916. a.href = URL.createObjectURL(blob);
  917. a.download = name;
  918. }
  919.  
  920. function xhr_func(messageDiv, xhr, func, repeatFunc, binary)
  921. {
  922. if(xhr.readyState == 4)
  923. {
  924. if(xhr.status == 200)
  925. {
  926. if(binary)
  927. {
  928. var byteArray = new Uint8Array(xhr.response);
  929. func(byteArray);
  930. }
  931. else
  932. {
  933. func(xhr.responseText);
  934. }
  935. }
  936. else
  937. {
  938. messageDiv.innerHTML = 'Error: '+xhr.status+'<br />retrying in 1 second';
  939. window.setTimeout(repeatFunc, 1000);
  940. }
  941. }
  942. }