def torrent_params_from_magnet_link(self, mag_link): res = lt.parse_magnet_uri(mag_link) # DAMN YOU LIBTORRENT res['info_hash'] = hex_to_hash(str(res['info_hash']).decode('hex')) res["save_path"] = self.torrent_data_path return res
def addMagnetLink(self, url, paused = False): params = libtorrent.parse_magnet_uri(url) info_hash = str(params['info_hash']).lower() download = self.findTorrentByHash(info_hash) if download: return download else: save_path = self.cache_path atp = {} atp["save_path"] = save_path atp["storage_mode"] = libtorrent.storage_mode_t.storage_mode_sparse atp["auto_managed"] = True atp["duplicate_is_error"] = True #atp["paused"] = paused atp["url"] = url if paused: atp['flags'] = libtorrent.add_torrent_params_flags_t.flag_paused else: atp['flags'] = 0 handle = self.session.add_torrent(atp) handle.set_max_connections(60) handle.set_max_uploads(-1) download = TorrentDownload(handle, self, save_path) self.downloads.append(download) self.download_added.emit(download) return download
def test_parse_magnet_uri(self): ses = lt.session({}) magnet = 'magnet:?xt=urn:btih:C6EIF4CCYDBTIJVG3APAGM7M4NDONCTI' p = lt.parse_magnet_uri(magnet) p['save_path'] = '.' h = ses.add_torrent(p) self.assertEqual(str(h.info_hash()), '178882f042c0c33426a6d81e0333ece346e68a68')
def test_parse_magnet_uri(self): ses = lt.session({}) magnet = 'magnet:?xt=urn:btih:C6EIF4CCYDBTIJVG3APAGM7M4NDONCTI' p = lt.parse_magnet_uri(magnet) self.assertEqual(str(p.info_hash), '178882f042c0c33426a6d81e0333ece346e68a68') p.save_path = '.' h = ses.add_torrent(p) self.assertEqual(str(h.info_hash()), '178882f042c0c33426a6d81e0333ece346e68a68')
def download_torrent(self, magnet): import libtorrent as lt if not self.download_dir: raise RuntimeError( 'No download_dir specified in video.omxplayer configuration') ses = lt.session() ses.listen_on(*self.torrent_ports) info = lt.parse_magnet_uri(magnet) logging.info('Downloading "{}" to "{}" from [{}]'.format( info['name'], self.download_dir, magnet)) params = { 'save_path': self.download_dir, 'storage_mode': lt.storage_mode_t.storage_mode_sparse, } transfer = lt.add_magnet_uri(ses, magnet, params) status = transfer.status() files = [] self.torrent_state = { 'url': magnet, 'title': info['name'], } while (not status.is_seeding): status = transfer.status() torrent_file = transfer.torrent_file() if torrent_file: files = [ os.path.join(self.download_dir, torrent_file.files().file_path(i)) for i in range(0, torrent_file.files().num_files()) if self._is_video_file(torrent_file.files().file_name(i)) ] self.torrent_state['progress'] = 100 * status.progress self.torrent_state['download_rate'] = status.download_rate self.torrent_state['upload_rate'] = status.upload_rate self.torrent_state['num_peers'] = status.num_peers self.torrent_state['state'] = status.state logging.info( ('Torrent download: {:.2f}% complete (down: {:.1f} kb/s ' + 'up: {:.1f} kB/s peers: {} state: {})').format( status.progress * 100, status.download_rate / 1000, status.upload_rate / 1000, status.num_peers, status.state)) time.sleep(5) return Response(output=files)
def magnet_atp(protos: tuple[conftest.Proto, conftest.Proto], atp: lt.add_torrent_params) -> lt.add_torrent_params: magnet_proto, _ = protos assert atp.ti is not None magnet = lt.parse_magnet_uri(lt.make_magnet_uri(atp.ti)) if not (magnet_proto & conftest.V1): magnet.info_hashes = lt.info_hash_t(magnet.info_hashes.v2) elif not (magnet_proto & conftest.V2): magnet.info_hashes = lt.info_hash_t(magnet.info_hashes.v1) return magnet
def process(self, entry, destination_folder, timeout): import libtorrent magnet_uri = entry['url'] params = libtorrent.parse_magnet_uri(magnet_uri) session = libtorrent.session() lt_version = [int(v) for v in libtorrent.version.split('.')] if lt_version > [0, 16, 13, 0] and lt_version < [1, 1, 3, 0]: # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash params['info_hash'] = params['info_hash'].to_bytes() params.url = magnet_uri handle = session.add_torrent(params) log.debug('Acquiring torrent metadata for magnet %s', magnet_uri) handle.force_dht_announce() timeout_value = timeout while not handle.has_metadata(): time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: raise plugin.PluginError( 'Timed out after {} seconds trying to magnetize'.format( timeout)) log.debug('Metadata acquired') torrent_info = handle.get_torrent_info() torrent_file = libtorrent.create_torrent(torrent_info) torrent_path = pathscrub( os.path.join(destination_folder, torrent_info.name() + ".torrent")) with open(torrent_path, "wb") as f: f.write(libtorrent.bencode(torrent_file.generate())) log.debug('Torrent file wrote to %s', torrent_path) # Windows paths need an extra / prepended to them for url if not torrent_path.startswith('/'): torrent_path = '/' + torrent_path entry['url'] = torrent_path entry['file'] = torrent_path # make sure it's first in the list because of how download plugin works entry['urls'].insert(0, 'file://{}'.format(torrent_path)) entry['content_size'] = torrent_info.total_size() / 1024 / 1024 # Might as well get some more info while handle.status(0).num_complete < 0: time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: log.debug('Timed out after {} seconds trying to get peer info'. format(timeout)) return log.debug('Peer info acquired') torrent_status = handle.status(0) entry['torrent_seeds'] = torrent_status.num_complete entry['torrent_leeches'] = torrent_status.num_incomplete
def addTorrent(self): print(self.torrent) if self.torrent.startswith('magnet:'): atp = lt.add_torrent_params() atp = lt.parse_magnet_uri(self.torrent) atp.save_path = '.' h = self.ses.add_torrent(atp) else: info = lt.torrent_info(self.torrent) h = self.ses.add_torrent({'ti': info, 'save_path': '.'}) return h
def _get_torrent_info(self, torrent, download_dir): import libtorrent as lt torrent_file = None magnet = None info = {} file_info = {} # noinspection HttpUrlsUsage if torrent.startswith('magnet:?'): magnet = torrent magnet_info = lt.parse_magnet_uri(magnet) if isinstance(magnet_info, dict): info = { 'name': magnet_info.get('name'), 'url': magnet, 'magnet': magnet, 'trackers': magnet_info.get('trackers', []), 'save_path': download_dir, } else: info = { 'name': magnet_info.name, 'url': magnet, 'magnet': magnet, 'trackers': magnet_info.trackers, 'save_path': download_dir, } elif torrent.startswith('http://') or torrent.startswith('https://'): response = requests.get(torrent, allow_redirects=True) torrent_file = os.path.join(download_dir, self._generate_rand_filename()) with open(torrent_file, 'wb') as f: f.write(response.content) else: torrent_file = os.path.abspath(os.path.expanduser(torrent)) if not os.path.isfile(torrent_file): raise RuntimeError( '{} is not a valid torrent file'.format(torrent_file)) if torrent_file: file_info = lt.torrent_info(torrent_file) # noinspection PyArgumentList info = { 'name': file_info.name(), 'url': torrent, 'trackers': [t.url for t in list(file_info.trackers())], 'save_path': download_dir, } return info, file_info, torrent_file, magnet
def download_torrent(torrent_source, save_location, output_file_name): #Start a session session = libtorrent.session({'listen_interfaces': '0.0.0.0:6881'}) #Check if we are dealing with a torrent file or a magnet link if torrent_source.endswith('.torrent'): #Parse torrent file parameters torrent_file = download_file(torrent_source) torrent_info = libtorrent.torrent_info(torrent_file) torrent_in_progress = session.add_torrent({ 'ti': torrent_info, 'save_path': save_location }) remove(torrent_file) else: #Parse magnet URI parameters torrent_info = libtorrent.parse_magnet_uri(torrent_source).get( 'info_hash') torrent_in_progress = session.add_torrent({ 'ti': torrent_info, 'save_path': save_location }) logging.info(f'Starting download: {torrent_in_progress.name()}.') while (not torrent_in_progress.is_seed()): status = torrent_in_progress.status() sleep(1) logging.info('{:.2f}% complete. (Speed: {:.1f} kB/s)'.format( status.progress * 100, status.download_rate / 1000)) alerts = session.pop_alerts() for a in alerts: if a.category() & libtorrent.alert.category_t.error_notification: logging.error(f'{str(a)}') #TODO test files with more than one . in the name output_file_name += str(path.splitext(str(torrent_in_progress.name()))[1]) rename(f'{save_location}/{torrent_in_progress.name()}', f'{save_location}/{output_file_name}') logging.info(f'{torrent_in_progress.name()} - Download complete.') #return output_file_name, torrent_in_progress.name() return f'{save_location}/{output_file_name}', f'{torrent_in_progress.name()}'
def add_torrent(ses, filename, options): atp = lt.add_torrent_params() if filename.startswith('magnet:'): atp = lt.parse_magnet_uri(filename) else: atp.ti = lt.torrent_info(filename) try: atp.resume_data = open(os.path.join(options.save_path, atp.info.name() + '.fastresume'), 'rb').read() except Exception: pass atp.save_path = options.save_path atp.storage_mode = lt.storage_mode_t.storage_mode_sparse atp.flags |= lt.torrent_flags.duplicate_is_error \ | lt.torrent_flags.auto_managed \ | lt.torrent_flags.duplicate_is_error ses.async_add_torrent(atp)
def magnet2torrent_worker(magnet): logger.info('magnet2torrent: start [%s]', magnet) session = libtorrent.session() params = libtorrent.parse_magnet_uri(magnet) # bug: TypeError: No registered converter was able to produce a C++ # rvalue of type bytes from this Python object of type sha1_hash params.update({'info_hash': params['info_hash'].to_bytes()}) handle = session.add_torrent(params) if not handle.is_valid(): logger.error('magnet2torrent: invalid handle') time_lim = time.time() + 3 * 60 while not handle.has_metadata(): time.sleep(0.1) if time.time() > time_lim: logger.info( 'magnet2torrent: the waiting time of metadata has expired') break session.pause() try: torinfo = handle.get_torrent_info() if not torinfo: raise ValueError('magnet2torrent: failed getting torrent info') torfile = libtorrent.create_torrent(torinfo) except Exception: logger.exception('magnet2torrent: failed creating torrent file') return try: torrent_content = libtorrent.bencode(torfile.generate()) if torrent_content: logger.info('magnet2torrent: done [%s]', magnet) return torinfo.name() + '.torrent', torrent_content else: logger.error('magnet2torrent: empty torrent content body [%s]', magnet) except Exception: logger.exception('magnet2torrent: torrent generating problem [%s]', magnet)
def add_torrent(ses, filename, options): atp = lt.add_torrent_params() if filename.startswith('magnet:'): atp = lt.parse_magnet_uri(filename) else: ti = lt.torrent_info(filename) resume_file = os.path.join(options.save_path, ti.name() + '.fastresume') try: atp = lt.read_resume_data(open(resume_file, 'rb').read()) except Exception as e: print('failed to open resume file "%s": %s' % (resume_file, e)) atp.ti = ti atp.save_path = options.save_path atp.storage_mode = lt.storage_mode_t.storage_mode_sparse atp.flags |= lt.torrent_flags.duplicate_is_error \ | lt.torrent_flags.auto_managed \ | lt.torrent_flags.duplicate_is_error ses.async_add_torrent(atp)
def add_torrent(ses: lt.session, filename: str, options: optparse.Values) -> None: atp = lt.add_torrent_params() if filename.startswith("magnet:"): atp = lt.parse_magnet_uri(filename) else: ti = lt.torrent_info(filename) resume_file = os.path.join(options.save_path, ti.name() + ".fastresume") try: atp = lt.read_resume_data(open(resume_file, "rb").read()) except Exception as e: print('failed to open resume file "%s": %s' % (resume_file, e)) atp.ti = ti atp.save_path = options.save_path atp.storage_mode = lt.storage_mode_t.storage_mode_sparse atp.flags |= (lt.torrent_flags.duplicate_is_error | lt.torrent_flags.auto_managed | lt.torrent_flags.duplicate_is_error) ses.async_add_torrent(atp)
def magnet2torrent_worker(magnet): logger.info('magnet2torrent: start [%s]', magnet) session = libtorrent.session() params = libtorrent.parse_magnet_uri(magnet) # bug: TypeError: No registered converter was able to produce a C++ # rvalue of type bytes from this Python object of type sha1_hash params.update({'info_hash': params['info_hash'].to_bytes()}) handle = session.add_torrent(params) if not handle.is_valid(): logger.error('magnet2torrent: invalid handle') time_lim = time.time() + 3*60 while not handle.has_metadata(): time.sleep(0.1) if time.time() > time_lim: logger.info('magnet2torrent: the waiting time of metadata has expired') break session.pause() try: torinfo = handle.get_torrent_info() if not torinfo: raise ValueError('magnet2torrent: failed getting torrent info') torfile = libtorrent.create_torrent(torinfo) except Exception: logger.exception('magnet2torrent: failed creating torrent file') return try: torrent_content = libtorrent.bencode(torfile.generate()) if torrent_content: logger.info('magnet2torrent: done [%s]', magnet) return torinfo.name() + '.torrent', torrent_content else: logger.error('magnet2torrent: empty torrent content body [%s]', magnet) except Exception: logger.exception('magnet2torrent: torrent generating problem [%s]', magnet)
def magnet_to_torrent(self, magnet_uri, destination_folder, timeout=60): import libtorrent params = libtorrent.parse_magnet_uri(magnet_uri) session = libtorrent.session() handle = session.add_torrent(params) log.debug('Acquiring torrent metadata for magnet {}'.format(magnet_uri)) timeout_value = timeout while not handle.has_metadata(): time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: raise Exception('Timed out after {} seconds acquiring torrent metadata from the DHT/trackers.'.format( timeout )) log.debug('Metadata acquired') torrent_info = handle.get_torrent_info() torrent_file = libtorrent.create_torrent(torrent_info) torrent_path = pathscrub(os.path.join(destination_folder, torrent_info.name() + ".torrent")) with open(torrent_path, "wb") as f: f.write(libtorrent.bencode(torrent_file.generate())) log.debug('Torrent file wrote to {}'.format(torrent_path)) return torrent_path
def magnet2torrent(magnet, output_path): """ Convert magnet link to Torrent file. Code from Daniel Folkes: https://github.com/danfolkes/Magnet2Torrent Args: magnet(str): The magnet link. output_path(str): The absolute path to write the Torrent file. """ global logger tempdir = tempfile.mkdtemp() session = lt.session() params = lt.parse_magnet_uri(magnet) params.save_path = tempdir handle = session.add_torrent(params) logger.debug("Downloading Metadata...") while not handle.status().has_metadata: try: sleep(1) except KeyboardInterrupt: logger.debug("Aborting...") session.pause() logger.debug("Cleanup dir %s", tempdir) shutil.rmtree(tempdir) sys.exit(0) session.pause() torinfo = handle.torrent_file() torfile = lt.create_torrent(torinfo) with open(output_path, "wb") as f: f.write(lt.bencode(torfile.generate())) logger.debug("Saved! Cleaning up dir: %s", tempdir) session.remove_torrent(handle) shutil.rmtree(tempdir)
def magnet_to_torrent(self, magnet_uri, destination_folder, timeout): import libtorrent params = libtorrent.parse_magnet_uri(magnet_uri) session = libtorrent.session() # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash params["info_hash"] = bytes(params["info_hash"]) handle = libtorrent.add_magnet_uri(session, magnet_uri, params) log.debug("Acquiring torrent metadata for magnet %s", magnet_uri) timeout_value = timeout while not handle.has_metadata(): time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: raise plugin.PluginError("Timed out after {} seconds trying to magnetize".format(timeout)) log.debug("Metadata acquired") torrent_info = handle.get_torrent_info() torrent_file = libtorrent.create_torrent(torrent_info) torrent_path = pathscrub(os.path.join(destination_folder, torrent_info.name() + ".torrent")) with open(torrent_path, "wb") as f: f.write(libtorrent.bencode(torrent_file.generate())) log.debug("Torrent file wrote to %s", torrent_path) return torrent_path
def actionAddTorrent(self, to, torrentIdentifier): if not self.hasSitePermission(self.site.address): return self.response(to, {"error": "Forbidden"}) save_path = './data/' + self.site.address + '/downloads/' try: e = libtorrent.bdecode(base64.b64decode(torrentIdentifier)) info = libtorrent.torrent_info(e) params = { 'save_path': save_path, \ 'storage_mode': libtorrent.storage_mode_t.storage_mode_sparse, \ 'ti': info } except Exception as exception: try: # Test if a magnet params = libtorrent.parse_magnet_uri(torrentIdentifier) params.save_path = save_path # HACK: # Doesn't recognise sha1_hash python object when added to session if not converted to string # 'No registered converter was able to produce a C++ rvalue of type bytes from this Python object of type sha1_hash' #params['info_hash'] = params['info_hash'].to_string() except Exception as exception: params = { 'save_path': save_path, \ 'storage_mode': libtorrent.storage_mode_t.storage_mode_sparse, \ 'info_hash': torrentIdentifier.decode('hex') } try: session.async_add_torrent(params) except Exception as exception: self.response(to, {'error': str(exception)}) else: if type(params) is libtorrent.add_torrent_params: info_hash = params.info_hashes.get_best() else: if not info is None: info_hash = info.info_hashes().get_best() else: info_hash = params['info_hash'] self.response(to, {'info_hash': str(info_hash)})
def magnet_to_torrent(self, magnet_uri, destination_folder, timeout): import libtorrent params = libtorrent.parse_magnet_uri(magnet_uri) session = libtorrent.session() lt_version = [int(v) for v in libtorrent.version.split('.')] if lt_version > [0,16,13,0]: # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash params['info_hash'] = params['info_hash'].to_bytes() handle = libtorrent.add_magnet_uri(session, magnet_uri, params) log.debug('Acquiring torrent metadata for magnet %s', magnet_uri) timeout_value = timeout while not handle.has_metadata(): time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: raise plugin.PluginError('Timed out after {} seconds trying to magnetize'.format(timeout)) log.debug('Metadata acquired') torrent_info = handle.get_torrent_info() torrent_file = libtorrent.create_torrent(torrent_info) torrent_path = pathscrub(os.path.join(destination_folder, torrent_info.name() + ".torrent")) with open(torrent_path, "wb") as f: f.write(libtorrent.bencode(torrent_file.generate())) log.debug('Torrent file wrote to %s', torrent_path) return torrent_path
def api_upload(magnet_url_or_hash=None): """ <h5>Description:</h5> <p> Adds a new torrent to the system and retrieves its data if its not already in the system. Note: If the torrent is added via a SHA-1 info_hash, a magnet link is constructed and we attempt to retrieve the torrent via DHT </p> <h5>Parameters:</h5> <ul> <li><strong>magnet_url_or_hash</strong> - A magnet link, a HTTP url to the .torrent file, or a SHA-1 info_hash. Can also be the base64 encoding of a binary .torrent file</li> </ul> <h5>Returns:</h5> <p> If successful, a data structure like so: <pre> { "data": { "url": "(the contents of the url_magnet_or_hash parameter)", "added": true, "hash": "a4b93e50187930206dcf1351bceceb29f5a119ca" }, "success": true } </pre> If an error occured, the following data structure will be returned: <pre> { "message": "Cannot recognise this url: foo", "success": false } </pre> </p> <h5>Examples:</h5> <p> Add based on a magnet link:<br /> <pre>/api/upload/magnet%3A%3Fxt%3Durn%3Abtih%3Addceab34ac388ca56b0cdbc6eb726ca1844233c5%26dn%3DPioneer%2BOne%2BS01E03%2BXvid-VODO%26tr%3Dudp%253A%252F%252Ftracker.openbittorrent.com%253A80%26tr%3Dudp%253A%252F%252Ftracker.publicbt.com%253A80%26tr%3Dudp%253A%252F%252Ftracker.istole.it%253A6969%26tr%3Dudp%253A%252F%252Ftracker.ccc.de%253A80</pre> Add based on a HTTP url:<br /> <pre>/api/upload/http%3A%2F%2Ftorrents.thepiratebay.se%2F6753216%2FPioneer_One_S01E03_Xvid-VODO.6753216.TPB.torrent</pre> Add based on a SHA-1 info_hash:<br /> <pre>/api/upload/ddceab34ac388ca56b0cdbc6eb726ca1844233c5</pre> </p> """ url = magnet_url_or_hash if magnet_url_or_hash else request.params.get( "magnet_url_or_hash") if not url: return api_error("No magnet, url or hash supplied") item = url.strip() info_hash = "" try: if is_hash(item): info_hash = item if not is_in_database(item): add_to_database(item) elif is_base64(item): decoded = base64.b64decode(item) info = lt.torrent_info(lt.bdecode(decoded)) info_hash = "%s" % info.info_hash() if not is_in_database(info_hash): add_to_database(info_hash, fetch_metadata=False) thread.start_new_thread(add_from_torrent_info, (info, torrent_data)) elif is_magnet(item): params = lt.parse_magnet_uri(item) info_hash = str(params["info_hash"]) if not info_hash.replace("0", ""): raise RuntimeError( "The hash was all 0's, did you urlencode the magnet link properly?" ) else: if not is_in_database(info_hash): add_to_database(info_hash, item) elif is_url(item): item = urllib.unquote_plus(item) logger.debug("Fetching %s" % item) download_to = tempfile.mkstemp(suffix=".torrent")[1] urllib.urlretrieve(item, download_to) handle = open(download_to, "rb") torrent_data = handle.read() info = lt.torrent_info(lt.bdecode(torrent_data)) handle.close() os.remove(download_to) info_hash = "%s" % info.info_hash() if not is_in_database(info_hash): add_to_database(info_hash, fetch_metadata=False) thread.start_new_thread(add_from_torrent_info, (info, torrent_data)) else: raise RuntimeError("Cannot recognise this url: %s" % item) except (RuntimeError, IOError) as e: return api_error(str(e)) return api_success({"url": item, "hash": info_hash, "added": True})
def get_file(fn): # request_uri = fn.split("/",1)[-1] fsize = None exists = False mime_type = '' request_uri = fn.replace(STATIC_FILES_DIR + "/", "") print request_uri if request_uri.startswith(atp["static_path"]): torrent = atp chosen_file = "/".join(request_uri.split("/")[2:]) print "chosen file:" + chosen_file url = "magnet:?xt=urn:btih:" + request_uri.split("/")[1] info_hash = libtorrent.parse_magnet_uri(url)["info_hash"] handle = torrent_session.find_torrent(info_hash) # print str(info_hash)+".resume", os.listdir("resume") if handle.is_valid(): print "Magnet already in the session" torrent_handle = handle # elif str(info_hash)+".resume" in os.listdir("resume"): # torrent["resume_data"] = io.open("resume/"+str(info_hash)+".resume", "rb").read() # torrent_handle = torrent_session.add_torrent(torrent) else: print " start new torrent" torrent["url"] = url torrent["save_path"] = os.path.join(TORRENTS_DIR, str(info_hash)) # torrent["paused"]=True torrent_handle = torrent_session.add_torrent(torrent) while not torrent_handle.has_metadata(): sleep(0.5) info = torrent_handle.get_torrent_info() torrent_files = info.files() # torrent_handle.auto_managed(False) if chosen_file is not None: for i, file_info in enumerate(torrent_files): print "path:", file_info.path if chosen_file == file_info.path: torrent_handle.file_priority(i, 1) torrent_file = file_info file_index = i else: torrent_handle.file_priority(i, 0) torrent_handle.map_piece = lambda offset: info.map_file( file_index, offset, 1) path = os.path.join(TORRENTS_DIR, torrent_file.path) first_byte = torrent_file.offset last_byte = torrent_file.offset + torrent_file.size torrent_handle.set_sequential_download(True) first_piece = torrent_handle.map_piece(first_byte).piece last_piece = torrent_handle.map_piece(last_byte).piece num_pieces = info.num_pieces() future_pieces = int((last_piece - first_piece) * 0.01) print "offset", torrent_file.offset, "piece", first_piece, "total", num_pieces piece_priorities = first_piece * [0] + (num_pieces - first_piece) * [1] piece_priorities = piece_priorities[:num_pieces] # piece_priorities=first_piece*[0]+future_pieces*[7]+more_pieces*[1]+(num_pieces-first_piece-future_pieces-more_pieces)*[0] torrent_handle.prioritize_pieces(piece_priorities) # torrent_handle.prioritize_pieces(num_pieces*[0]) # torrent_handle.piece_priority(first_piece,7) torrent_handle.piece_priority(last_piece, 7) torrent_handle.piece_priority(last_piece - 1, 7) # torrent_handle.num_pieces=info.num_pieces() piece = first_piece waiting = True while waiting: sleep(1) # if torrent_handle.have_piece(first_piece) and torrent_handle.have_piece(last_piece): # waiting =False status = torrent_handle.status() pieces = status.pieces print pieces[piece:piece + future_pieces], last_piece, pieces[ last_piece - 1], status.progress, status.download_rate, status.state if pieces[piece:piece + future_pieces] == future_pieces * [True] and pieces[ last_piece - 1]: waiting = False print "first and last piece received" # torrent_handle.prioritize_pieces(num_pieces*[1]) else: torrent_handle = None try: fsize = os.path.getsize(fn) exists = True type, encoding = mimetypes.guess_type(request_uri) if type: mime_type = type except: pass return File(request_uri, fn, fsize, exists, mime_type, torrent_handle)
def main_torrent_descr(options): main_default(options) sett = { 'enable_lsd': True, 'enable_dht': True, 'enable_upnp': True, 'enable_natpmp': True, } torrent_session = libtorrent.session(sett) alert_mask = (libtorrent.alert.category_t.storage_notification | libtorrent.alert.category_t.status_notification) torrent_session.apply_settings({'alert_mask': alert_mask}) torrent_session.listen_on(6881, 6891) torrent_session.dht_nodes = [('router.bittorrent.com', 6881), ('router.utorrent.com', 6881), ('dht.transmissionbt.com', 6881), ('dht.libtorrent.org', 25401), ('dht.aelitis.com', 6881)] torrent_session.start_dht() torrent_session.start_lsd() torrent_session.add_extension('ut_metadata') torrent_session.add_extension('ut_pex_plugin') torrent_session.add_extension('smart_ban_plugin') torrent_descr = {"save_path": options["save-path"]} if "hash-file" in options: if options["hash-file"].startswith('magnet:?'): magnet = libtorrent.parse_magnet_uri(options["hash-file"]) e = str(magnet.info_hash) if len(e) == 40: info_hash = binascii.unhexlify(e) elif len(e) == 32: info_hash = base64.b32decode(e) else: raise Exception("Unable to parse infohash") trackers = magnet.trackers torrent_handle = torrent_session.add_torrent({ 'info_hashes': info_hash, 'trackers': trackers, "save_path": options["save-path"] }) dots = 0 while not torrent_handle.has_metadata(): dots += 1 sys.stdout.write('.') sys.stdout.flush() time.sleep(1) if (dots): sys.stdout.write('\n') torrent_info = torrent_handle.get_torrent_info() else: torrent_info = libtorrent.torrent_info(options["hash-file"]) torrent_descr["ti"] = torrent_info torrent_handle = torrent_session.add_torrent(torrent_descr) piece_par_ref0 = reference() piece_server0 = piece_server() piece_server0.torrent_handle = torrent_handle piece_server0.torrent_info = torrent_info piece_server0.init() alert_client0 = alert_client() alert_client0.torrent_session = torrent_session alert_client0.torrent_handle = torrent_handle alert_client0.piece_server = piece_server0 alert_client0.start() r = torrent_read_bt2p() r.torrent_handle = torrent_handle r.torrent_info = torrent_info #r.init() http_server = http_server_bt2p((options["domain-name"], options["port"]), http_responder_bt2p) http_server.daemon_threads = True http_server.torrent = r http_server.piece_server = piece_server0 http_responder_bt2p.torrent_session = torrent_session http_responder_bt2p.torrent_handle = torrent_handle http_responder_bt2p.delete_files = options["delete-files"] http_responder_bt2p.http_server = http_server try: http_server.serve_forever() except KeyboardInterrupt: print("An exception occurred")
def magnet_to_torrent(self, magnet_uri, destination_folder, timeout, num_try, use_dht, http_proxy): import libtorrent as lt # parameters params = lt.parse_magnet_uri(magnet_uri) # prevent downloading # https://stackoverflow.com/q/45680113 if isinstance(params, dict): params['flags'] |= lt.add_torrent_params_flags_t.flag_upload_mode else: params.flags |= lt.add_torrent_params_flags_t.flag_upload_mode lt_version = [int(v) for v in lt.version.split('.')] if [0, 16, 13, 0] < lt_version < [1, 1, 3, 0]: # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash if isinstance(params, dict): params['info_hash'] = params['info_hash'].to_bytes() else: params.info_hash = params.info_hash.to_bytes() # add_trackers - currently always append try: if isinstance(params, dict): params['trackers'] += self.trackers else: params.trackers += self.trackers except Exception as e: logger.debug('Failed to add trackers: {}', str(e)) # session from setting pack settings = { # basics # 'user_agent': 'libtorrent/' + lt.__version__, 'listen_interfaces': '0.0.0.0:6881', # dht 'enable_dht': use_dht, 'use_dht_as_fallback': True, 'dht_bootstrap_nodes': 'router.bittorrent.com:6881,dht.transmissionbt.com:6881,router.utorrent.com:6881,127.0.0.1:6881', 'enable_lsd': False, 'enable_upnp': True, 'enable_natpmp': True, 'announce_to_all_tiers': True, 'announce_to_all_trackers': True, 'aio_threads': 4*2, 'checking_mem_usage': 1024*2, } if http_proxy: # TODO: TEST http_proxy proxy_url = urlparse(http_proxy) logger.debug(proxy_url) settings.update({ 'proxy_username': proxy_url.username, 'proxy_password': proxy_url.password, 'proxy_hostname': proxy_url.hostname, 'proxy_port': proxy_url.port, 'proxy_type': lt.proxy_type_t.http_pw if proxy_url.username and proxy_url.password else lt.proxy_type_t.http, 'force_proxy': True, 'anonymous_mode': True, }) session = lt.session(settings) # session.add_extension('ut_metadata') # session.add_extension('ut_pex') # session.add_extension('metadata_transfer') # handle handle = session.add_torrent(params) if use_dht: handle.force_dht_announce() logger.debug('Acquiring torrent metadata for magnet {}', magnet_uri) max_try = max(num_try, 1) for tryid in range(max_try): timeout_value = timeout logger.debug('Trying to get metadata ... {}/{}'.format(tryid+1, max_try)) while not handle.has_metadata(): time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: break if handle.has_metadata(): lt_info = handle.get_torrent_info() logger.debug('Metadata acquired after {}*{}+{:.1f} seconds', tryid, timeout, timeout - timeout_value) break else: if tryid+1 == max_try: session.remove_torrent(handle, True) raise plugin.PluginError( 'Timed out after {}*{} seconds'.format(max_try, timeout) ) # create torrent object torrent = lt.create_torrent(lt_info) torrent.set_creator('libtorrent v{}'.format(lt.version)) # signature torrent_dict = torrent.generate() torrent_info = self.convert_torrent_info(lt_info) torrent_info.update({ 'trackers': params['trackers'] if isinstance(params, dict) else params.trackers, 'creation_date': datetime.fromtimestamp(torrent_dict[b'creation date']).isoformat(), }) # start scraping timeout_value = timeout logger.debug('Trying to get peerinfo ... ') while handle.status(0).num_complete < 0: time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: break if handle.status(0).num_complete >= 0: torrent_status = handle.status(0) logger.debug('Peerinfo acquired after {:.1f} seconds', timeout - timeout_value) torrent_info.update({ 'seeders': torrent_status.num_complete, 'peers': torrent_status.num_incomplete, }) else: raise plugin.PluginError('Timed out after {} seconds'.format(timeout)) session.remove_torrent(handle, True) torrent_path = pathscrub( os.path.join(destination_folder, lt_info.name() + ".torrent") ) with open(torrent_path, "wb") as f: f.write(lt.bencode(torrent_dict)) logger.debug('Torrent file wrote to {}', torrent_path) return torrent_path, torrent_info
def magnet_to_torrent(self, magnet_uri, destination_folder, timeout, num_try): import libtorrent # parameters params = libtorrent.parse_magnet_uri(magnet_uri) # prevent downloading # https://stackoverflow.com/q/45680113 params.flags |= libtorrent.add_torrent_params_flags_t.flag_upload_mode lt_version = [int(v) for v in libtorrent.version.split('.')] if [0, 16, 13, 0] < lt_version < [1, 1, 3, 0]: # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash params.info_hash = params.info_hash.to_bytes() # add_trackers if len(params.trackers) == 0: try: import random params.trackers = random.sample(self.trackers, 5) except Exception as e: logger.debug('Failed to add trackers: {}', str(e)) # session session = libtorrent.session() session.listen_on(6881, 6891) session.add_extension('ut_metadata') session.add_extension('ut_pex') session.add_extension('metadata_transfer') session.add_dht_router('router.utorrent.com', 6881) session.add_dht_router('router.bittorrent.com', 6881) session.add_dht_router("dht.transmissionbt.com", 6881) session.add_dht_router('127.0.0.1', 6881) session.start_dht() # handle handle = session.add_torrent(params) handle.force_dht_announce() logger.debug('Acquiring torrent metadata for magnet {}', magnet_uri) for tryid in range(max(num_try, 1)): timeout_value = timeout while not handle.has_metadata(): time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: logger.debug( 'Failed to get metadata on trial: {}/{}'.format( tryid + 1, num_try)) break if handle.has_metadata(): logger.debug( 'Metadata acquired after {} seconds on trial {}'.format( timeout - timeout_value, tryid + 1)) break else: if tryid + 1 == max(num_try, 1): session.remove_torrent(handle, True) raise plugin.PluginError( 'Timed out after {}x{} seconds trying to magnetize'. format(timeout, num_try)) torrent_info = handle.get_torrent_info() torrent_file = libtorrent.create_torrent(torrent_info) torrent_path = pathscrub( os.path.join(destination_folder, torrent_info.name() + ".torrent")) with open(torrent_path, "wb") as f: f.write(libtorrent.bencode(torrent_file.generate())) logger.debug('Torrent file wrote to {}', torrent_path) return torrent_path
def magnet2torrent(magnet): tempdir = tempfile.mkdtemp() ses = lt.session() torrent_data = {} def clean_up_before_abort(abort_message): print(abort_message) ses.pause() print("Cleanup dir " + tempdir) shutil.rmtree(tempdir) params = { 'save_path': tempdir, 'storage_mode': lt.storage_mode_t(2), 'paused': False, 'auto_managed': True, 'duplicate_is_error': True } magnet_info = lt.parse_magnet_uri(magnet) torrent_data['trackers'] = magnet_info['trackers'] torrent_data['info_hash'] = magnet_info['info_hash'] torrent_name = magnet_info['name'] handle = lt.add_magnet_uri(ses, magnet, params) try: print("{0}: ".format(torrent_name)) print("Downloading Metadata (this may take a while)") time_spent_converting = 0 while (not handle.has_metadata()): if time_spent_converting >= TORRENT_CREATE_TIMEOUT: clean_up_before_abort( "Failed to convert magent link -- aborting") return None sleep(1) time_spent_converting += 1 torinfo = handle.get_torrent_info() info_list = [ 'name', 'total_size', 'piece_length', 'num_pieces', 'num_files', 'metadata_size' ] for info_name in info_list: torrent_data[info_name] = getattr(torinfo, info_name)() print("Done downloading meta data") print("Starting to download torrent ...") handle.set_upload_limit(0) #DO NOT UPLOAD ANYTHING peer_info_list = {} def update_ip_results(peer_list): for peer in peer_list: if peer.ip in peer_info_list: peer_in_hash = peer_info_list[peer.ip] peer_in_hash['up_speed'] = max(peer_in_hash['up_speed'], peer.up_speed) peer_in_hash['down_speed'] = max( peer_in_hash['down_speed'], peer.down_speed) else: peer_info_list[peer.ip] = { 'up_speed': peer.up_speed, 'down_speed': peer.down_speed } counter = 0 while (not handle.is_seed() and counter < TORRENT_DONWLOAD_LOOPS): print("counter: {0}".format(counter)) counter += 1 peer_list = handle.get_peer_info() update_ip_results(peer_list) if len(peer_info_list) > NUMBER_OF_PEERS_INFO: break sleep(5) torrent_data['peer_info'] = [{ 'ip': key, 'down_speed': value['down_speed'], 'up_speed': value['up_speed'] } for key, value in peer_info_list.iteritems()] except KeyboardInterrupt: clean_up_before_abort('Keyboard Interrupt Triggered') return print("Downloading stopped as peer data gathered ...") print("\nTORRENT INFO: {0} \n".format(torrent_data)) print("Done info gathered ...\n\n") ses.pause() ses.remove_torrent(handle) shutil.rmtree(tempdir) return torrent_data
import libtorrent as lt import time import sys import base64 import binascii ses = lt.session() ses.listen_on(6881, 6891) magnet = lt.parse_magnet_uri(sys.argv[1]) e = str(magnet.info_hash) if len(e) == 40: info_hash = binascii.unhexlify(e) elif len(e) == 32: info_hash = base64.b32decode(e) else: raise Exception("Unable to parse infohash") trackers = magnet.trackers h = ses.add_torrent({'info_hash': info_hash, 'trackers': trackers}) dots=0 while not h.has_metadata(): dots += 1 sys.stdout.write('.') sys.stdout.flush() time.sleep(1) if (dots): sys.stdout.write('\n') ses.pause() tinf = h.get_torrent_info() f = open('/tmp/b2pgen' + '.torrent', 'wb') f.write(lt.bencode(
def parse_magnet_uri( self, magnet_uri, scrape=None, use_dht=None, timeout=None, trackers=None, no_cache=None, n_try=None, to_torrent=None, http_proxy=None, ): try: import libtorrent as lt except ImportError as _e: raise ImportError("libtorrent package required") from _e # default function arguments from db if scrape is None: scrape = ModelSetting.get_bool("scrape") if use_dht is None: use_dht = ModelSetting.get_bool("use_dht") if timeout is None: timeout = ModelSetting.get_int("timeout") if trackers is None: trackers = json.loads(ModelSetting.get("trackers")) if n_try is None: n_try = ModelSetting.get_int("n_try") if no_cache is None: no_cache = False if to_torrent is None: to_torrent = False if http_proxy is None: http_proxy = ModelSetting.get("http_proxy") # parameters params = lt.parse_magnet_uri(magnet_uri) # prevent downloading # https://stackoverflow.com/q/45680113 if isinstance(params, dict): params["flags"] |= lt.add_torrent_params_flags_t.flag_upload_mode else: params.flags |= lt.add_torrent_params_flags_t.flag_upload_mode lt_version = [int(v) for v in lt.version.split(".")] if [0, 16, 13, 0] < lt_version < [1, 1, 3, 0]: # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash if isinstance(params, dict): params["info_hash"] = params["info_hash"].to_bytes() else: params.info_hash = params.info_hash.to_bytes() # 캐시에 있으면... info_hash_from_magnet = str(params["info_hash"] if isinstance(params, dict) else params.info_hash) self.cache_init() if (not no_cache) and (info_hash_from_magnet in self.torrent_cache): return self.torrent_cache[info_hash_from_magnet]["info"] # add trackers if isinstance(params, dict): if len(params["trackers"]) == 0: params["trackers"] = trackers else: if len(params.trackers) == 0: params.trackers = trackers # session settings = { # basics # 'user_agent': 'libtorrent/' + lt.__version__, "listen_interfaces": "0.0.0.0:6881", # dht "enable_dht": use_dht, "use_dht_as_fallback": True, "dht_bootstrap_nodes": "router.bittorrent.com:6881,dht.transmissionbt.com:6881,router.utorrent.com:6881,127.0.0.1:6881", "enable_lsd": False, "enable_upnp": True, "enable_natpmp": True, "announce_to_all_tiers": True, "announce_to_all_trackers": True, "aio_threads": 4 * 2, "checking_mem_usage": 1024 * 2, } if http_proxy: proxy_url = urlparse(http_proxy) settings.update( { "proxy_username": proxy_url.username, "proxy_password": proxy_url.password, "proxy_hostname": proxy_url.hostname, "proxy_port": proxy_url.port, "proxy_type": lt.proxy_type_t.http_pw if proxy_url.username and proxy_url.password else lt.proxy_type_t.http, "force_proxy": True, "anonymous_mode": True, } ) session = lt.session(settings) session.add_extension("ut_metadata") session.add_extension("ut_pex") session.add_extension("metadata_transfer") # handle handle = session.add_torrent(params) if use_dht: handle.force_dht_announce() max_try = max(n_try, 1) for tryid in range(max_try): timeout_value = timeout logger.debug("Trying to get metadata... %d/%d", tryid + 1, max_try) while not handle.has_metadata(): time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: break if handle.has_metadata(): lt_info = handle.get_torrent_info() logger.debug( "Successfully got metadata after %d*%d+%.2f seconds", tryid, timeout, timeout - timeout_value ) time_metadata = tryid * timeout + (timeout - timeout_value) break if tryid + 1 == max_try: session.remove_torrent(handle, True) raise Exception(f"Timed out after {max_try}*{timeout} seconds") # create torrent object and generate file stream torrent = lt.create_torrent(lt_info) torrent.set_creator(f"libtorrent v{lt.version}") # signature torrent_dict = torrent.generate() torrent_info = self.convert_torrent_info(lt_info) torrent_info.update( { "trackers": params.trackers if not isinstance(params, dict) else params["trackers"], "creation_date": datetime.fromtimestamp(torrent_dict[b"creation date"]).isoformat(), "time": {"total": time_metadata, "metadata": time_metadata}, } ) if scrape: # start scraping for tryid in range(max_try): timeout_value = timeout logger.debug("Trying to get peerinfo... %d/%d", tryid + 1, max_try) while handle.status(0).num_complete < 0: time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: break if handle.status(0).num_complete >= 0: torrent_status = handle.status(0) logger.debug( "Successfully got peerinfo after %d*%d+%.2f seconds", tryid, timeout, timeout - timeout_value ) time_scrape = tryid * timeout + (timeout - timeout_value) torrent_info.update( { "seeders": torrent_status.num_complete, "peers": torrent_status.num_incomplete, } ) torrent_info["time"]["scrape"] = time_scrape torrent_info["time"]["total"] = torrent_info["time"]["metadata"] + torrent_info["time"]["scrape"] break if tryid + 1 == max_try: logger.error("Timed out after %d*%d seconds", max_try, timeout) session.remove_torrent(handle, True) # caching for later use self.torrent_cache[torrent_info["info_hash"]] = { "info": torrent_info, } if to_torrent: return lt.bencode(torrent_dict), pathscrub(lt_info.name(), os="windows", filename=True) return torrent_info
def handle_request(clientsock, addr): data = clientsock.recv(RECV_BUFSIZ) #Log('Request received: %s' % data) request = parse_http_request(data) path = STATIC_FILES_DIR + clean_path(request.request_uri) request_uri = request.request_uri[1:] if request_uri.startswith("_omx"): req = request_uri.split("/") cmd = req[1] if cmd == "play": omxplayer.reset_tv() link = ("/").join(req[2:]) path = STATIC_FILES_DIR + "/" + clean_path(req[2]) print path if os.path.isdir(path): link = "http://localhost/" + link playing_video = omxplayer.omxplayer(str(link)) elif link.split(".").pop() in omxplayer.FORMATS: playing_video = omxplayer.omxplayer(str(link)) elif link.split(".").pop() in omxplayer.FBI_FORMATS: shown_image = omxplayer.image(str(link)) elif link.split(".").pop() in ["pdf"]: shown_pdf = omxplayer.pdf(str(link)) else: link = omxplayer.ytdl(link) playing_video = omxplayer.omxplayer(str(link)) response = HttpResponse(protocol=request.protocol, status_code=200) response.write_to(clientsock) clientsock.close() # if request_uri.startswith("magnet") or request_uri.endswith(".torrent") or request_uri.startswith(atp["static_path"]): if request_uri.startswith("magnet") or request_uri.endswith(".torrent"): chosen_file = None torrent = atp print "req uri:" + request_uri if request_uri.startswith("magnet"): info_hash = libtorrent.parse_magnet_uri(request_uri)["info_hash"] elif request_uri.startswith(atp["static_path"]): chosen_file = urllib.unquote("/".join(request_uri.split("/")[2:])) print "chosen file:" + chosen_file request_uri = "magnet:?xt=urn:btih:" + request_uri.split("/")[1] info_hash = libtorrent.parse_magnet_uri(request_uri)["info_hash"] elif request_uri.endswith(".torrent"): #get info hash pass handle = torrent_session.find_torrent(info_hash) if handle.is_valid(): print "Magnet already in the session" torrent_handle = handle elif (str(info_hash) + ".resume") in os.listdir("resume"): torrent["resume_data"] = io.open( "resume/" + str(info_hash) + ".resume", "rb").read() torrent_handle = torrent_session.add_torrent(torrent) else: print " start new torrrent" torrent["url"] = request_uri # torrent["paused"]=True torrent["save_path"] = os.path.join(TORRENTS_DIR, str(info_hash)) torrent_handle = torrent_session.add_torrent(torrent) print "getting metadata" while not torrent_handle.has_metadata(): sleep(1) print "getting info" info = torrent_handle.get_torrent_info() torrent_files = info.files() torrent_handle.auto_managed(False) if chosen_file is not None: for i, file_info in enumerate(torrent_files): print "path:", file_info.path if chosen_file == file_info.path: torrent_handle.file_priority(i, 1) file_index = i else: torrent_handle.file_priority(i, 0) file = get_torrent_file(torrent_handle, file_index) if file.exists and request.is_range_requested(): response = HttpResponse(protocol=request.protocol, status_code=206, range=request.get_range()) response.file = file elif file.exists: response = HttpResponse(protocol=request.protocol, status_code=200) response.file = file Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() info = torrent_handle.get_torrent_info() name = info.name() # f = str() # f += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">' # f += "<html>\n<title>Directory listing for %s</title>\n" % name # f +="<body>\n<h2>Directory listing for %s</h2>\n" % name # f += "<hr>\n<ul>\n" f = {} for i, file_info in enumerate(torrent_files): f[i] = { "link": "/" + os.path.join(atp["static_path"], str(info_hash), file_info.path), "size": file_info.size, "path": file_info.path } # f += '<li><a href="%s">%s</a><h6>%s</h6></li>\n' % (os.path.join(atp["static_path"],str(info_hash),file_info.path), file_info.path,file_info.size) # f += "</ul>\n<hr>\n</body>\n</html>\n" f = json.dumps(f) response = HttpResponse(protocol=request.protocol, status_code=200) response.headers['Content-type'] = 'application/json' response.headers['Content-Length'] = len(f) # response.headers['Accept-Ranges'] = 'bytes' response.content = f Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() return None # h.set_sequential_download(True) # while h.status().progress < 0.01: # sleep(1) # h.file_index=max_i # h.offset=max_offset # check if path is dir (copy from the SimpleHttpServer) path = STATIC_FILES_DIR + clean_path(request.request_uri) if os.path.isdir(path): print path if not path.endswith('/'): # redirect browser - doing basically what apache does response = HttpResponse(protocol=request.protocol, status_code=301) response.headers['Location'] = path + "/" Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() return None for index in "index.html", "index.htm": index = os.path.join(path, index) if os.path.exists(index): path = index break else: # quick and dirty but it works :P (also copy from SimpleHttpServer) try: list = os.listdir(path) except os.error: response = HttpResponse(protocol=request.protocol, status_code=404) response.headers['Content-type'] = 'text/plain' response.content = 'No permission to list directory' Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() return None list.sort(key=lambda a: a.lower()) f = str() displaypath = cgi.escape(urllib.unquote(request.request_uri)) # f += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">' # f += "<html>\n<title>Directory listing for %s</title>\n" % displaypath # f +="<body>\n<h2>Directory listing for %s</h2>\n" % displaypath f += "<hr>\n<ul>\n" for name in list: fullname = os.path.join(path, name) displayname = linkname = name # Append / for directories or @ for symbolic links if os.path.isdir(fullname): displayname = name + "/" linkname = name + "/" if os.path.islink(fullname): displayname = name + "/" # "@" # Note: a link to a directory displays with @ and links with / f += '<li><a href="%s">%s</a>\n' % (urllib.quote(linkname), cgi.escape(displayname)) f += "</ul>\n<hr>\n</body>\n</html>\n" response = HttpResponse(protocol=request.protocol, status_code=200) response.headers['Content-type'] = 'text/html' response.headers['Content-Length'] = len(f) response.headers['Accept-Ranges'] = 'bytes' response.content = f Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() return None print urllib.unquote(request.request_uri)[1:] file = get_file(path) if file.exists and request.is_range_requested(): response = HttpResponse(protocol=request.protocol, status_code=206, range=request.get_range()) response.headers["Content-Type"] = file.mime_type response.headers["Connection"] = "Keep-Alive" response.file = file elif file.exists: response = HttpResponse(protocol=request.protocol, status_code=200) response.file = file else: response = HttpResponse(protocol=request.protocol, status_code=404) response.headers['Content-type'] = 'text/plain' response.content = 'This file does not exist!' Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close()
def api_upload(magnet_url_or_hash=None): """ <h5>Description:</h5> <p> Adds a new torrent to the system and retrieves its data if its not already in the system. Note: If the torrent is added via a SHA-1 info_hash, a magnet link is constructed and we attempt to retrieve the torrent via DHT </p> <h5>Parameters:</h5> <ul> <li><strong>magnet_url_or_hash</strong> - A magnet link, a HTTP url to the .torrent file, or a SHA-1 info_hash. Can also be the base64 encoding of a binary .torrent file</li> </ul> <h5>Returns:</h5> <p> If successful, a data structure like so: <pre> { "data": { "url": "(the contents of the url_magnet_or_hash parameter)", "added": true, "hash": "a4b93e50187930206dcf1351bceceb29f5a119ca" }, "success": true } </pre> If an error occured, the following data structure will be returned: <pre> { "message": "Cannot recognise this url: foo", "success": false } </pre> </p> <h5>Examples:</h5> <p> Add based on a magnet link:<br /> <pre>/api/upload/magnet%3A%3Fxt%3Durn%3Abtih%3Addceab34ac388ca56b0cdbc6eb726ca1844233c5%26dn%3DPioneer%2BOne%2BS01E03%2BXvid-VODO%26tr%3Dudp%253A%252F%252Ftracker.openbittorrent.com%253A80%26tr%3Dudp%253A%252F%252Ftracker.publicbt.com%253A80%26tr%3Dudp%253A%252F%252Ftracker.istole.it%253A6969%26tr%3Dudp%253A%252F%252Ftracker.ccc.de%253A80</pre> Add based on a HTTP url:<br /> <pre>/api/upload/http%3A%2F%2Ftorrents.thepiratebay.se%2F6753216%2FPioneer_One_S01E03_Xvid-VODO.6753216.TPB.torrent</pre> Add based on a SHA-1 info_hash:<br /> <pre>/api/upload/ddceab34ac388ca56b0cdbc6eb726ca1844233c5</pre> </p> """ url = magnet_url_or_hash if magnet_url_or_hash else request.params.get("magnet_url_or_hash") if not url: return api_error("No magnet, url or hash supplied") item = url.strip() info_hash = ""; try : if is_hash(item): info_hash = item; if not is_in_database(item): add_to_database(item) elif is_base64(item): decoded = base64.b64decode(item) info = lt.torrent_info(lt.bdecode(decoded)) info_hash = "%s" % info.info_hash() if not is_in_database(info_hash): add_to_database(info_hash, fetch_metadata=False) thread.start_new_thread(add_from_torrent_info, (info, torrent_data)) elif is_magnet(item): params = lt.parse_magnet_uri(item) info_hash = str(params["info_hash"]) if not info_hash.replace("0", ""): raise RuntimeError("The hash was all 0's, did you urlencode the magnet link properly?") else: if not is_in_database(info_hash): add_to_database(info_hash, item) elif is_url(item): item = urllib.unquote_plus(item) logger.debug("Fetching %s" % item) download_to = tempfile.mkstemp(suffix=".torrent")[1] urllib.urlretrieve(item, download_to) handle = open(download_to, "rb"); torrent_data = handle.read() info = lt.torrent_info(lt.bdecode(torrent_data)) handle.close() os.remove(download_to) info_hash = "%s" % info.info_hash() if not is_in_database(info_hash): add_to_database(info_hash, fetch_metadata=False) thread.start_new_thread(add_from_torrent_info, (info, torrent_data)) else: raise RuntimeError("Cannot recognise this url: %s" % item) except (RuntimeError, IOError) as e: return api_error(str(e)) return api_success({ "url" : item, "hash" : info_hash, "added" : True})
def get_file(fn): # request_uri = fn.split("/",1)[-1] fsize = None exists = False mime_type = '' request_uri=fn.replace(STATIC_FILES_DIR+"/","") print request_uri if request_uri.startswith(atp["static_path"]): torrent=atp chosen_file="/".join(request_uri.split("/")[2:]) print "chosen file:"+chosen_file url="magnet:?xt=urn:btih:"+request_uri.split("/")[1] info_hash=libtorrent.parse_magnet_uri(url)["info_hash"] handle=torrent_session.find_torrent(info_hash) # print str(info_hash)+".resume", os.listdir("resume") if handle.is_valid(): print "Magnet already in the session" torrent_handle=handle # elif str(info_hash)+".resume" in os.listdir("resume"): # torrent["resume_data"] = io.open("resume/"+str(info_hash)+".resume", "rb").read() # torrent_handle = torrent_session.add_torrent(torrent) else: print " start new torrent" torrent["url"]=url torrent["save_path"]=os.path.join(TORRENTS_DIR,str(info_hash)) # torrent["paused"]=True torrent_handle = torrent_session.add_torrent(torrent) while not torrent_handle.has_metadata(): sleep(0.5) info=torrent_handle.get_torrent_info() torrent_files=info.files() # torrent_handle.auto_managed(False) if chosen_file is not None: for i,file_info in enumerate(torrent_files): print "path:",file_info.path if chosen_file == file_info.path: torrent_handle.file_priority(i,1) torrent_file=file_info file_index=i else: torrent_handle.file_priority(i,0) torrent_handle.map_piece = lambda offset: info.map_file(file_index, offset, 1) path=os.path.join(TORRENTS_DIR,torrent_file.path) first_byte=torrent_file.offset last_byte=torrent_file.offset+torrent_file.size torrent_handle.set_sequential_download(True) first_piece=torrent_handle.map_piece(first_byte).piece last_piece=torrent_handle.map_piece(last_byte).piece num_pieces=info.num_pieces() future_pieces=int((last_piece-first_piece)*0.01) print "offset",torrent_file.offset,"piece",first_piece,"total", num_pieces piece_priorities=first_piece*[0]+(num_pieces-first_piece)*[1] piece_priorities=piece_priorities[:num_pieces] # piece_priorities=first_piece*[0]+future_pieces*[7]+more_pieces*[1]+(num_pieces-first_piece-future_pieces-more_pieces)*[0] torrent_handle.prioritize_pieces(piece_priorities) # torrent_handle.prioritize_pieces(num_pieces*[0]) # torrent_handle.piece_priority(first_piece,7) torrent_handle.piece_priority(last_piece,7) torrent_handle.piece_priority(last_piece-1,7) # torrent_handle.num_pieces=info.num_pieces() piece=first_piece waiting=True while waiting: sleep(1) # if torrent_handle.have_piece(first_piece) and torrent_handle.have_piece(last_piece): # waiting =False status=torrent_handle.status() pieces=status.pieces print pieces[piece:piece+future_pieces],last_piece ,pieces[last_piece-1] , status.progress,status.download_rate,status.state if pieces[piece:piece+future_pieces] == future_pieces*[True] and pieces[last_piece-1]: waiting=False print "first and last piece received" # torrent_handle.prioritize_pieces(num_pieces*[1]) else: torrent_handle=None try: fsize = os.path.getsize(fn) exists = True type, encoding = mimetypes.guess_type(request_uri) if type: mime_type = type except: pass return File(request_uri, fn, fsize, exists, mime_type,torrent_handle)
def parse_magnet_uri(magnet_uri, scrape=False, use_dht=True, force_dht=False, timeout=10, trackers=None, no_cache=False, n_try=3): try: import libtorrent as lt except ImportError: raise ImportError('libtorrent package required') # parameters params = lt.parse_magnet_uri(magnet_uri) # prevent downloading # https://stackoverflow.com/q/45680113 if isinstance(params, dict): params['flags'] |= lt.add_torrent_params_flags_t.flag_upload_mode else: params.flags |= lt.add_torrent_params_flags_t.flag_upload_mode lt_version = [int(v) for v in lt.version.split('.')] if [0, 16, 13, 0] < lt_version < [1, 1, 3, 0]: # for some reason the info_hash needs to be bytes but it's a struct called sha1_hash if type({}) == type(params): params['info_hash'] = params['info_hash'].to_bytes() else: params.info_hash = params.info_hash.to_bytes() # 캐시에 있으면 ... info_hash_from_magnet = str(params['info_hash'] if type({}) == type(params) else params.info_hash) if (not no_cache) and (info_hash_from_magnet in Logic.torrent_cache): return Logic.torrent_cache[info_hash_from_magnet]['info'] # add trackers if type({}) == type(params): if len(params['trackers']) == 0: if trackers is None: trackers = json.loads(ModelSetting.get('trackers')) params['trackers'] = random.sample(trackers, 5) else: if len(params.trackers) == 0: if trackers is None: trackers = json.loads(ModelSetting.get('trackers')) params.trackers = random.sample(trackers, 5) # session session = lt.session() session.listen_on(6881, 6891) session.add_extension('ut_metadata') session.add_extension('ut_pex') session.add_extension('metadata_transfer') if use_dht: session.add_dht_router('router.utorrent.com', 6881) session.add_dht_router('router.bittorrent.com', 6881) session.add_dht_router("dht.transmissionbt.com", 6881) session.add_dht_router('127.0.0.1', 6881) session.start_dht() # handle handle = session.add_torrent(params) if force_dht: handle.force_dht_announce() for tryid in range(max(n_try, 1)): timeout_value = timeout while not handle.has_metadata(): time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: logger.debug( 'Failed to get metadata on trial: {}/{}'.format( tryid + 1, n_try)) break if handle.has_metadata(): lt_info = handle.get_torrent_info() logger.debug( 'Successfully get metadata after {} seconds on trial {}'. format(timeout - timeout_value, tryid + 1)) break else: if tryid + 1 == max(n_try, 1): session.remove_torrent(handle, True) raise Exception( 'Timed out after {}x{} seconds trying to get metainfo'. format(timeout, n_try)) # create torrent object and generate file stream torrent = lt.create_torrent(lt_info) torrent.set_creator('libtorrent v{}'.format(lt.version)) # signature torrent_dict = torrent.generate() torrent_info = Logic.convert_torrent_info(lt_info) torrent_info.update({ 'trackers': params.trackers if type({}) != type(params) else params['trackers'], 'creation_date': datetime.fromtimestamp(torrent_dict[b'creation date']).isoformat(), 'time': { 'total': timeout - timeout_value, 'metadata': timeout - timeout_value }, }) if scrape: # start scraping timeout_value = timeout while handle.status(0).num_complete < 0: time.sleep(0.1) timeout_value -= 0.1 if timeout_value <= 0: logger.error( 'Timed out after {} seconds trying to get peer info'. format(timeout)) if handle.status(0).num_complete >= 0: torrent_status = handle.status(0) torrent_info.update({ 'seeders': torrent_status.num_complete, 'peers': torrent_status.num_incomplete, }) torrent_info['time']['scrape'] = timeout - timeout_value torrent_info['time']['total'] = torrent_info['time'][ 'metadata'] + torrent_info['time']['scrape'] session.remove_torrent(handle, True) # caching for later use if Logic.torrent_cache is None: Logic.cache_init() Logic.torrent_cache[torrent_info['info_hash']] = { 'info': torrent_info, } return torrent_info
def test_parse_to_atp_error(self) -> None: with self.assertRaises(RuntimeError): lt.parse_magnet_uri("magnet:?")
def test_parse_to_atp(self) -> None: uri = f"magnet:?xt=urn:btih:{self.info_hash_sha1}" atp = lt.parse_magnet_uri(uri) self.assertEqual(str(atp.info_hash).lower(), self.info_hash_sha1)
def handle_request(clientsock, addr): data = clientsock.recv(RECV_BUFSIZ) #Log('Request received: %s' % data) request = parse_http_request(data) path = STATIC_FILES_DIR + clean_path(request.request_uri) request_uri=request.request_uri[1:] if request_uri.startswith("_omx"): req=request_uri.split("/") cmd=req[1] if cmd=="play": omxplayer.reset_tv() link=("/").join(req[2:]) path=STATIC_FILES_DIR + "/"+clean_path(req[2]) print path if os.path.isdir(path): link= "http://localhost/"+link playing_video=omxplayer.omxplayer(str(link)) elif link.split(".").pop() in omxplayer.FORMATS: playing_video=omxplayer.omxplayer(str(link)) elif link.split(".").pop() in omxplayer.FBI_FORMATS: shown_image= omxplayer.image(str(link)) elif link.split(".").pop() in ["pdf"]: shown_pdf= omxplayer.pdf(str(link)) else: link=omxplayer.ytdl(link) playing_video=omxplayer.omxplayer(str(link)) response = HttpResponse(protocol=request.protocol, status_code=200) response.write_to(clientsock) clientsock.close() # if request_uri.startswith("magnet") or request_uri.endswith(".torrent") or request_uri.startswith(atp["static_path"]): if request_uri.startswith("magnet") or request_uri.endswith(".torrent"): chosen_file=None torrent=atp print "req uri:"+request_uri if request_uri.startswith("magnet"): info_hash=libtorrent.parse_magnet_uri(request_uri)["info_hash"] elif request_uri.startswith(atp["static_path"]): chosen_file=urllib.unquote("/".join(request_uri.split("/")[2:])) print "chosen file:"+chosen_file request_uri="magnet:?xt=urn:btih:"+request_uri.split("/")[1] info_hash=libtorrent.parse_magnet_uri(request_uri)["info_hash"] elif request_uri.endswith(".torrent"): #get info hash pass handle=torrent_session.find_torrent(info_hash) if handle.is_valid(): print "Magnet already in the session" torrent_handle=handle elif (str(info_hash)+".resume") in os.listdir("resume"): torrent["resume_data"] = io.open("resume/"+str(info_hash)+".resume", "rb").read() torrent_handle = torrent_session.add_torrent(torrent) else: print " start new torrrent" torrent["url"]=request_uri # torrent["paused"]=True torrent["save_path"]=os.path.join(TORRENTS_DIR,str(info_hash)) torrent_handle = torrent_session.add_torrent(torrent) print "getting metadata" while not torrent_handle.has_metadata(): sleep(1) print "getting info" info=torrent_handle.get_torrent_info() torrent_files=info.files() torrent_handle.auto_managed(False) if chosen_file is not None: for i,file_info in enumerate(torrent_files): print "path:",file_info.path if chosen_file == file_info.path: torrent_handle.file_priority(i,1) file_index=i else: torrent_handle.file_priority(i,0) file = get_torrent_file(torrent_handle,file_index) if file.exists and request.is_range_requested(): response = HttpResponse(protocol=request.protocol, status_code=206, range=request.get_range()) response.file = file elif file.exists: response = HttpResponse(protocol=request.protocol, status_code=200) response.file = file Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() info=torrent_handle.get_torrent_info() name= info.name() # f = str() # f += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">' # f += "<html>\n<title>Directory listing for %s</title>\n" % name # f +="<body>\n<h2>Directory listing for %s</h2>\n" % name # f += "<hr>\n<ul>\n" f={} for i,file_info in enumerate(torrent_files): f[i]={"link":"/"+os.path.join(atp["static_path"],str(info_hash),file_info.path), "size":file_info.size, "path":file_info.path } # f += '<li><a href="%s">%s</a><h6>%s</h6></li>\n' % (os.path.join(atp["static_path"],str(info_hash),file_info.path), file_info.path,file_info.size) # f += "</ul>\n<hr>\n</body>\n</html>\n" f=json.dumps(f) response = HttpResponse(protocol=request.protocol, status_code=200) response.headers['Content-type'] = 'application/json' response.headers['Content-Length'] = len(f) # response.headers['Accept-Ranges'] = 'bytes' response.content = f Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() return None # h.set_sequential_download(True) # while h.status().progress < 0.01: # sleep(1) # h.file_index=max_i # h.offset=max_offset # check if path is dir (copy from the SimpleHttpServer) path=STATIC_FILES_DIR + clean_path(request.request_uri) if os.path.isdir(path): print path if not path.endswith('/'): # redirect browser - doing basically what apache does response = HttpResponse(protocol=request.protocol, status_code=301) response.headers['Location'] = path + "/" Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() return None for index in "index.html", "index.htm": index = os.path.join(path, index) if os.path.exists(index): path = index break else: # quick and dirty but it works :P (also copy from SimpleHttpServer) try: list = os.listdir(path) except os.error: response = HttpResponse(protocol=request.protocol, status_code=404) response.headers['Content-type'] = 'text/plain' response.content = 'No permission to list directory' Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() return None list.sort(key=lambda a: a.lower()) f = str() displaypath = cgi.escape(urllib.unquote(request.request_uri)) # f += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">' # f += "<html>\n<title>Directory listing for %s</title>\n" % displaypath # f +="<body>\n<h2>Directory listing for %s</h2>\n" % displaypath f += "<hr>\n<ul>\n" for name in list: fullname = os.path.join(path, name) displayname = linkname = name # Append / for directories or @ for symbolic links if os.path.isdir(fullname): displayname = name + "/" linkname = name + "/" if os.path.islink(fullname): displayname = name + "/" # "@" # Note: a link to a directory displays with @ and links with / f += '<li><a href="%s">%s</a>\n' % (urllib.quote(linkname), cgi.escape(displayname)) f += "</ul>\n<hr>\n</body>\n</html>\n" response = HttpResponse(protocol=request.protocol, status_code=200) response.headers['Content-type'] = 'text/html' response.headers['Content-Length'] = len(f) response.headers['Accept-Ranges'] = 'bytes' response.content = f Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close() return None print urllib.unquote(request.request_uri)[1:] file = get_file(path) if file.exists and request.is_range_requested(): response = HttpResponse(protocol=request.protocol, status_code=206, range=request.get_range()) response.headers["Content-Type"]=file.mime_type response.headers["Connection"]="Keep-Alive" response.file = file elif file.exists: response = HttpResponse(protocol=request.protocol, status_code=200) response.file = file else: response = HttpResponse(protocol=request.protocol, status_code=404) response.headers['Content-type'] = 'text/plain' response.content = 'This file does not exist!' Log('%s GET "%s" %s %s %s' % (addr[0], request.request_uri, request.protocol, request.get_range(), response.status_code)) response.write_to(clientsock) clientsock.close()