Open Magnets in Transmission.user.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // ==UserScript==
  2. // @name Open Magnets in Transmission
  3. // @namespace ca.tarka.home
  4. // @description Open magnet links from ThePirateBay in the Transmission web client
  5. // @include https://thepiratebay.org/*
  6. // @include https://www.thepiratebay.org/*
  7. // @include https://thepiratebay.se/*
  8. // @include https://www.thepiratebay.se/*
  9. // @include https://1337x.to/*
  10. // @include https://tpb.party/*
  11. // @include https://thepiratebay.net/*
  12. // @include https://downloadtorrentfile.com/*
  13. // @include https://rarbg2020.org/*
  14. // @include https://torrentz2eu.org/*
  15. // @include http://storm:9091/*
  16. // @include storm.tarka:9091/*
  17. // @include https://bittorrent/*
  18. // @include https://bittorrent.tarka/*
  19. // @connect storm.tarka
  20. // @connect storm.tarka:9091
  21. // @connect bittorrent
  22. // @connect bittorrent.tarka
  23. // @version 1.1
  24. // @grant GM_xmlhttpRequest
  25. // @grant GM_setValue
  26. // @grant GM_getValue
  27. // ==/UserScript==
  28. const options = {
  29. host: 'bittorrent',
  30. altHosts: ['bt', 'bittorrent.tarka', 'bt.tarka', 'storm:9091', 'storm.tarka:9091', 'bittorrent'],
  31. auth: 'YnQ6bm9QYXNzd29yZDEyMw==',
  32. destination: '/var/lib/transmission-daemon/downloads/unsorted'
  33. };
  34. const csrfTokenkey = 'csrfToken';
  35. (function() {
  36. let host = document.location.host;
  37. if( host == options.host || options.altHosts.includes(host) ) {
  38. getCsrfToken();
  39. //setConfig();
  40. } else if( self == top ) {
  41. setTimeout( setupLinks, 300 );
  42. }
  43. })();
  44. function getCsrfToken() {
  45. console.log( 'Attempting to get CSRF token' );
  46. if( !unsafeWindow.transmission ) {
  47. console.log( 'Transmission doesn\'t exist on window. Trying again.' );
  48. return setTimeout( getCsrfToken, 100 );
  49. }
  50. let token = unsafeWindow.transmission.remote._token;
  51. console.log( 'Storing CSRF token:', token );
  52. GM_setValue( csrfTokenkey, token );
  53. }
  54. function setConfig() {
  55. console.log( 'Attempting to set seeding config' );
  56. const data = {
  57. method: "session-set",
  58. arguments: {
  59. "seedRatioLimited": true,
  60. "seedRatioLimit": 0.001,
  61. "idle-seeding-limit-enabled": true,
  62. "idle-seeding-limit": 1,
  63. "speed-limit-up-enabled": true,
  64. "speed-limit-up": 5
  65. }
  66. };
  67. postData( data, () => console.log( 'Updated configs' ), false );
  68. }
  69. var searches = 0;
  70. function setupLinks() {
  71. console.log( 'setting up links' );
  72. let links = Array.from( document.querySelectorAll( 'a[href^="magnet:"]' ) );
  73. if( ++searches >= 10 ) {
  74. console.error( 'Too many searches. Aborting.' );
  75. return;
  76. }
  77. if( !links.length ) {
  78. console.log( 'No links found on page. Trying again in a moment.', links );
  79. return setTimeout( setupLinks, 50 );
  80. } else {
  81. console.log( 'Got links', links );
  82. links.forEach( x => x.addEventListener( 'click', clickLink ) );
  83. }
  84. }
  85. function clickLink( event ) {
  86. console.log( 'Clicking link', event );
  87. let magnet = this.href;
  88. startTorrent( magnet );
  89. // Stop the link from being clicked
  90. event.preventDefault();
  91. }
  92. function startTorrent( magnet ) {
  93. let data = {
  94. method: 'torrent-add',
  95. arguments: {
  96. paused: false,
  97. 'download-dir': options.destination,
  98. filename: magnet
  99. }
  100. };
  101. postData(
  102. data,
  103. () => alert( 'Successfully added torrent' ),
  104. true
  105. );
  106. }
  107. function postData( data, success, showError ) {
  108. GM_xmlhttpRequest( {
  109. method: 'POST',
  110. url: `https://${options.host}/transmission/rpc`,
  111. data: JSON.stringify( data ),
  112. headers: {
  113. 'Authorization': `Basic ${options.auth}`,
  114. 'X-Transmission-Session-Id': GM_getValue( csrfTokenkey )
  115. },
  116. onload: response => {
  117. if( response.status != 200 ) {
  118. return onError( response );
  119. }
  120. success();
  121. },
  122. onerror: response => {
  123. console.error( response );
  124. if( showError ) {
  125. alert( 'An error occurred adding the torrent' );
  126. }
  127. }
  128. } );
  129. function onError( response ) {
  130. console.error( response );
  131. if( !showError ) {
  132. return;
  133. }
  134. if( response.statusText == 'Conflist' ) {
  135. alert('Received "Conflict" error.\n\nHas this torrent already been added?');
  136. } else if( response.status == 409 ) {
  137. alert( 'CSRF token is out of date.\n\nPlease open the Transmission UI in another tab, then try again' );
  138. } else {
  139. alert( 'Unknown error occurred adding the event. More details available in the browser console.' );
  140. }
  141. }
  142. }