PTH Collector

Download multiple torrents by some criteria on PTH

目前為 2016-12-17 提交的版本,檢視 最新版本

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