def add_torrent(data): ''' Adds torrent or magnet to rtorrent data: dict of torrrent/magnet information Adds label if set in config Returns dict {'response': True, 'downloadid': 'id'} {'response': False, 'error': 'exception'} ''' conf = core.CONFIG['Downloader']['Torrent']['rTorrentSCGI'] if rTorrentSCGI.client is None: connected = rTorrentSCGI.test_connection(conf) if connected is not True: return {'response': False, 'error': connected} try: if conf['addpaused']: rTorrentSCGI.client.load(data['torrentfile']) else: rTorrentSCGI.client.load_start(data['torrentfile']) downloadid = Torrent.get_hash(data['torrentfile']) if conf['label']: rTorrentSCGI.client.d.set_custom1(downloadid, conf['label']) return {'response': True, 'downloadid': downloadid} except Exception, e: return {'response': False, 'error': str(e)}
def _download_magnet(data, file): ''' Resolves magnet link to torrent file data (dict): release information file (str): absolute path to FILE in which to save file Iterates through bt_cache sites and attempts to get download. The downloaded content is ran through bencode (via core.helpers.Torrent) to make sure the hash from the torrent file (or whatever content was download) matches the hash submitted. Returns bool ''' magnet_hash = data['guid'].upper() for i in bt_cache: try: url = i.format(magnet_hash) logging.info('Attempting to resolve torrent hash through {}'.format(url)) dl_bytes = Url.open(url, stream=True).content h = th.get_hash(dl_bytes, file_bytes=True) if h == magnet_hash: with open(file, 'wb') as f: f.write(dl_bytes) del dl_bytes return True else: continue except Exception as e: logging.warning('Unable to resolve magnet hash.', exc_info=True) continue logging.warning('Torrent hash {} not found on any torrent cache.'.format(magnet_hash)) return False
def snatch_torrent(data): ''' Sends torrent or magnet to download client data (dict): search result from local database Returns dict {'response': True, 'message': 'lorem impsum'} ''' guid = data['guid'] imdbid = data['imdbid'] title = data['title'] kind = data['type'] if urllib.parse.urlparse(guid).netloc: # if guid is not a url and not hash we'll have to get the hash now guid_ = Torrent.get_hash(data['torrentfile']) if not guid_: # torrent url may redirect to magnet uri guid_, magnet = Torrent.get_hash_and_magnet(data['torrentfile']) if magnet: data['torrentfile'] = magnet core.sql.update('SEARCHRESULTS', 'torrentfile', magnet, 'guid', guid) if guid_: core.sql.update('SEARCHRESULTS', 'guid', guid_, 'guid', guid) guid = guid_ else: return {'response': False, 'error': 'Unable to get torrent hash from indexer.'} for client, config in core.CONFIG['Downloader']['Torrent'].items(): if config['enabled']: logging.info('Sending {} to {}'.format(kind, client)) response = getattr(downloaders, client).add_torrent(data) if response['response']: logging.info('Successfully sent {} to {}.'.format(title, client)) db_update = {'downloadid': response['downloadid'], 'download_client': client} core.sql.update_multiple_values('SEARCHRESULTS', db_update, 'guid', guid) if update_status_snatched(guid, imdbid): return {'response': True, 'message': 'Sent to {}.'.format(client), 'download_client': client, 'downloadid': response['downloadid']} else: return {'response': False, 'error': 'Could not mark search result as Snatched.'} else: return response else: return {'response': False, 'error': 'No download client enabled.'}
def _verify_torrent(stream, magnet): ''' Verifies torrent against magnet hash to make sure download is correct stream (str): bitstream of torrent file magnet (str): magnet hash to check against Returns Bool ''' return magnet == th.get_hash(stream, file_bytes=True)
def add_torrent(data): ''' Adds torrent or magnet to qbittorrent data: dict of torrrent/magnet information Adds torrents to default/path/<category> Returns dict {'response': True, 'download_id': 'id'} {'response': False, 'error': 'exception'} ''' conf = core.CONFIG['Downloader']['Torrent']['QBittorrent'] host = conf['host'] port = conf['port'] base_url = u'{}:{}/'.format(host, port) user = conf['user'] password = conf['pass'] # check cookie validity while getting default download dir download_dir = QBittorrent._get_download_dir(base_url) if not download_dir: if QBittorrent._login(base_url, user, password) is not True: return {'response': False, 'error': 'Incorrect usename or password.'} download_dir = QBittorrent._get_download_dir(base_url) if not download_dir: return {'response': False, 'error': 'Unable to get path information.'} # if we got download_dir we can connect. post_data = {} post_data['urls'] = data['torrentfile'] post_data['savepath'] = u'{}{}'.format(download_dir, conf['category']) post_data['category'] = conf['category'] url = u'{}command/download'.format(base_url) post_data = urllib.urlencode(post_data) request = Url.request(url, post_data=post_data) request.add_header('cookie', QBittorrent.cookie) try: Url.open(request) # QBit returns an empty string downloadid = Torrent.get_hash(data['torrentfile']) return {'response': True, 'downloadid': downloadid} except (SystemExit, KeyboardInterrupt): raise except Exception, e: logging.error(u'QBittorrent connection test failed.', exc_info=True) return {'response': False, 'error': str(e.reason)}
def add_torrent(data): ''' Adds torrent or magnet to qbittorrent data: dict of torrrent/magnet information Adds torrents to default/path/<category> Returns dict {'response': True, 'download_id': 'id'} {'response': False, 'error': 'exception'} ''' logging.info('Sending torrent {} to QBittorrent.'.format( data['title'])) conf = core.CONFIG['Downloader']['Torrent']['QBittorrent'] host = conf['host'] port = conf['port'] base_url = '{}:{}/'.format(host, port) user = conf['user'] password = conf['pass'] if QBittorrent.cookie is None: QBittorrent._login(base_url, user, password) download_dir = QBittorrent._get_download_dir(base_url) if not download_dir: return { 'response': False, 'error': 'Unable to get path information.' } # if we got download_dir we can connect. post_data = {} post_data['urls'] = data['torrentfile'] post_data['savepath'] = '{}{}'.format(download_dir, conf['category']) post_data['category'] = conf['category'] url = '{}command/download'.format(base_url) headers = {'cookie': QBittorrent.cookie} try: Url.open(url, post_data=post_data, headers=headers) # QBit returns an empty string downloadid = Torrent.get_hash(data['torrentfile']) return {'response': True, 'downloadid': downloadid} except (SystemExit, KeyboardInterrupt): raise except Exception as e: logging.error('QBittorrent connection test failed.', exc_info=True) return {'response': False, 'error': str(e)}
def add_torrent(data): ''' Adds torrent or magnet to rtorrent data: dict of torrrent/magnet information Adds label if set in config Returns dict {'response': True, 'downloadid': 'id'} {'response': False, 'error': 'exception'} ''' logging.info('Sending torrent {} to rTorrent HTTP RPC Plugin.'.format( data['title'])) conf = core.CONFIG['Downloader']['Torrent']['rTorrentHTTP'] if rTorrentHTTP.client is None: connected = rTorrentHTTP.test_connection(conf) if connected is not True: return {'response': False, 'error': connected} try: downloadid = Torrent.get_hash(data['torrentfile']) if conf['addpaused']: rTorrentHTTP.client.load(data['torrentfile']) else: rTorrentHTTP.client.load_start(data['torrentfile']) if conf['label'] and downloadid: t = 0 while t < 5: if downloadid in rTorrentHTTP.client.download_list(): rTorrentHTTP.client.d.set_custom1( downloadid, conf['label']) return {'response': True, 'downloadid': downloadid} time.sleep(2) t += 1 logging.error( 'Torrent hash ({}) not found in rTorrent after 10 seconds, cannot apply label.' .format(downloadid)) return { 'response': False, 'error': 'Torrent hash not found in rTorrent after 10 seconds, cannot apply label.' } else: return {'response': True, 'downloadid': downloadid} except Exception as e: logging.error('Unable to send torrent to rTorrent HTTP', exc_info=True) return {'response': False, 'error': str(e)[1:-1]}
def add_torrent(data): ''' Adds torrent or magnet to qbittorrent data: dict of torrrent/magnet information Adds torrents to default/path/<category> Returns dict {'response': True, 'download_id': 'id'} {'response': False, 'error': 'exception'} ''' logging.info('Sending torrent {} to QBittorrent.'.format( data['title'])) conf = core.CONFIG['Downloader']['Torrent']['QBittorrent'] host = conf['host'] port = conf['port'] base_url = '{}:{}/'.format(host, port) download_dir = QBittorrent._get_download_dir(base_url) if download_dir is None: return { 'response': False, 'error': 'Unable to get path information.' } # if we got download_dir we can connect. post_data = { 'urls': data['torrentfile'], 'savepath': '{}{}'.format(download_dir, conf['category']), 'category': conf['category'] } try: QBittorrent._send('command/download', post_data=post_data) downloadid = Torrent.get_hash(data['torrentfile']) return {'response': True, 'downloadid': downloadid} except (SystemExit, KeyboardInterrupt): raise except Exception as e: logging.error('QBittorrent command/download failed.', exc_info=True) return {'response': False, 'error': str(e)}
def add_torrent(data): ''' Adds torrent or magnet to deluge web api data: dict of torrrent/magnet information Adds torrents to default/path/<category> Returns dict {'response': 'true', 'download_id': 'id'} {'response': 'false', 'error': 'exception'} ''' deluge_conf = core.CONFIG['DelugeWeb'] host = deluge_conf['delugewebhost'] port = deluge_conf['delugewebport'] url = '{}:{}/json'.format(host, port) # check cookie validity while getting default download dir download_dir = DelugeWeb._get_download_dir(url) if not download_dir: password = deluge_conf['delugewebpass'] if DelugeWeb._login(url, password) is not True: return { 'response': 'false', 'error': 'Incorrect usename or password.' } download_dir = DelugeWeb._get_download_dir(url) if not download_dir: return { 'response': 'false', 'error': 'Unable to get path information.' } # if we got download_dir we can connect. download_dir = '{}/{}'.format(download_dir, deluge_conf['delugewebcategory']) priority_keys = {'Normal': 0, 'High': 128, 'Max': 255} torrent = {'path': data['torrentfile'], 'options': {}} torrent['options']['add_paused'] = deluge_conf[ 'delugewebaddpaused'] == u'true' torrent['options']['download_location'] = download_dir torrent['options']['priority'] = priority_keys[ deluge_conf['delugewebpriority']] command = { 'method': 'web.add_torrents', 'params': [[torrent]], 'id': DelugeWeb.command_id } DelugeWeb.command_id += 1 post_data = json.dumps(command) request = urllib2.Request(url, post_data, headers={'User-Agent': 'Mozilla/5.0'}) request.add_header('cookie', DelugeWeb.cookie) try: response = DelugeWeb._read(urllib2.urlopen(request)) if response['result'] is True: downloadid = Torrent.get_hash(data['torrentfile']) return {'response': 'true', 'downloadid': downloadid} else: return {'response': 'false', 'error': response['error']} except (SystemExit, KeyboardInterrupt): raise except Exception, e: logging.error(u'Delugeweb add_torrent', exc_info=True) return {'response': 'false', 'error': str(e)}
def add_torrent(data): ''' Adds torrent or magnet to deluge web api data (dict): torrrent/magnet information Adds torrents to default/path/<category> Returns dict ajax-style response ''' global command_id logging.info('Sending torrent {} to Deluge Web UI.'.format(data['title'])) conf = core.CONFIG['Downloader']['Torrent']['DelugeWeb'] host = conf['host'] port = conf['port'] url = '{}:{}/json'.format(host, port) priority_keys = { 'Low': 64, 'Normal': 128, 'High': 255, } if cookie is None: if _login(url, conf['pass']) is not True: return { 'response': False, 'error': 'Incorrect usename or password.' } download_dir = _get_download_dir(url) if not download_dir: return {'response': False, 'error': 'Unable to get path information.'} # if we got download_dir we can connect. download_dir = '{}/{}'.format(download_dir, conf['category']) # if file is a torrent, have deluge download it to a tmp dir if data['type'] == 'torrent': tmp_torrent_file = _get_torrent_file(data['torrentfile'], url) if tmp_torrent_file['response'] is True: torrent = {'path': tmp_torrent_file['torrentfile'], 'options': {}} else: return {'response': False, 'error': tmp_torrent_file['error']} else: torrent = {'path': data['torrentfile'], 'options': {}} torrent['options']['add_paused'] = conf['addpaused'] torrent['options']['download_location'] = download_dir torrent['options']['priority'] = priority_keys[conf['priority']] command = { 'method': 'web.add_torrents', 'params': [[torrent]], 'id': command_id } command_id += 1 post_data = json.dumps(command) headers['cookie'] = cookie try: response = Url.open(url, post_data=post_data, headers=headers) response = json.loads(response.text) if response['result'] is True: downloadid = Torrent.get_hash(data['torrentfile']) else: return {'response': False, 'error': response['error']} except (SystemExit, KeyboardInterrupt): raise except Exception as e: logging.error('Delugeweb add_torrent', exc_info=True) return {'response': False, 'error': str(e)} _set_label(downloadid, conf['category'], url) return {'response': True, 'downloadid': downloadid}
def snatch_torrent(self, data): ''' Sends torrent or magnet to download client data (dict): search result from local database Returns dict {'response': True, 'message': 'lorem impsum'} ''' guid = data['guid'] imdbid = data['imdbid'] title = data['title'] kind = data['type'] if urllib.parse.urlparse(guid).netloc: # if guid is not a url and not hash we'll have to get the hash now guid_ = Torrent.get_hash(data['torrentfile']) if guid_: core.sql.update('SEARCHRESULTS', 'guid', guid_, 'guid', guid) guid = guid_ else: return { 'response': False, 'error': 'Unable to get torrent hash from indexer.' } # If sending to Transmission transmission_conf = core.CONFIG['Downloader']['Torrent'][ 'Transmission'] if transmission_conf['enabled'] is True: logging.info('Sending {} to Transmission.'.format(kind)) response = transmission.Transmission.add_torrent(data) if response['response'] is True: logging.info( 'Successfully sent {} to Transmission.'.format(title)) db_update = { 'downloadid': response['downloadid'], 'download_client': 'Transmission' } core.sql.update_multiple_values('SEARCHRESULTS', db_update, guid=guid) if self.update_status_snatched(guid, imdbid): return { 'response': True, 'message': 'Sent to Transmission.', 'download_client': 'Transmission', 'downloadid': response['downloadid'] } else: return { 'response': False, 'error': 'Could not mark search result as Snatched.' } else: return response # If sending to QBittorrent qbit_conf = core.CONFIG['Downloader']['Torrent']['QBittorrent'] if qbit_conf['enabled'] is True: logging.info('Sending {} to QBittorrent.'.format(kind)) response = qbittorrent.QBittorrent.add_torrent(data) if response['response'] is True: logging.info( 'Successfully sent {} to QBittorrent.'.format(title)) db_update = { 'downloadid': response['downloadid'], 'download_client': 'QBittorrent' } core.sql.update_multiple_values('SEARCHRESULTS', db_update, guid=guid) if self.update_status_snatched(guid, imdbid): return { 'response': True, 'message': 'Sent to QBittorrent.', 'download_client': 'QBittorrent', 'downloadid': response['downloadid'] } else: return { 'response': False, 'error': 'Could not mark search result as Snatched.' } else: return response # If sending to DelugeRPC delugerpc_conf = core.CONFIG['Downloader']['Torrent']['DelugeRPC'] if delugerpc_conf['enabled'] is True: logging.info('Sending {} to DelugeRPC.'.format(kind)) response = deluge.DelugeRPC.add_torrent(data) if response['response'] is True: logging.info( 'Successfully sent {} to DelugeRPC.'.format(title)) db_update = { 'downloadid': response['downloadid'], 'download_client': 'DelugeRPC' } core.sql.update_multiple_values('SEARCHRESULTS', db_update, guid=guid) if self.update_status_snatched(guid, imdbid): return { 'response': True, 'message': 'Sent to Deluge.', 'download_client': 'DelugeRPC', 'downloadid': response['downloadid'] } else: return { 'response': False, 'error': 'Could not mark search result as Snatched.' } else: return response # If sending to DelugeWeb delugeweb_conf = core.CONFIG['Downloader']['Torrent']['DelugeWeb'] if delugeweb_conf['enabled'] is True: logging.info('Sending {} to DelugeWeb.'.format(kind)) response = deluge.DelugeWeb.add_torrent(data) if response['response'] is True: logging.info( 'Successfully sent {} to DelugeWeb.'.format(title)) db_update = { 'downloadid': response['downloadid'], 'download_client': 'DelugeWeb' } core.sql.update_multiple_values('SEARCHRESULTS', db_update, guid=guid) if self.update_status_snatched(guid, imdbid): return { 'response': True, 'message': 'Sent to Deluge.', 'download_client': 'DelugeWeb', 'downloadid': response['downloadid'] } else: return { 'response': False, 'error': 'Could not mark search result as Snatched.' } else: return response # If sending to rTorrentSCGI rtorrent_conf = core.CONFIG['Downloader']['Torrent']['rTorrentSCGI'] if rtorrent_conf['enabled'] is True: logging.info('Sending {} to rTorrent.'.format(kind)) response = rtorrent.rTorrentSCGI.add_torrent(data) if response['response'] is True: logging.info('Successfully sent {} to rTorrent.'.format(title)) db_update = { 'downloadid': response['downloadid'], 'download_client': 'rTorrentSCGI' } core.sql.update_multiple_values('SEARCHRESULTS', db_update, guid=guid) if self.update_status_snatched(guid, imdbid): return { 'response': True, 'message': 'Sent to rTorrent.', 'download_client': 'rTorrentSCGI', 'downloadid': response['downloadid'] } else: return { 'response': False, 'error': 'Could not mark ' 'search result as Snatched.' } else: return response # If sending to rTorrentHTTP via ruTorrent plugin rtorrent_conf = core.CONFIG['Downloader']['Torrent']['rTorrentHTTP'] if rtorrent_conf['enabled'] is True: logging.info('Sending {} to rTorrent.'.format(kind)) response = rtorrent.rTorrentHTTP.add_torrent(data) if response['response'] is True: logging.info('Successfully sent {} to rTorrent.'.format(title)) db_update = { 'downloadid': response['downloadid'], 'download_client': 'rTorrentHTTP' } core.sql.update_multiple_values('SEARCHRESULTS', db_update, guid=guid) if self.update_status_snatched(guid, imdbid): return { 'response': True, 'message': 'Sent to rTorrent.', 'download_client': 'rTorrentHTTP', 'downloadid': response['downloadid'] } else: return { 'response': False, 'error': 'Could not mark search result as Snatched.' } else: return response # If sending to BlackHole blackhole_conf = core.CONFIG['Downloader']['Torrent']['BlackHole'] if blackhole_conf['enabled'] is True: d = blackhole_conf['directory'] logging.info('Saving {} as {}'.format(kind, os.path.join(d, title))) response = blackhole.Torrent.add_torrent(data) if response['response'] is True: logging.info( 'Successfully saved {} in BlackHole.'.format(title)) db_update = { 'downloadid': response['downloadid'], 'download_client': 'BlackHole' } core.sql.update_multiple_values('SEARCHRESULTS', db_update, guid=guid) db_update = { 'downloadid': response['downloadid'], 'download_client': 'BlackHole' } core.sql.update_multiple_values('SEARCHRESULTS', db_update, guid=guid) if self.update_status_snatched(guid, imdbid): return { 'response': True, 'message': 'Saved to BlackHole.', 'download_client': 'BlackHole', 'downloadid': None } else: return { 'response': False, 'error': 'Could not mark search result as Snatched.' } else: return response else: return {'response': False, 'error': 'No download client enabled.'}
def add_torrent(data): ''' Adds torrent or magnet to deluge web api data: dict of torrrent/magnet information Adds torrents to default/path/<category> Returns dict {'response': True, 'download_id': 'id'} {'response': False, 'error': 'exception'} ''' conf = core.CONFIG['Downloader']['Torrent']['DelugeWeb'] host = conf['host'] port = conf['port'] url = u'{}:{}/json'.format(host, port) priority_keys = {'Normal': 0, 'High': 128, 'Max': 255} # check cookie validity while getting default download dir download_dir = DelugeWeb._get_download_dir(url) if not download_dir: password = conf['pass'] if DelugeWeb._login(url, password) is not True: return { 'response': False, 'error': 'Incorrect usename or password.' } download_dir = DelugeWeb._get_download_dir(url) if not download_dir: return { 'response': False, 'error': 'Unable to get path information.' } # if we got download_dir we can connect. download_dir = u'{}/{}'.format(download_dir, conf['category']) # if file is a torrent, have deluge download it to a tmp dir if data['type'] == 'torrent': tmp_torrent_file = DelugeWeb._get_torrent_file( data['torrentfile'], url) if tmp_torrent_file['response'] is True: data['torrentfile'] = tmp_torrent_file['torrentfile'] else: return {'response': False, 'error': tmp_torrent_file['error']} torrent = {'path': data['torrentfile'], 'options': {}} torrent['options']['add_paused'] = conf['addpaused'] torrent['options']['download_location'] = download_dir torrent['options']['priority'] = priority_keys[conf['priority']] command = { 'method': 'web.add_torrents', 'params': [[torrent]], 'id': DelugeWeb.command_id } DelugeWeb.command_id += 1 post_data = json.dumps(command) request = Url.request(url, post_data=post_data, headers=DelugeWeb.headers) request.add_header('cookie', DelugeWeb.cookie) try: response = DelugeWeb._read(Url.open(request)) if response['result'] is True: downloadid = Torrent.get_hash(data['torrentfile']) return {'response': True, 'downloadid': downloadid} else: return {'response': False, 'error': response['error']} except (SystemExit, KeyboardInterrupt): raise except Exception, e: logging.error(u'Delugeweb add_torrent', exc_info=True) return {'response': False, 'error': str(e)}