def __init__(self, filename): self.torrent = Torrent(filename) self.host = '0.0.0.0' self.port = 6886 # self.listener = self.create_listener() self.inputs = [] self.outputs = []
def get_torrents(self, view="main"): """Get list of all torrents in specified view @return: list of L{Torrent} instances @rtype: list @todo: add validity check for specified view """ self.torrents = [] methods = torrent.methods retriever_methods = [ m for m in methods if m.is_retriever() and m.is_available(self) ] m = rpc.Multicall(self) m.add("d.multicall", view, "d.get_hash=", *[method.rpc_call + "=" for method in retriever_methods]) results = m.call()[0] # only sent one call, only need first result for result in results: results_dict = {} # build results_dict for m, r in zip(retriever_methods, result[1:]): # result[0] is the info_hash results_dict[m.varname] = rpc.process_result(m, r) self.torrents.append( Torrent(self, info_hash=result[0], **results_dict)) self._manage_torrent_cache() return (self.torrents)
def parse(self): with open(self.path, 'rb') as f: torrent_file = bdecode(f) urls = [] if 'announce' in torrent_file: urls.append(torrent_file['announce']) if 'announce-list' in torrent_file: for tracker in torrent_file['announce-list']: urls.append(tracker[0]) info = torrent_file['info'] name = info['name'] piece_length = info['piece length'] pieces = info['pieces'] if 'length' in info: length = info['length'] # only exists for single-file torrents file_list = [File(length, [name], 0)] else: files = info['files'] file_list = [] offset = 0 for file in files: file_list.append(File(file['length'], file['path'], offset)) offset += file['length'] target = FileStructure(name, file_list) print("Torrent has %d pieces" % (len(pieces) // 20)) print("Torrent piece length = %d" % int(piece_length)) # print("Torrent has %d bytes" % length) return Torrent(urls, info, piece_length, pieces, target)
async def main(): # torrent = Torrent('Dua Lipa - Future Nostalgia (2020) MP3 [320 kbps]-[rarbg.to].torrent') # torrent = Torrent('flagfromserver.torrent') torrent = Torrent('ubuntu-19.10-desktop-amd64.iso.torrent') tracker = Tracker(torrent) await tracker.send_announce_request(0, 0, 'started') await tracker.close()
def search(term): request = create_search_request(term) print "fetcihing " + request.url html = BeautifulSoup(request.text) results_div = html.find(lambda e: e.name == 'div' and e.has_attr('class') and e['class'] == ['results']) torrents = [] for item in results_div.find_all('dl'): try: new_torrent = Torrent() new_torrent.name = item.dt.a.text new_torrent.rel_url = item.dt.a['href'].replace('/', '') age_span = item.dd.find(lambda e: e.name == 'span' and e.has_attr( 'class') and e['class'] == ['a']).span new_torrent.date_exact = age_span['title'] new_torrent.date_relative = age_span.text new_torrent.size = item.dd.find( lambda e: e.name == 'span' and e.has_attr('class') and e[ 'class'] == ['s']).text new_torrent.seeders = item.dd.find( lambda e: e.name == 'span' and e.has_attr('class') and e[ 'class'] == ['u']).text torrents.append(new_torrent) except Exception, e: print e continue
def getTorrentIfAny(config): eztvSearchString = (config.tvShow).replace(' ', '_').lower() raw_html = simple_get('https://eztv.io/search/' + eztvSearchString) html = BeautifulSoup(raw_html, 'html.parser') torrents = [] expr = re.compile(config.tvShow + ' ' + config.episode, re.I) for p in html.select('tr.forum_header_border'): row = p.select('td') title = row[1].text.strip() magnet = row[2].find('a', 'magnet').get('href') if (bool(expr.match(title))): t = Torrent(config.episode, title, row[3].text, magnet, row[4].text, int(row[5].text.replace(',', ''))) torrents.append(t) if len(torrents) == 0: quit() # The file with more seeds that is bigger that 1Gb torrentsBigger1G = [t for t in torrents if t.size_in_bytes > 1000000000] torrents = torrentsBigger1G if len(torrents) == 0: quit() sortedTorrents = sorted(torrents, reverse=True) theTorrent = sortedTorrents[0] #print('\n'.join(map(str, sortedTorrents))) filename = getFilenameFromMagnet(theTorrent.magnet) theTorrent.setFile(filename) return theTorrent
def main(argv): if len(argv) != 2: print "Usage: %s <torrent-file>" % argv[0] sys.exit(1) inputs = [] outputs = [] tfile = Torrent(argv[1]) tfile.print_info() my_id = "xxxSpicyboiiixx%20d" % random.randint(0, 99999) tracker = Tracker(tfile.tracker_url) tracker.connect(tfile, my_id) brain = Brain({ "ip": "localhost", "port": 1050, "id": my_id }, tfile, tracker) if brain.is_complete(): print "Aborting" else: print "Received list of peers: %r" % tracker.peers brain.add_peers() brain.connect_all(3) brain.run() print "Downloaded a torrent"
def main(): parser = argparse.ArgumentParser() parser.add_argument('torrent', help='the .torrent to download') parser.add_argument('-v', '--verbose', action='store_true', help='enable verbose output') args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.INFO) loop = asyncio.get_event_loop() client = TorrentClient(Torrent(args.torrent)) task = loop.create_task(client.start()) def signal_handler(*_): logging.info('Exiting, please wait until everything is shutdown...') client.stop() task.cancel() signal.signal(signal.SIGINT, signal_handler) try: loop.run_until_complete(task) except CancelledError: logging.warning('Event loop was canceled')
def main(argv): if len(argv) != 2: print "Usage: %s <torrent-file>" % argv[0] sys.exit(1) inputs = [] outputs = [] print "~~~ Starting BitTorrent Client ~~~" print "----------------------------------" # Read & parse torrent file tfile = Torrent(argv[1]) tfile.print_info() #My ID has to be exactly 20 characters but each ID should be random my_id = "-SilviaLearnsBT%05d"%random.randint(0,99999) # Setup tracker connection tracker = Tracker(tfile.tracker_url) tracker.connect(tfile, my_id) # Setup Brain, the dispatcher brain = Brain({ "ip": "localhost", "port": 1050, "id": my_id}, tfile, tracker) if brain.is_complete(): print "Aborting. I have the entire file!" else: print "Received list of peers from tracker: %r" % tracker.peers brain.add_peers() brain.connect_all(3) brain.run() print "~~~ GROOVY! You successfully downloaded a torrent ~~~"
def get_torrent_info(page_url): """ get a torrent's info from kickass torrent page info includes: title, magnet link, torrent link, size, seeders, leechers, update time and upload time return a Torrent object """ # response = session.get(page_url) response = requests.get(page_url, verify=VERIFY) soup = bs4.BeautifulSoup(response.text, "html.parser") try: c_title_and_size = soup.select('span.folderopen')[0].text.strip() size_beg_index = c_title_and_size.index('(Size: ') c_title = c_title_and_size[:size_beg_index].strip() c_size = c_title_and_size[size_beg_index:] c_size = c_size[c_size.index(' ') + 1:-1] # remove the '(Size: ' and ')' c_magnet = soup.select('a[href^="magnet:"]')[0].attrs.get('href') c_torrent_cache = u'http:' + soup.select( 'a[href^="//torcache.net"]')[0].attrs.get('href') c_seeders = soup.select('div.seedBlock > strong')[0].text c_leechers = soup.select('div.leechBlock > strong')[0].text c_update_time = soup.select('time.timeago')[0].text c_upload_time = soup.select('time.timeago')[1].text torrent = Torrent(title=c_title, magnet=c_magnet, torrent_cache=c_torrent_cache, size=c_size, seeders=c_seeders, leechers=c_leechers, update_time=c_update_time, upload_time=c_upload_time) # filter function to remove non-ascii characters from showing up in terminal print termcolor.colored( 'Processing torrent info at {} succeeded.'.format( filter(lambda x: x in string.printable, page_url)), 'green') return torrent except IndexError: # torrent page has been deleted print termcolor.colored('Torrent at {} deleted!'.format(page_url), 'red') return Torrent(title='Deleted!')
def conv_json_torrents(self): """Util function to normalize data""" if self.data['Torrents']: torrents = self.data['Torrents'] for t in torrents: if 'RemasterTitle' not in t: t['RemasterTitle'] = '' self.data['Torrents'] = [Torrent(data=t) for t in torrents]
def get_torrent(self, id): """ Returns a TorrentGroup for the passed ID, associated with this API object. """ id = int(id) if id in self.cached_torrents.keys(): return self.cached_torrents[id] else: return Torrent(id, self)
class Main: parser = argparse.ArgumentParser() parser.add_argument('torrent', help='.torrent file') args = parser.parse_args() loop = asyncio.get_event_loop() client = Client(Torrent(args.torrent)) task = loop.create_task(client.start()) loop.run_until_complete(task)
def add_torrent(self, tor_file_path): """Give the Client at Torrent to use.""" if self._torrent: raise ClientError('Client already has a Torrent') else: self._torrent = Torrent(tor_file_path) self.unrequested_pieces = piece_factory(self._torrent.length, self._torrent.piece_length, self._torrent.piece_hashes)
def parse_raw_page_for_torrents(self, content): soup = BeautifulSoup(content, 'html.parser') content_searchResult = soup.body.find(id='searchResult') if content_searchResult is None: logging.info('No torrents found for the search criteria.') return None listElements = content_searchResult.tr torrentWrapper = self.removeHeader(listElements) torrents_found = [] for torrentElement in torrentWrapper.find_all_next('td'): if torrentElement.find_all("div", class_='detName'): name = torrentElement.find('a', class_='detLink').get_text() url = torrentElement.find('a', class_='detLink')['href'] magnet = torrentElement.find(href=self.has_magnet) uploader = torrentElement.find('a', class_='detDesc') if uploader is None: uploader = torrentElement.find('i') uploader = uploader.get_text() info_text = torrentElement.find('font', class_='detDesc').get_text() date = return_re_match( info_text, r"(\d+\-\d+\s\d+)|(Y\-day\s\d{2}\:\d{2})") size = return_re_match(info_text, r"(\d+(\.\d+)?\s[a-zA-Z]+)") byteSize = deHumansize(size) # COULD NOT FIND HREF! if (magnet is None): logger.warning('Could not find magnet for {}'.format(name)) continue seed_and_leech = torrentElement.find_all_next( attrs={"align": "right"}) seed = seed_and_leech[0].get_text() leech = seed_and_leech[1].get_text() torrent = Torrent(name, magnet['href'], byteSize, uploader, date, seed, leech, url) torrents_found.append(torrent) else: logger.warning( 'Could not find torrent element on thepiratebay webpage.') continue logging.info('Found %s torrents for given search criteria.' % len(torrents_found)) return torrents_found
def get_peers(metainfo): '''Input: metainfo file (.torrent file) Output: a list of peer_ids (strings) returned from the tracker Calls methods to send an http request to the tracker, parse the returned result message and return a list of peer_ids ''' torrentObj = Torrent(metainfo) r = requests.get(torrentObj.announce_url, params=torrentObj.param_dict) peers = parse_response_from_tracker(r) return peers, torrentObj
def setUp(self): self.torrent = Torrent('data/ubuntu.torrent') self.pg = PeersGetter(self.torrent) self.pg.request_peers = mock.Mock( return_value={ b'complete': 389, b'peers': b'.\xa6\xbc\xe2\xa7\xabI\xe1\xc8\x1c\x1a\xe1^\x17\xd3K\xc8\x89\xd43\x9f\x81~\xafQ\xa9\x96:\xc8\xd5\x94e\x94\xbd\xf0PY_&\xb8\xc8\xd5G\xaf1\x11\xe3\x88[\xca(s\xc78\xc6\x1bJ\xd0y\xb8\x1f\xd0)\x9e\x1a\xe1X\xc6\\/\x1a\xe1G\xf1\xff\xbc\xd1.\xc1Gp\x83\x1b:\x05\x87\xb7\xe2\x82e%\xbbp\x9a\xc8\xd5XP((\xc8\xd5T\xec"#\xcb\x1fm\xcd\xc8\xa1\xd6\xd8>\xd2\xc34\xc8\xd5\xb0\x1fx.\xdd\x1eU\x11\x1ds\xee\x80\xd9\x0b\xb6\x04\xc8\xd5%\xbb\x05\xba\xaf\xc8\xc3\x9ai\x85\xc8\xd5l\x13kV\xe1\n_\xd3\xcd\x97\xc8\xd5\xc3\x9a\r\xa7\xc8\nd#\xec\xfe\xc3P\xbc\x1b\xbd-\xc8\xd5\x05\xc4Xj\xaf\xc8K\x98x\xb5\xc00\xbck\xa4\xc2\x1a\xe1[\xd2W\xcd\xc8\xd5Q\x02S~\xc8\xd5\xb9\x15\xd8\x9djmO\x8d\xad\xad\x9c\xddO\x8d\xabQ,\xefO\x8d\xae\'\xb0\xd3O\x8d\xad\x8et&_\x8d\x1c\xb5\x8f\x06O\x8d\xabI\xe5\x01O\x8d\xa0I\xbb\x06O\x8d\xad\xa3A\x95_\x8d\x1c\xb1\xb7\x18O\x8d\xabDz\x10_\x8d\x1c\xb4\xe6y_\x8d\x1c\xb3 \x90O\x8d\xabE\xee@O\x8d\xa0KA@', b'incomplete': 60, b'interval': 1800 })
def main(): # make sure a file name is provided if len(sys.argv) < 2: error_quit("File name not provided") ## attempt to decode torrent torrent = None try: torrent = Torrent(sys.argv[1]) except OSError as e: error_quit(f"Could not open torrent file - {e}") except BEncodeDecodeError as e: error_quit(f"Could not decode torrent file - {e}") except Exception as e: error_quit(f"Unexpected error! - {e}") ## attempt to contact tracker tracker = Tracker(torrent, ID, PORT) try: response = tracker.request() except TrackerParseError as e: error_quit(f"Tracker Parsing error - {e}") except URLError as e: error_quit(f"Could not connect to tracker: {e}") except BEncodeDecodeError as e: error_quit(f"Malformed tracker response: {e}") except Exception as e: error_quit(f"Unexpected error! - {e}") # make sure the peers blob is correct if len(response["peers"]) % 6 != 0: error_quit("Malformed peers list") # list of raw peer IPs and port raw_peers = [ response["peers"][i:i + 6] for i in range(0, len(response["peers"]), 6) ] # peers we are attempting to request pieces from seed_peers = [] for peer_bytes in raw_peers: try: seed_peers.append(Peer(peer_bytes)) except ValueError as e: print(f"Could not parse {peer_bytes}'s ip: {e}") asyncio.run(do_connect(seed_peers, torrent))
def _load_torrents(self): """load torrents in default dir, seeding in default period""" log.debug("load torrents from %s..." % TORRENT_DIR) from vtrans import Vtrans vtrans = Vtrans() for file in os.listdir(TORRENT_DIR): if file.endswith(".torrent"): log.debug("loading %s" % file) file_path = os.path.join(TORRENT_DIR, file) torrent = Torrent(file_path, SAVE_DIR, SEED_TIME) vtrans.add_torrent(torrent) log.debug("load torrents end.")
def main(): torrent = Torrent('data/ubuntu.torrent') td = deepcopy(torrent.torrent_file_dict) td[b'info'][b'pieces'] = '20 byte pieces hashes go here...' pp(td) print('Number of pieces in the file:', torrent.num_pieces) print('Size of download in bytes: ', torrent.get_download_length()) input() peers_info = PeersGetter(torrent).parse_peers() writers = [] readers = [] peers_connected_to_count = 0 # Build connected peers for peer_info in peers_info: if peers_connected_to_count > 3: break peers_connected_to_count += 1 peer = Peer(torrent, peer_info=peer_info) peer.connect() if peer.is_connected: writers.append(peer) readers.append(peer) while not torrent.is_download_finished(): # print( # 'Downloading... Writers: {} Readers: {}'.format( # len(readers), len(writers) # ) # ) to_read, to_write, errors = select.select(readers, writers, readers) for peer in to_read: peer.read() for peer in to_write: peer.write() for peer in errors: readers.remove(peer) writers.remove(peer)
def make_test_files(torrent_data, torrent_info, download_dir, number_of_files): t = Torrent(torrent_data, torrent_info, download_dir, None) files = [] main_file_wrapper = file_manager.FileWrapper(torrent=t, file_suffix="") main_file_wrapper.create_file_or_return_hashes() for i in range(int(number_of_files)): fw = file_manager.FileWrapper(torrent=t, file_suffix=".{}".format(i)) fw.create_file_or_return_hashes() files.append(fw) for p in t._pieces: data = main_file_wrapper.read_block(p.index, 0, t.piece_length(p.index)) if p.sha1hash == hashlib.sha1(data).digest(): random.choice(files).write_piece(p.index, data)
def get_peers(metainfo): '''Input: metainfo file (.torrent file) Output: a list of peer_ids (strings) returned from the tracker Calls methods to send an http request to the tracker, parse the returned result message and return a list of peer_ids ''' torrentObj = Torrent(metainfo) #http://pow7.com:80/announce #socket.create_connection(('pow7.com', 80 ), timeout=2) r = requests.get(torrentObj.announce_url, params=torrentObj.param_dict) #print 'r.content: '+r.content #print 'r.text: '+r.text peers = parse_response_from_tracker(r) return peers, torrentObj
async def download(torrent_file: str, download_location: str): """ Download coroutine to start a download by accepting a torrent file and download location :param torrent_file: torrent file to be downloaded :param download_location: location to download it to """ torrent = Torrent(torrent_file) torrent_writer = FileSaver(download_location, torrent) session = DownloadSession( torrent, torrent_writer.get_received_pieces_queue()) # FILESAVER done_pieces = 0 while done_pieces < torrent.number_of_pieces: await torrent.get_peers() peers_info = list(set(torrent.peers)) seen_peers = set() peers = [Peer(session, host, port) for host, port in peers_info] seen_peers.update([str(p) for p in peers]) print('[Peers]: {} {}'.format(len(seen_peers), seen_peers)) for peer in peers: peer.inflight_requests = 0 print("STARTING") await (asyncio.gather(*[peer.download() for peer in peers])) print("received", len(session.received_pieces)) print("progress", len(session.pieces_in_progress)) pprint(session.pieces_in_progress) print("resetting session.pieces_in_progress") session.pieces_in_progress = {} print("alive peers") peers = [peer for peer in peers if peer.have_pieces is not None] print("bitfields") pprint([(peer, peer.have_pieces) for peer in peers]) done_pieces = len(session.received_pieces) print("Done pieces:", done_pieces) print("RESTARTING") return True
def search(self, query): request = self.search_params['request'] response = self.session.get(self.domain + request['url_template'].format(query)) response = BeautifulSoup(response.text, "html.parser") rows = response.select(self.search_params['rows']) pages_params = self.search_params['pages'] pages = list( map( lambda x: x['href'], response.select(pages_params['selector']) [pages_params['start']:pages_params['end']])) for pg in pages: response = self.session.get(self.domain + pg) response = BeautifulSoup(response.text, "html.parser") rows += response.select(self.search_params['rows']) torrents = [] for row in rows: try: name = row.select_one(self.search_params['name']).text if self.search_params['size']['attribute'] is not None: size = row.select(self.search_params['size']['selector'])[ self.search_params['size']['num']][ self.search_params['size']['attribute']] else: size = row.select(self.search_params['size']['selector'])[ self.search_params['size']['num']].text link = row.select_one(self.search_params['link'])['href'] if self.search_params['magnet'] is not None: magnet = row.select_one( self.search_params['magnet'])['href'] else: magnet = None seeds = row.select_one(self.search_params['seeds']).text leeches = row.select_one(self.search_params['leeches']).text if int(seeds) > 0: torrents.append( Torrent(self, name, size, link, magnet, seeds, leeches)) except AttributeError: pass return torrents
def __init__(self, role=SEEDER): """ Class constructor :param self._ip: used when need to use the ip assigned by LAN """ # get local ip self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.s.connect(("8.8.8.8", 80)) self.s.getsockname()[0] self._ip = self.s.getsockname()[0] # self._ip = socket.gethostbyname(socket.gethostname()) self.server = Server( self._ip, self.SERVER_PORT) # inherits methods from the server self.id = uuid.uuid4() # creates unique id for the peer self.role = role self.torrent = Torrent("age.torrent") self.tracker = None
def handle_torrent_local(tfilename, fake_announce_url): ''' Spracovanie parametru -t (-a). @param tfilename Cesta k torrentu @param fake_announce_url URL @return True ak je spracovanie uspesne, inak False ''' rslt = False tpath = abspath(tfilename) torrent = Torrent(abspath(tfilename)) if torrent: rslt = write_peerlist(tpath, \ abspath("{}.peerlist".format(torrent.info_hash)), \ fake_announce_url) return rslt
def __init__(self, role=PEER, server_ip_address='127.0.0.1'): """ Class constructor :param server_ip_address: used when need to use the ip assigned by LAN """ self.server_ip_address = server_ip_address self.id = uuid.uuid4() # creates unique id for the peer self.role = role # Commented out from this lab b/c not needed self.DHT = None self.torrent = Torrent(self.TORRENT_PATH) self.message = Message(self.id, self.torrent.create_info_hash()) # peer_id, torrent, message, server_ip_address="127.0.0.1", server_port=12000 self.server = Server(peer_id=self.id, torrent=self.torrent, message=self.message, server_ip_address=server_ip_address, server_port=self.SERVER_PORT) self.tracker = None
def run(log_level, torrent_path, listening_port, download_dir): if log_level: log_level = getattr(logging, log_level.upper()) else: log_level = getattr(logging, "WARNING") logfile = "tmp/{}.log".format( listening_port) # TODO - directory shouldn't be hardcoded logging.basicConfig( filename=logfile, level=log_level, format= "%(asctime)s %(levelname)s %(filename)s:%(lineno)d `%(funcName)s` -- %(message)s", ) torrent_data, torrent_info = read_torrent_file(torrent_path) download_dir = download_dir if download_dir else os.path.dirname( os.path.abspath(__file__)) port = int(listening_port) if listening_port else None t = Torrent(torrent_data, torrent_info, download_dir, port) engine.run(t)
async def download(t_file : str, download_loc : str, loop=None): '''Entry point for client, initializes `Peers` and `DownloadSession` according to configureation present in `t_file` which is the .torrent file and saves the downloaded file to `download_loc` directory''' torrent = Torrent(t_file) LOG.info('Torrent : {}'.format(torrent)) torrent_writer = FileSaver(download_loc, torrent) session = DownloadSession(torrent, torrent_writer.get_received_blocks_queue()) tracker = Tracker(torrent) # implement Tracker class peer_info = await tracker.get_peers() seen_peers = set() peers = [Peer(session, host, port) for host, port in peer_info] seen_peers.update([str(p) for p in peers]) LOG.info('Peers : {}'.format(seen_peers)) asyncio.gather([peer.download() for peer in peers])
def parse_td(row): name_tag = row.find('td', class_='coll-1') name_contents = name_tag.contents name = name_contents[0].text + name_contents[1].text page_url = row.find('td', class_='coll-1').findAll('a')[1].attrs['href'] id_ = page_url.split('/')[2] page_url = self.domain + page_url seeds = row.find('td', class_='coll-2 seeds').text leeches = row.find('td', class_='coll-3 leeches').text date = row.find('td', class_='coll-date').text size = str(row.find('td', class_='coll-4').contents[0]) magnet_link = extract_magnet_link(page_url) return Torrent(id=id_, name=name, seeds=seeds, leeches=leeches, date=date, size=size, url=page_url, magnet=magnet_link)