// ==UserScript== // @name Open Magnets in Transmission // @namespace ca.tarka.home // @description Open magnet links from ThePirateBay in the Transmission web client // @include https://thepiratebay.org/* // @include https://www.thepiratebay.org/* // @include https://thepiratebay.se/* // @include https://www.thepiratebay.se/* // @include https://1337x.to/* // @include https://tpb.party/* // @include https://thepiratebay.net/* // @include https://downloadtorrentfile.com/* // @include https://rarbg2020.org/* // @include https://torrentz2eu.org/* // @include http://storm:9091/* // @include storm.tarka:9091/* // @include https://bittorrent/* // @include https://bittorrent.tarka/* // @connect storm.tarka // @connect storm.tarka:9091 // @connect bittorrent // @connect bittorrent.tarka // @version 1.1 // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // ==/UserScript== const options = { host: 'bittorrent', altHosts: ['bt', 'bittorrent.tarka', 'bt.tarka', 'storm:9091', 'storm.tarka:9091', 'bittorrent'], auth: 'YnQ6bm9QYXNzd29yZDEyMw==', destination: '/var/lib/transmission-daemon/downloads/unsorted' }; const csrfTokenkey = 'csrfToken'; (function() { let host = document.location.host; if( host == options.host || options.altHosts.includes(host) ) { getCsrfToken(); //setConfig(); } else if( self == top ) { setTimeout( setupLinks, 300 ); } })(); function getCsrfToken() { console.log( 'Attempting to get CSRF token' ); if( !unsafeWindow.transmission ) { console.log( 'Transmission doesn\'t exist on window. Trying again.' ); return setTimeout( getCsrfToken, 100 ); } let token = unsafeWindow.transmission.remote._token; console.log( 'Storing CSRF token:', token ); GM_setValue( csrfTokenkey, token ); } function setConfig() { console.log( 'Attempting to set seeding config' ); const data = { method: "session-set", arguments: { "seedRatioLimited": true, "seedRatioLimit": 0.001, "idle-seeding-limit-enabled": true, "idle-seeding-limit": 1, "speed-limit-up-enabled": true, "speed-limit-up": 5 } }; postData( data, () => console.log( 'Updated configs' ), false ); } var searches = 0; function setupLinks() { console.log( 'setting up links' ); let links = Array.from( document.querySelectorAll( 'a[href^="magnet:"]' ) ); if( ++searches >= 10 ) { console.error( 'Too many searches. Aborting.' ); return; } if( !links.length ) { console.log( 'No links found on page. Trying again in a moment.', links ); return setTimeout( setupLinks, 50 ); } else { console.log( 'Got links', links ); links.forEach( x => x.addEventListener( 'click', clickLink ) ); } } function clickLink( event ) { console.log( 'Clicking link', event ); let magnet = this.href; startTorrent( magnet ); // Stop the link from being clicked event.preventDefault(); } function startTorrent( magnet ) { let data = { method: 'torrent-add', arguments: { paused: false, 'download-dir': options.destination, filename: magnet } }; postData( data, () => alert( 'Successfully added torrent' ), true ); } function postData( data, success, showError ) { GM_xmlhttpRequest( { method: 'POST', url: `https://${options.host}/transmission/rpc`, data: JSON.stringify( data ), headers: { 'Authorization': `Basic ${options.auth}`, 'X-Transmission-Session-Id': GM_getValue( csrfTokenkey ) }, onload: response => { if( response.status != 200 ) { return onError( response ); } success(); }, onerror: response => { console.error( response ); if( showError ) { alert( 'An error occurred adding the torrent' ); } } } ); function onError( response ) { console.error( response ); if( !showError ) { return; } if( response.statusText == 'Conflist' ) { alert('Received "Conflict" error.\n\nHas this torrent already been added?'); } else if( response.status == 409 ) { alert( 'CSRF token is out of date.\n\nPlease open the Transmission UI in another tab, then try again' ); } else { alert( 'Unknown error occurred adding the event. More details available in the browser console.' ); } } }